/projects/tomcat-7.0.2/java/org/apache/catalina/connector/Request.java
Java | 1815 lines | 795 code | 378 blank | 642 comment | 141 complexity | df02a215293e28035e7961909d863dda MD5 | raw file
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.catalina.connector;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.UnsupportedEncodingException;
- import java.security.Principal;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.Enumeration;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- import java.util.TimeZone;
- import java.util.TreeMap;
- import javax.security.auth.Subject;
- import javax.servlet.AsyncContext;
- import javax.servlet.DispatcherType;
- import javax.servlet.FilterChain;
- 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.ServletResponse;
- import javax.servlet.SessionTrackingMode;
- 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.apache.catalina.Context;
- import org.apache.catalina.Globals;
- import org.apache.catalina.Host;
- import org.apache.catalina.Manager;
- import org.apache.catalina.Realm;
- import org.apache.catalina.Session;
- import org.apache.catalina.Wrapper;
- import org.apache.catalina.core.ApplicationSessionCookieConfig;
- import org.apache.catalina.core.AsyncContextImpl;
- import org.apache.catalina.core.ApplicationPart;
- import org.apache.catalina.deploy.LoginConfig;
- import org.apache.catalina.realm.GenericPrincipal;
- import org.apache.catalina.util.Enumerator;
- import org.apache.catalina.util.ParameterMap;
- import org.apache.catalina.util.StringParser;
- import org.apache.coyote.ActionCode;
- import org.apache.tomcat.util.buf.B2CConverter;
- import org.apache.tomcat.util.buf.ByteChunk;
- import org.apache.tomcat.util.buf.MessageBytes;
- import org.apache.tomcat.util.buf.StringCache;
- import org.apache.tomcat.util.http.Cookies;
- import org.apache.tomcat.util.http.FastHttpDateFormat;
- import org.apache.tomcat.util.http.Parameters;
- import org.apache.tomcat.util.http.ServerCookie;
- import org.apache.tomcat.util.http.fileupload.FileItem;
- import org.apache.tomcat.util.http.fileupload.FileUploadBase;
- import org.apache.tomcat.util.http.fileupload.FileUploadException;
- import org.apache.tomcat.util.http.fileupload.FileUploadBase.InvalidContentTypeException;
- import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
- import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
- import org.apache.tomcat.util.http.mapper.MappingData;
- import org.apache.tomcat.util.res.StringManager;
- /**
- * Wrapper object for the Coyote request.
- *
- * @author Remy Maucherat
- * @author Craig R. McClanahan
- * @version $Id: Request.java 981190 2010-08-01 09:52:35Z markt $
- */
- public class Request
- implements HttpServletRequest {
- // ----------------------------------------------------------- Constructors
- static {
- // Ensure that classes are loaded for SM
- new StringCache.ByteEntry();
- new StringCache.CharEntry();
- }
- public Request() {
- formats[0].setTimeZone(GMT_ZONE);
- formats[1].setTimeZone(GMT_ZONE);
- formats[2].setTimeZone(GMT_ZONE);
- }
- // ------------------------------------------------------------- Properties
- /**
- * Coyote request.
- */
- protected org.apache.coyote.Request coyoteRequest;
- /**
- * Set the Coyote request.
- *
- * @param coyoteRequest The Coyote request
- */
- public void setCoyoteRequest(org.apache.coyote.Request coyoteRequest) {
- this.coyoteRequest = coyoteRequest;
- inputBuffer.setRequest(coyoteRequest);
- }
- /**
- * Get the Coyote request.
- */
- public org.apache.coyote.Request getCoyoteRequest() {
- return (this.coyoteRequest);
- }
- // ----------------------------------------------------- Variables
- protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
- /**
- * The string manager for this package.
- */
- protected static final StringManager sm =
- StringManager.getManager(Constants.Package);
- /**
- * The set of cookies associated with this Request.
- */
- protected Cookie[] cookies = null;
- /**
- * The set of SimpleDateFormat formats to use in getDateHeader().
- *
- * Notice that because SimpleDateFormat is not thread-safe, we can't
- * declare formats[] as a static variable.
- */
- protected SimpleDateFormat formats[] = {
- new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
- new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
- new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
- };
- /**
- * The default Locale if none are specified.
- */
- protected static Locale defaultLocale = Locale.getDefault();
- /**
- * The attributes associated with this Request, keyed by attribute name.
- */
- protected HashMap<String, Object> attributes =
- new HashMap<String, Object>();
- /**
- * Flag that indicates if SSL attributes have been parsed to improve
- * performance for applications (usually frameworks) that make multiple
- * calls to {@link Request#getAttributeNames()}.
- */
- protected boolean sslAttributesParsed = false;
- /**
- * List of read only attributes for this Request.
- */
- private HashMap<String,Object> readOnlyAttributes =
- new HashMap<String,Object>();
- /**
- * The preferred Locales associated with this Request.
- */
- protected ArrayList<Locale> locales = new ArrayList<Locale>();
- /**
- * Internal notes associated with this request by Catalina components
- * and event listeners.
- */
- private transient HashMap<String, Object> notes = new HashMap<String, Object>();
- /**
- * Authentication type.
- */
- protected String authType = null;
-
- /**
- * Associated event.
- */
- protected CometEventImpl event = null;
-
- /**
- * Comet state
- */
- protected boolean comet = false;
-
-
- /**
- * The current dispatcher type.
- */
- protected DispatcherType internalDispatcherType = null;
- /**
- * The associated input buffer.
- */
- protected InputBuffer inputBuffer = new InputBuffer();
- /**
- * ServletInputStream.
- */
- protected CoyoteInputStream inputStream =
- new CoyoteInputStream(inputBuffer);
- /**
- * Reader.
- */
- protected CoyoteReader reader = new CoyoteReader(inputBuffer);
- /**
- * Using stream flag.
- */
- protected boolean usingInputStream = false;
- /**
- * Using writer flag.
- */
- protected boolean usingReader = false;
- /**
- * User principal.
- */
- protected Principal userPrincipal = null;
- /**
- * Session parsed flag.
- */
- protected boolean sessionParsed = false;
- /**
- * Request parameters parsed flag.
- */
- protected boolean parametersParsed = false;
- /**
- * Cookies parsed flag.
- */
- protected boolean cookiesParsed = false;
- /**
- * Secure flag.
- */
- protected boolean secure = false;
-
- /**
- * The Subject associated with the current AccessControllerContext
- */
- protected transient Subject subject = null;
- /**
- * Post data buffer.
- */
- protected static int CACHED_POST_LEN = 8192;
- protected byte[] postData = null;
- /**
- * Hash map used in the getParametersMap method.
- */
- protected ParameterMap<String, String[]> parameterMap = new ParameterMap<String, String[]>();
- /**
- * The parts, if any, uploaded with this request.
- */
- protected Collection<Part> parts = null;
-
-
- /**
- * The exception thrown, if any when parsing the parts.
- */
- protected Exception partsParseException = null;
-
-
- /**
- * The currently active session for this request.
- */
- protected Session session = null;
- /**
- * The current request dispatcher path.
- */
- protected Object requestDispatcherPath = null;
- /**
- * Was the requested session ID received in a cookie?
- */
- protected boolean requestedSessionCookie = false;
- /**
- * The requested session ID (if any) for this request.
- */
- protected String requestedSessionId = null;
- /**
- * Was the requested session ID received in a URL?
- */
- protected boolean requestedSessionURL = false;
- /**
- * Was the requested session ID obtained from the SSL session?
- */
- protected boolean requestedSessionSSL = false;
- /**
- * Parse locales.
- */
- protected boolean localesParsed = false;
- /**
- * The string parser we will use for parsing request lines.
- */
- private StringParser parser = new StringParser();
- /**
- * Local port
- */
- protected int localPort = -1;
- /**
- * Remote address.
- */
- protected String remoteAddr = null;
- /**
- * Remote host.
- */
- protected String remoteHost = null;
-
- /**
- * Remote port
- */
- protected int remotePort = -1;
-
- /**
- * Local address
- */
- protected String localAddr = null;
-
- /**
- * Local address
- */
- protected String localName = null;
-
- /**
- * AsyncContext
- */
- protected volatile AsyncContextImpl asyncContext = null;
-
- protected Boolean asyncSupported = null;
-
-
- /**
- * Path parameters
- */
- protected Map<String,String> pathParameters = new HashMap<String, String>();
- // --------------------------------------------------------- Public Methods
-
- protected void addPathParameter(String name, String value) {
- pathParameters.put(name, value);
- }
- protected String getPathParameter(String name) {
- return pathParameters.get(name);
- }
- public void setAsyncSupported(boolean asyncSupported) {
- this.asyncSupported = Boolean.valueOf(asyncSupported);
- }
- /**
- * Release all object references, and initialize instance variables, in
- * preparation for reuse of this object.
- */
- public void recycle() {
- context = null;
- wrapper = null;
- internalDispatcherType = null;
- requestDispatcherPath = null;
- comet = false;
- if (event != null) {
- event.clear();
- event = null;
- }
-
- authType = null;
- inputBuffer.recycle();
- usingInputStream = false;
- usingReader = false;
- userPrincipal = null;
- subject = null;
- sessionParsed = false;
- parametersParsed = false;
- parts = null;
- partsParseException = null;
- cookiesParsed = false;
- locales.clear();
- localesParsed = false;
- secure = false;
- remoteAddr = null;
- remoteHost = null;
- remotePort = -1;
- localPort = -1;
- localAddr = null;
- localName = null;
- attributes.clear();
- sslAttributesParsed = false;
- notes.clear();
- cookies = null;
- if (session != null) {
- session.endAccess();
- }
- session = null;
- requestedSessionCookie = false;
- requestedSessionId = null;
- requestedSessionURL = false;
- if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
- parameterMap = new ParameterMap<String, String[]>();
- } else {
- parameterMap.setLocked(false);
- parameterMap.clear();
- }
- mappingData.recycle();
- if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
- if (facade != null) {
- facade.clear();
- facade = null;
- }
- if (inputStream != null) {
- inputStream.clear();
- inputStream = null;
- }
- if (reader != null) {
- reader.clear();
- reader = null;
- }
- }
-
- asyncSupported = null;
- if (asyncContext!=null) asyncContext.recycle();
- asyncContext = null;
- pathParameters.clear();
- }
- protected boolean isProcessing() {
- return coyoteRequest.isProcessing();
- }
- /**
- * Clear cached encoders (to save memory for Comet requests).
- */
- public void clearEncoders() {
- inputBuffer.clearEncoders();
- }
-
- /**
- * Clear cached encoders (to save memory for Comet requests).
- */
- public boolean read()
- throws IOException {
- return (inputBuffer.realReadBytes(null, 0, 0) > 0);
- }
-
- // -------------------------------------------------------- Request Methods
- /**
- * Associated Catalina connector.
- */
- protected Connector connector;
- /**
- * Return the Connector through which this Request was received.
- */
- public Connector getConnector() {
- return this.connector;
- }
- /**
- * Set the Connector through which this Request was received.
- *
- * @param connector The new connector
- */
- public void setConnector(Connector connector) {
- this.connector = connector;
- }
- /**
- * Associated context.
- */
- protected Context context = null;
- /**
- * Return the Context within which this Request is being processed.
- */
- public Context getContext() {
- return this.context;
- }
- /**
- * Set the Context within which this Request is being processed. This
- * must be called as soon as the appropriate Context is identified, because
- * it identifies the value to be returned by <code>getContextPath()</code>,
- * and thus enables parsing of the request URI.
- *
- * @param context The newly associated Context
- */
- public void setContext(Context context) {
- this.context = context;
- }
- /**
- * Filter chain associated with the request.
- */
- protected FilterChain filterChain = null;
- /**
- * Get filter chain associated with the request.
- */
- public FilterChain getFilterChain() {
- return this.filterChain;
- }
- /**
- * Set filter chain associated with the request.
- *
- * @param filterChain new filter chain
- */
- public void setFilterChain(FilterChain filterChain) {
- this.filterChain = filterChain;
- }
- /**
- * Return the Host within which this Request is being processed.
- */
- public Host getHost() {
- return ((Host) mappingData.host);
- }
- /**
- * Set the Host within which this Request is being processed. This
- * must be called as soon as the appropriate Host is identified, and
- * before the Request is passed to a context.
- *
- * @param host The newly associated Host
- */
- public void setHost(Host host) {
- mappingData.host = host;
- }
- /**
- * Descriptive information about this Request implementation.
- */
- protected static final String info =
- "org.apache.coyote.catalina.CoyoteRequest/1.0";
- /**
- * Return descriptive information about this Request implementation and
- * the corresponding version number, in the format
- * <code><description>/<version></code>.
- */
- public String getInfo() {
- return info;
- }
- /**
- * Mapping data.
- */
- protected MappingData mappingData = new MappingData();
- /**
- * Return mapping data.
- */
- public MappingData getMappingData() {
- return mappingData;
- }
- /**
- * The facade associated with this request.
- */
- protected RequestFacade facade = null;
- /**
- * Return the <code>ServletRequest</code> for which this object
- * is the facade. This method must be implemented by a subclass.
- */
- public HttpServletRequest getRequest() {
- if (facade == null) {
- facade = new RequestFacade(this);
- }
- return facade;
- }
- /**
- * The response with which this request is associated.
- */
- protected org.apache.catalina.connector.Response response = null;
- /**
- * Return the Response with which this Request is associated.
- */
- public org.apache.catalina.connector.Response getResponse() {
- return this.response;
- }
- /**
- * Set the Response with which this Request is associated.
- *
- * @param response The new associated response
- */
- public void setResponse(org.apache.catalina.connector.Response response) {
- this.response = response;
- }
- /**
- * Return the input stream associated with this Request.
- */
- public InputStream getStream() {
- if (inputStream == null) {
- inputStream = new CoyoteInputStream(inputBuffer);
- }
- return inputStream;
- }
- /**
- * URI byte to char converter (not recycled).
- */
- protected B2CConverter URIConverter = null;
- /**
- * Return the URI converter.
- */
- protected B2CConverter getURIConverter() {
- return URIConverter;
- }
- /**
- * Set the URI converter.
- *
- * @param URIConverter the new URI converter
- */
- protected void setURIConverter(B2CConverter URIConverter) {
- this.URIConverter = URIConverter;
- }
- /**
- * Associated wrapper.
- */
- protected Wrapper wrapper = null;
- /**
- * Return the Wrapper within which this Request is being processed.
- */
- public Wrapper getWrapper() {
- return this.wrapper;
- }
- /**
- * Set the Wrapper within which this Request is being processed. This
- * must be called as soon as the appropriate Wrapper is identified, and
- * before the Request is ultimately passed to an application servlet.
- * @param wrapper The newly associated Wrapper
- */
- public void setWrapper(Wrapper wrapper) {
- this.wrapper = wrapper;
- }
- // ------------------------------------------------- Request Public Methods
- /**
- * Create and return a ServletInputStream to read the content
- * associated with this Request.
- *
- * @exception IOException if an input/output error occurs
- */
- public ServletInputStream createInputStream()
- throws IOException {
- if (inputStream == null) {
- inputStream = new CoyoteInputStream(inputBuffer);
- }
- return inputStream;
- }
- /**
- * Perform whatever actions are required to flush and close the input
- * stream or reader, in a single operation.
- *
- * @exception IOException if an input/output error occurs
- */
- public void finishRequest() throws IOException {
- // The reader and input stream don't need to be closed
- }
- /**
- * Return the object bound with the specified name to the internal notes
- * for this request, or <code>null</code> if no such binding exists.
- *
- * @param name Name of the note to be returned
- */
- public Object getNote(String name) {
- return notes.get(name);
- }
- /**
- * Return an Iterator containing the String names of all notes bindings
- * that exist for this request.
- */
- public Iterator<String> getNoteNames() {
- return notes.keySet().iterator();
- }
- /**
- * Remove any object bound to the specified name in the internal notes
- * for this request.
- *
- * @param name Name of the note to be removed
- */
- public void removeNote(String name) {
- notes.remove(name);
- }
- /**
- * Bind an object to a specified name in the internal notes associated
- * with this request, replacing any existing binding for this name.
- *
- * @param name Name to which the object should be bound
- * @param value Object to be bound to the specified name
- */
- public void setNote(String name, Object value) {
- notes.put(name, value);
- }
- /**
- * Set the IP address of the remote client associated with this Request.
- *
- * @param remoteAddr The remote IP address
- */
- public void setRemoteAddr(String remoteAddr) {
- this.remoteAddr = remoteAddr;
- }
- /**
- * Set the fully qualified name of the remote client associated with this
- * Request.
- *
- * @param remoteHost The remote host name
- */
- public void setRemoteHost(String remoteHost) {
- this.remoteHost = remoteHost;
- }
- /**
- * Set the value to be returned by <code>isSecure()</code>
- * for this Request.
- *
- * @param secure The new isSecure value
- */
- public void setSecure(boolean secure) {
- this.secure = secure;
- }
- /**
- * Set the name of the server (virtual host) to process this request.
- *
- * @param name The server name
- */
- public void setServerName(String name) {
- coyoteRequest.serverName().setString(name);
- }
- /**
- * Set the port number of the server to process this request.
- *
- * @param port The server port
- */
- public void setServerPort(int port) {
- coyoteRequest.setServerPort(port);
- }
- // ------------------------------------------------- ServletRequest Methods
- /**
- * Return the specified request attribute if it exists; otherwise, return
- * <code>null</code>.
- *
- * @param name Name of the request attribute to return
- */
- public Object getAttribute(String name) {
- if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
- return (internalDispatcherType == null)
- ? DispatcherType.REQUEST
- : internalDispatcherType;
- } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
- return (requestDispatcherPath == null)
- ? getRequestPathMB().toString()
- : requestDispatcherPath.toString();
- }
-
- if (name.equals(Globals.ASYNC_SUPPORTED_ATTR)) {
- return asyncSupported;
- }
- Object attr=attributes.get(name);
- if(attr!=null)
- return(attr);
- attr = coyoteRequest.getAttribute(name);
- if(attr != null)
- return attr;
- if( isSSLAttribute(name) ) {
- coyoteRequest.action(ActionCode.ACTION_REQ_SSL_ATTRIBUTE,
- coyoteRequest);
- attr = coyoteRequest.getAttribute(Globals.CERTIFICATES_ATTR);
- if( attr != null) {
- attributes.put(Globals.CERTIFICATES_ATTR, attr);
- }
- attr = coyoteRequest.getAttribute(Globals.CIPHER_SUITE_ATTR);
- if(attr != null) {
- attributes.put(Globals.CIPHER_SUITE_ATTR, attr);
- }
- attr = coyoteRequest.getAttribute(Globals.KEY_SIZE_ATTR);
- if(attr != null) {
- attributes.put(Globals.KEY_SIZE_ATTR, attr);
- }
- attr = coyoteRequest.getAttribute(Globals.SSL_SESSION_ID_ATTR);
- if(attr != null) {
- attributes.put(Globals.SSL_SESSION_ID_ATTR, attr);
- }
- attr = coyoteRequest.getAttribute(Globals.SSL_SESSION_MGR_ATTR);
- if(attr != null) {
- attributes.put(Globals.SSL_SESSION_MGR_ATTR, attr);
- }
- attr = attributes.get(name);
- sslAttributesParsed = true;
- }
- return attr;
- }
- /**
- * Test if a given name is one of the special Servlet-spec SSL attributes.
- */
- static boolean isSSLAttribute(String name) {
- return Globals.CERTIFICATES_ATTR.equals(name) ||
- Globals.CIPHER_SUITE_ATTR.equals(name) ||
- Globals.KEY_SIZE_ATTR.equals(name) ||
- Globals.SSL_SESSION_ID_ATTR.equals(name) ||
- Globals.SSL_SESSION_MGR_ATTR.equals(name);
- }
- /**
- * Return the names of all request attributes for this Request, or an
- * empty <code>Enumeration</code> if there are none. Note that the attribute
- * names returned will only be those for the attributes set via
- * {@link #setAttribute(String, Object)}. Tomcat internal attributes will
- * not be included although they are accessible via
- * {@link #getAttribute(String)}. The Tomcat internal attributes include:
- * <ul>
- * <li>{@link Globals#DISPATCHER_TYPE_ATTR}</li>
- * <li>{@link Globals#DISPATCHER_REQUEST_PATH_ATTR}</li>
- * <li>{@link Globals#ASYNC_SUPPORTED_ATTR}</li>
- * <li>{@link Globals#CERTIFICATES_ATTR} (SSL connections only)</li>
- * <li>{@link Globals#CIPHER_SUITE_ATTR} (SSL connections only)</li>
- * <li>{@link Globals#KEY_SIZE_ATTR} (SSL connections only)</li>
- * <li>{@link Globals#SSL_SESSION_ID_ATTR} (SSL connections only)</li>
- * <li>{@link Globals#SSL_SESSION_MGR_ATTR} (SSL connections only)</li>
- * </ul>
- * The underlying connector may also expose request attributes. These all
- * have names starting with "org.apache.tomcat" and include:
- * <ul>
- * <li>org.apache.tomcat.sendfile.support</li>
- * <li>org.apache.tomcat.comet.support</li>
- * <li>org.apache.tomcat.comet.timeout.support</li>
- * </ul>
- * Connector implementations may return some, all or none of these
- * attributes and may also support additional attributes.
- */
- public Enumeration<String> getAttributeNames() {
- if (isSecure() && !sslAttributesParsed) {
- getAttribute(Globals.CERTIFICATES_ATTR);
- }
- return new Enumerator<String>(attributes.keySet(), true);
- }
- /**
- * Return the character encoding for this Request.
- */
- public String getCharacterEncoding() {
- return coyoteRequest.getCharacterEncoding();
- }
- /**
- * Return the content length for this Request.
- */
- public int getContentLength() {
- return coyoteRequest.getContentLength();
- }
- /**
- * Return the content type for this Request.
- */
- public String getContentType() {
- return coyoteRequest.getContentType();
- }
- /**
- * Return the servlet input stream for this Request. The default
- * implementation returns a servlet input stream created by
- * <code>createInputStream()</code>.
- *
- * @exception IllegalStateException if <code>getReader()</code> has
- * already been called for this request
- * @exception IOException if an input/output error occurs
- */
- public ServletInputStream getInputStream() throws IOException {
- if (usingReader)
- throw new IllegalStateException
- (sm.getString("coyoteRequest.getInputStream.ise"));
- usingInputStream = true;
- if (inputStream == null) {
- inputStream = new CoyoteInputStream(inputBuffer);
- }
- return inputStream;
- }
- /**
- * Return the preferred Locale that the client will accept content in,
- * based on the value for the first <code>Accept-Language</code> header
- * that was encountered. If the request did not specify a preferred
- * language, the server's default Locale is returned.
- */
- public Locale getLocale() {
- if (!localesParsed)
- parseLocales();
- if (locales.size() > 0) {
- return locales.get(0);
- }
- return defaultLocale;
- }
- /**
- * Return the set of preferred Locales that the client will accept
- * content in, based on the values for any <code>Accept-Language</code>
- * headers that were encountered. If the request did not specify a
- * preferred language, the server's default Locale is returned.
- */
- public Enumeration<Locale> getLocales() {
- if (!localesParsed)
- parseLocales();
- if (locales.size() > 0)
- return (new Enumerator<Locale>(locales));
- ArrayList<Locale> results = new ArrayList<Locale>();
- results.add(defaultLocale);
- return new Enumerator<Locale>(results);
- }
- /**
- * Return the value of the specified request parameter, if any; otherwise,
- * return <code>null</code>. If there is more than one value defined,
- * return only the first one.
- *
- * @param name Name of the desired request parameter
- */
- public String getParameter(String name) {
- if (!parametersParsed)
- parseParameters();
- return coyoteRequest.getParameters().getParameter(name);
- }
- /**
- * Returns a <code>Map</code> of the parameters of this request.
- * Request parameters are extra information sent with the request.
- * For HTTP servlets, parameters are contained in the query string
- * or posted form data.
- *
- * @return A <code>Map</code> containing parameter names as keys
- * and parameter values as map values.
- */
- public Map<String, String[]> getParameterMap() {
- if (parameterMap.isLocked())
- return parameterMap;
- Enumeration<String> enumeration = getParameterNames();
- while (enumeration.hasMoreElements()) {
- String name = enumeration.nextElement();
- String[] values = getParameterValues(name);
- parameterMap.put(name, values);
- }
- parameterMap.setLocked(true);
- return parameterMap;
- }
- /**
- * Return the names of all defined request parameters for this request.
- */
- public Enumeration<String> getParameterNames() {
- if (!parametersParsed)
- parseParameters();
- return coyoteRequest.getParameters().getParameterNames();
- }
- /**
- * Return the defined values for the specified request parameter, if any;
- * otherwise, return <code>null</code>.
- *
- * @param name Name of the desired request parameter
- */
- public String[] getParameterValues(String name) {
- if (!parametersParsed)
- parseParameters();
- return coyoteRequest.getParameters().getParameterValues(name);
- }
- /**
- * Return the protocol and version used to make this Request.
- */
- public String getProtocol() {
- return coyoteRequest.protocol().toString();
- }
- /**
- * Read the Reader wrapping the input stream for this Request. The
- * default implementation wraps a <code>BufferedReader</code> around the
- * servlet input stream returned by <code>createInputStream()</code>.
- *
- * @exception IllegalStateException if <code>getInputStream()</code>
- * has already been called for this request
- * @exception IOException if an input/output error occurs
- */
- public BufferedReader getReader() throws IOException {
- if (usingInputStream)
- throw new IllegalStateException
- (sm.getString("coyoteRequest.getReader.ise"));
- usingReader = true;
- inputBuffer.checkConverter();
- if (reader == null) {
- reader = new CoyoteReader(inputBuffer);
- }
- return reader;
- }
- /**
- * Return the real path of the specified virtual path.
- *
- * @param path Path to be translated
- *
- * @deprecated As of version 2.1 of the Java Servlet API, use
- * <code>ServletContext.getRealPath()</code>.
- */
- @Deprecated
- public String getRealPath(String path) {
- if (context == null)
- return null;
- ServletContext servletContext = context.getServletContext();
- if (servletContext == null) {
- return null;
- }
- try {
- return (servletContext.getRealPath(path));
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- /**
- * Return the remote IP address making this Request.
- */
- public String getRemoteAddr() {
- if (remoteAddr == null) {
- coyoteRequest.action
- (ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE, coyoteRequest);
- remoteAddr = coyoteRequest.remoteAddr().toString();
- }
- return remoteAddr;
- }
- /**
- * Return the remote host name making this Request.
- */
- public String getRemoteHost() {
- if (remoteHost == null) {
- if (!connector.getEnableLookups()) {
- remoteHost = getRemoteAddr();
- } else {
- coyoteRequest.action
- (ActionCode.ACTION_REQ_HOST_ATTRIBUTE, coyoteRequest);
- remoteHost = coyoteRequest.remoteHost().toString();
- }
- }
- return remoteHost;
- }
- /**
- * Returns the Internet Protocol (IP) source port of the client
- * or last proxy that sent the request.
- */
- public int getRemotePort(){
- if (remotePort == -1) {
- coyoteRequest.action
- (ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE, coyoteRequest);
- remotePort = coyoteRequest.getRemotePort();
- }
- return remotePort;
- }
- /**
- * Returns the host name of the Internet Protocol (IP) interface on
- * which the request was received.
- */
- public String getLocalName(){
- if (localName == null) {
- coyoteRequest.action
- (ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE, coyoteRequest);
- localName = coyoteRequest.localName().toString();
- }
- return localName;
- }
- /**
- * Returns the Internet Protocol (IP) address of the interface on
- * which the request was received.
- */
- public String getLocalAddr(){
- if (localAddr == null) {
- coyoteRequest.action
- (ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE, coyoteRequest);
- localAddr = coyoteRequest.localAddr().toString();
- }
- return localAddr;
- }
- /**
- * Returns the Internet Protocol (IP) port number of the interface
- * on which the request was received.
- */
- public int getLocalPort(){
- if (localPort == -1){
- coyoteRequest.action
- (ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE, coyoteRequest);
- localPort = coyoteRequest.getLocalPort();
- }
- return localPort;
- }
-
- /**
- * Return a RequestDispatcher that wraps the resource at the specified
- * path, which may be interpreted as relative to the current request path.
- *
- * @param path Path of the resource to be wrapped
- */
- public RequestDispatcher getRequestDispatcher(String path) {
- if (context == null)
- return null;
- // If the path is already context-relative, just pass it through
- if (path == null)
- return null;
- else if (path.startsWith("/"))
- return (context.getServletContext().getRequestDispatcher(path));
- // Convert a request-relative path to a context-relative one
- String servletPath = (String) getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
- if (servletPath == null)
- servletPath = getServletPath();
- // Add the path info, if there is any
- String pathInfo = getPathInfo();
- String requestPath = null;
- if (pathInfo == null) {
- requestPath = servletPath;
- } else {
- requestPath = servletPath + pathInfo;
- }
- int pos = requestPath.lastIndexOf('/');
- String relative = null;
- if (pos >= 0) {
- relative = requestPath.substring(0, pos + 1) + path;
- } else {
- relative = requestPath + path;
- }
- return context.getServletContext().getRequestDispatcher(relative);
- }
- /**
- * Return the scheme used to make this Request.
- */
- public String getScheme() {
- return coyoteRequest.scheme().toString();
- }
- /**
- * Return the server name responding to this Request.
- */
- public String getServerName() {
- return coyoteRequest.serverName().toString();
- }
- /**
- * Return the server port responding to this Request.
- */
- public int getServerPort() {
- return coyoteRequest.getServerPort();
- }
- /**
- * Was this request received on a secure connection?
- */
- public boolean isSecure() {
- return secure;
- }
- /**
- * Remove the specified request attribute if it exists.
- *
- * @param name Name of the request attribute to remove
- */
- public void removeAttribute(String name) {
- Object value = null;
- boolean found = false;
- // Remove the specified attribute
- // Check for read only attribute
- // requests are per thread so synchronization unnecessary
- if (readOnlyAttributes.containsKey(name)) {
- return;
- }
- // Pass special attributes to the native layer
- if (name.startsWith("org.apache.tomcat.")) {
- coyoteRequest.getAttributes().remove(name);
- }
- found = attributes.containsKey(name);
- if (found) {
- value = attributes.get(name);
- attributes.remove(name);
- } else {
- return;
- }
-
- // Notify interested application event listeners
- Object listeners[] = context.getApplicationEventListeners();
- if ((listeners == null) || (listeners.length == 0))
- return;
- ServletRequestAttributeEvent event =
- new ServletRequestAttributeEvent(context.getServletContext(),
- getRequest(), name, value);
- for (int i = 0; i < listeners.length; i++) {
- if (!(listeners[i] instanceof ServletRequestAttributeListener))
- continue;
- ServletRequestAttributeListener listener =
- (ServletRequestAttributeListener) listeners[i];
- try {
- listener.attributeRemoved(event);
- } catch (Throwable t) {
- context.getLogger().error(sm.getString("coyoteRequest.attributeEvent"), t);
- // Error valve will pick this exception up and display it to user
- attributes.put( Globals.EXCEPTION_ATTR, t );
- }
- }
- }
- /**
- * Set the specified request attribute to the specified value.
- *
- * @param name Name of the request attribute to set
- * @param value The associated value
- */
- public void setAttribute(String name, Object value) {
- // Name cannot be null
- if (name == null)
- throw new IllegalArgumentException
- (sm.getString("coyoteRequest.setAttribute.namenull"));
- // Null value is the same as removeAttribute()
- if (value == null) {
- removeAttribute(name);
- return;
- }
- if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
- internalDispatcherType = (DispatcherType)value;
- return;
- } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
- requestDispatcherPath = value;
- return;
- }
-
- if (name.equals(Globals.ASYNC_SUPPORTED_ATTR)) {
- this.asyncSupported = (Boolean)value;
- }
- Object oldValue = null;
- boolean replaced = false;
- // Add or replace the specified attribute
- // Check for read only attribute
- // requests are per thread so synchronization unnecessary
- if (readOnlyAttributes.containsKey(name)) {
- return;
- }
- oldValue = attributes.put(name, value);
- if (oldValue != null) {
- replaced = true;
- }
- // Pass special attributes to the native layer
- if (name.startsWith("org.apache.tomcat.")) {
- coyoteRequest.setAttribute(name, value);
- }
-
- // Notify interested application event listeners
- Object listeners[] = context.getApplicationEventListeners();
- if ((listeners == null) || (listeners.length == 0))
- return;
- ServletRequestAttributeEvent event = null;
- if (replaced)
- event =
- new ServletRequestAttributeEvent(context.getServletContext(),
- getRequest(), name, oldValue);
- else
- event =
- new ServletRequestAttributeEvent(context.getServletContext(),
- getRequest(), name, value);
- for (int i = 0; i < listeners.length; i++) {
- if (!(listeners[i] instanceof ServletRequestAttributeListener))
- continue;
- ServletRequestAttributeListener listener =
- (ServletRequestAttributeListener) listeners[i];
- try {
- if (replaced) {
- listener.attributeReplaced(event);
- } else {
- listener.attributeAdded(event);
- }
- } catch (Throwable t) {
- context.getLogger().error(sm.getString("coyoteRequest.attributeEvent"), t);
- // Error valve will pick this exception up and display it to user
- attributes.put( Globals.EXCEPTION_ATTR, t );
- }
- }
- }
- /**
- * Overrides the name of the character encoding used in the body of
- * this request. This method must be called prior to reading request
- * parameters or reading input using <code>getReader()</code>.
- *
- * @param enc The character encoding to be used
- *
- * @exception UnsupportedEncodingException if the specified encoding
- * is not supported
- *
- * @since Servlet 2.3
- */
- public void setCharacterEncoding(String enc)
- throws UnsupportedEncodingException {
- if (usingReader)
- return;
-
- // Ensure that the specified encoding is valid
- byte buffer[] = new byte[1];
- buffer[0] = (byte) 'a';
- new String(buffer, enc);
- // Save the validated encoding
- coyoteRequest.setCharacterEncoding(enc);
- }
- public ServletContext getServletContext() {
- return context.getServletContext();
- }
- public AsyncContext startAsync() {
- return startAsync(getRequest(),response.getResponse());
- }
- public AsyncContext startAsync(ServletRequest request,
- ServletResponse response) {
- if (!isAsyncSupported()) {
- throw new IllegalStateException("Not supported.");
- }
-
- if (asyncContext==null) {
- asyncContext = new AsyncContextImpl(this);
- } else if (asyncContext.isStarted()) {
- throw new IllegalStateException("Already started.");
- }
-
- asyncContext.setStarted(getContext());
- asyncContext.init(request,response);
- asyncContext.setHasOriginalRequestAndResponse(request==getRequest() &&
- response==getResponse().getResponse());
-
- asyncContext.setTimeout(getConnector().getAsyncTimeout());
-
- return asyncContext;
- }
- public boolean isAsyncStarted() {
- if (asyncContext == null) {
- return false;
- }
-
- return asyncContext.isStarted();
- }
- public boolean isAsyncDispatching() {
- if (asyncContext == null) {
- return false;
- }
-
- return (asyncContext.getState()==AsyncContextImpl.AsyncState.DISPATCHING ||
- asyncContext.getState()==AsyncContextImpl.AsyncState.TIMING_OUT ||
- asyncContext.getState()==AsyncContextImpl.AsyncState.STARTED ||
- asyncContext.getState()==AsyncContextImpl.AsyncState.ERROR_DISPATCHING ||
- asyncContext.getState()==AsyncContextImpl.AsyncState.COMPLETING);
- }
- public boolean isAsyncSupported() {
- if (this.asyncSupported == null) {
- return true;
- }
- return asyncSupported.booleanValue();
- }
- public AsyncContext getAsyncContext() {
- return this.asyncContext;
- }
- public DispatcherType getDispatcherType() {
- if (internalDispatcherType == null) {
- return DispatcherType.REQUEST;
- }
- return this.internalDispatcherType;
- }
- // ---------------------------------------------------- HttpRequest Methods
- /**
- * Add a Cookie to the set of Cookies associated with this Request.
- *
- * @param cookie The new cookie
- */
- public void addCookie(Cookie cookie) {
- if (!cookiesParsed)
- parseCookies();
- int size = 0;
- if (cookies != null) {
- size = cookies.length;
- }
- Cookie[] newCookies = new Cookie[size + 1];
- for (int i = 0; i < size; i++) {
- newCookies[i] = cookies[i];
- }
- newCookies[size] = cookie;
- cookies = newCookies;
- }
- /**
- * Add a Locale to the set of preferred Locales for this Request. The
- * first added Locale will be the first one returned by getLocales().
- *
- * @param locale The new preferred Locale
- */
- public void addLocale(Locale locale) {
- locales.add(locale);
- }
- /**
- * Add a parameter name and corresponding set of values to this Request.
- * (This is used when restoring the original request on a form based
- * login).
- *
- * @param name Name of this request parameter
- * @param values Corresponding values for this request parameter
- */
- public void addParameter(String name, String values[]) {
- coyoteRequest.getParameters().addParameterValues(name, values);
- }
- /**
- * Clear the collection of Cookies associated with this Request.
- */
- public void clearCookies() {
- cookiesParsed = true;
- cookies = null;
- }
- /**
- * Clear the collection of Headers associated with this Request.
- */
- public void clearHeaders() {
- // Not used
- }
- /**
- * Clear the collection of Locales associated with this Request.
- */
- public void clearLocales() {
- locales.clear();
- }
- /**
- * Clear the collection of parameters associated with this Request.
- */
- public void clearParameters() {
- // Not used
- }
- /**
- * Set the authentication type used for this request, if any; otherwise
- * set the type to <code>null</code>. Typical values are "BASIC",
- * "DIGEST", or "SSL".
- *
- * @param type The authentication type used
- */
- public void setAuthType(String type) {
- this.authType = type;
- }
- /**
- * Set the context path for this Request. This will normally be called
- * when the associated Context is mapping the Request to a particular
- * Wrapper.
- *
- * @param path The context path
- */
- public void setContextPath(String path) {
- if (path == null) {
- mappingData.contextPath.setString("");
- } else {
- mappingData.contextPath.setString(path);
- }
- }
- /**
- * Set the path information for this Request. This will normally be called
- * when the associated Context is mapping the Request to a particular
- * Wrapper.
- *
- * @param path The path information
- */
- public void setPathInfo(String path) {
- mappingData.pathInfo.setString(path);
- }
- /**
- * Set a flag indicating whether or not the requested session ID for this
- * request came in through a cookie. This is normally called by the
- * HTTP Connector, when it parses the request headers.
- *
- * @param flag The new flag
- */
- public void setRequestedSessionCookie(boolean flag) {
- this.requestedSessionCookie = flag;
- }
- /**
- * Set the requested session ID for this request. This is normally called
- * by the HTTP Connector, when it parses the request headers.
- *
- * @param id The new session id
- */
- public void setRequestedSessionId(String id) {
- this.requestedSessionId = id;
- }
- /**
- * Set a flag indicating whether or not the requested session ID for this
- * request came in through a URL. This is normally called by the
- * HTTP Connector, when it parses the request headers.
- *
- * @param flag The new flag
- */
- public void setRequestedSessionURL(boolean flag) {
- this.requestedSessionURL = flag;
- }
- /**
- * Set a flag indicating whether or not the requested session ID for this
- * request came in through SSL. This is normally called by the
- * HTTP Connector, when it parses the request headers.
- *
- * @param flag The new flag
- */
- public void setRequestedSessionSSL(boolean flag) {
- this.requestedSessionSSL = flag;
- }
- /**
- * Get the decoded request URI.
- *
- * @return the URL decoded request URI
- */
- public String getDecodedRequestURI() {
- return coyoteRequest.decodedURI().toString();
- }
- /**
- * Get the decoded request URI.
- *
- * @return the URL decoded request URI
- */
- public MessageBytes getDecodedRequestURIMB() {
- return co