/* * 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;
/** * Create a new Request object associated with the given Connector. * * @param connector The Connector with which this Request object will always be associated. In normal usage this * must be non-null. In some test scenarios, it may be possible to use a null Connector without * triggering an NPE.
*/ public Request(Connector connector) { this.connector = connector;
}
/** * Set the Coyote request. * * @param coyoteRequest The Coyote request
*/ publicvoid setCoyoteRequest(org.apache.coyote.Request coyoteRequest) { this.coyoteRequest = coyoteRequest;
inputBuffer.setRequest(coyoteRequest);
}
/** * Get the Coyote request. * * @return the Coyote request object
*/ public org.apache.coyote.Request getCoyoteRequest() { returnthis.coyoteRequest;
}
/** * The string manager for this package.
*/ protectedstaticfinal StringManager sm = StringManager.getManager(Request.class);
/** * The set of cookies associated with this Request.
*/ protected Cookie[] cookies = null;
/** * The default Locale if none are specified.
*/ protectedstaticfinal Locale defaultLocale = Locale.getDefault();
/** * The attributes associated with this Request, keyed by attribute name.
*/ privatefinal Map<String,Object> attributes = new ConcurrentHashMap<>();
/** * Flag that indicates if SSL attributes have been parsed to improve performance for applications (usually * frameworks) that make multiple calls to {@link Request#getAttributeNames()}.
*/ protectedboolean sslAttributesParsed = false;
/** * The preferred Locales associated with this Request.
*/ protectedfinal ArrayList<Locale> locales = new ArrayList<>();
/** * Internal notes associated with this request by Catalina components and event listeners.
*/ privatefinaltransient HashMap<String,Object> notes = new HashMap<>();
/** * Cookie headers parsed flag. Indicates that the cookie headers have been parsed into ServerCookies.
*/ protectedboolean cookiesParsed = false;
/** * Cookie parsed flag. Indicates that the ServerCookies have been converted into user facing Cookie objects.
*/ protectedboolean cookiesConverted = false;
/** * @return the Connector through which this Request was received.
*/ public Connector getConnector() { returnthis.connector;
}
/** * Return the Context within which this Request is being processed. * <p> * This is available as soon as the appropriate Context is identified. Note that availability of a Context allows * <code>getContextPath()</code> to return a value, and thus enables parsing of the request URI. * * @return the Context mapped with the request
*/ public Context getContext() { return mappingData.context;
}
/** * Get the recycling strategy of the facade objects. * * @return the value of the flag as set on the connector, or <code>true</code> if no connector is associated with * this request
*/ publicboolean getDiscardFacades() { return (connector == null) ? true : connector.getDiscardFacades();
}
/** * Filter chain associated with the request.
*/ protected FilterChain filterChain = null;
/** * Get filter chain associated with the request. * * @return the associated filter chain
*/ public FilterChain getFilterChain() { returnthis.filterChain;
}
/** * Set filter chain associated with the request. * * @param filterChain new filter chain
*/ publicvoid setFilterChain(FilterChain filterChain) { this.filterChain = filterChain;
}
/** * @return the Host within which this Request is being processed.
*/ public Host getHost() { return mappingData.host;
}
/** * Mapping data.
*/ protectedfinal MappingData mappingData = new MappingData(); privatefinal ApplicationMapping applicationMapping = new ApplicationMapping(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);
} if (applicationRequest == null) {
applicationRequest = facade;
} return applicationRequest;
}
/** * Set a wrapped HttpServletRequest to pass to the application. Components wishing to wrap the request should obtain * the request via {@link #getRequest()}, wrap it and then call this method with the wrapped request. * * @param applicationRequest The wrapped request to pass to the application
*/ publicvoid setRequest(HttpServletRequest applicationRequest) { // Check the wrapper wraps this request
ServletRequest r = applicationRequest; while (r instanceof HttpServletRequestWrapper) {
r = ((HttpServletRequestWrapper) r).getRequest();
} if (r != facade) { thrownew IllegalArgumentException(sm.getString("request.illegalWrap"));
} this.applicationRequest = applicationRequest;
}
/** * The response with which this request is associated.
*/ protected Response response = null;
/** * @return the Response with which this Request is associated.
*/ public Response getResponse() { returnthis.response;
}
/** * Set the Response with which this Request is associated. * * @param response The new associated response
*/ publicvoid setResponse(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.
*/ protected B2CConverter URIConverter = null;
/** * @return the URI converter.
*/ protected B2CConverter getURIConverter() { return URIConverter;
}
/** * Set the URI converter. * * @param URIConverter the new URI converter
*/ protectedvoid setURIConverter(B2CConverter URIConverter) { this.URIConverter = URIConverter;
}
/** * @return the Wrapper within which this Request is being processed.
*/ public Wrapper getWrapper() { return mappingData.wrapper;
}
// ------------------------------------------------- Request Public Methods
/** * Create and return a ServletInputStream to read the content associated with this Request. * * @return the created input stream * * @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
*/ publicvoid finishRequest() throws IOException { if (response.getStatus() == HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE) {
checkSwallowInput();
}
}
/** * @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);
}
/** * Remove any object bound to the specified name in the internal notes for this request. * * @param name Name of the note to be removed
*/ publicvoid removeNote(String name) {
notes.remove(name);
}
/** * Set the port number of the server to process this request. * * @param port The server port
*/ publicvoid setLocalPort(int port) {
localPort = port;
}
/** * 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
*/ publicvoid 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
*/ publicvoid 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
*/ publicvoid 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
*/ publicvoid setSecure(boolean secure) { this.secure = secure;
}
/** * Set the port number of the server to process this request. * * @param port The server port
*/ publicvoid setServerPort(int port) {
coyoteRequest.setServerPort(port);
}
/** * @return the specified request attribute if it exists; otherwise, return <code>null</code>. * * @param name Name of the request attribute to return
*/
@Override public Object getAttribute(String name) { // Special attributes
SpecialAttributeAdapter adapter = specialAttributes.get(name); if (adapter != null) { return adapter.get(this, 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> * <li>{@link Globals#PARAMETER_PARSE_FAILED_ATTR}</li> * </ul> * The underlying connector may also expose request attributes. These all have names starting with * "org.apache.tomcat" and include: * <ul> * <li>{@link Globals#SENDFILE_SUPPORTED_ATTR}</li> * </ul> * Connector implementations may return some, all or none of these attributes and may also support additional * attributes. * * @return the attribute names enumeration
*/
@Override public Enumeration<String> getAttributeNames() { if (isSecure() && !sslAttributesParsed) {
getAttribute(Globals.CERTIFICATES_ATTR);
} // Take a copy to prevent ConcurrentModificationExceptions if used to // remove attributes
Set<String> names = new HashSet<>(attributes.keySet()); return Collections.enumeration(names);
}
/** * @return the character encoding for this Request.
*/
@Override public String getCharacterEncoding() {
String characterEncoding = coyoteRequest.getCharacterEncoding(); if (characterEncoding != null) { return characterEncoding;
}
/** * @return the content length for this Request.
*/
@Override publicint getContentLength() { return coyoteRequest.getContentLength();
}
/** * @return the content type for this Request.
*/
@Override public String getContentType() { return coyoteRequest.getContentType();
}
/** * Set the content type for this Request. * * @param contentType The content type
*/ publicvoid setContentType(String contentType) {
coyoteRequest.setContentType(contentType);
}
/** * @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
*/
@Override public ServletInputStream getInputStream() throws IOException {
if (usingReader) { thrownew 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.
*/
@Override 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.
*/
@Override public Enumeration<Locale> getLocales() {
if (!localesParsed) {
parseLocales();
}
if (locales.size() > 0) { return Collections.enumeration(locales);
}
ArrayList<Locale> results = new ArrayList<>();
results.add(defaultLocale); return Collections.enumeration(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
*/
@Override public String getParameter(String 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.
*/
@Override 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.
*/
@Override public Enumeration<String> 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
*/
@Override public String[] getParameterValues(String name) {
/** * @return the protocol and version used to make this Request.
*/
@Override public String getProtocol() { return coyoteRequest.protocol().toStringType();
}
/** * 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>. * * @return a buffered reader for the request * * @exception IllegalStateException if <code>getInputStream()</code> has already been called for this request * @exception IOException if an input/output error occurs
*/
@Override public BufferedReader getReader() throws IOException {
if (usingInputStream) { thrownew IllegalStateException(sm.getString("coyoteRequest.getReader.ise"));
}
// InputBuffer has no easily accessible reference chain to the Context // to check for a default request character encoding at the Context. // Therefore, if a Context default should be used, it is set explicitly // here. Need to do this before setting usingReader. if (coyoteRequest.getCharacterEncoding() == null) { // Nothing currently set explicitly. // Check the context
Context context = getContext(); if (context != null) {
String enc = context.getRequestCharacterEncoding(); if (enc != null) { // Explicitly set the context default so it is visible to // InputBuffer when creating the Reader.
setCharacterEncoding(enc);
}
}
}
usingReader = true;
inputBuffer.checkConverter(); if (reader == null) {
reader = new CoyoteReader(inputBuffer);
} return reader;
}
/** * @return the remote IP address making this Request.
*/
@Override public String getRemoteAddr() { if (remoteAddr == null) {
coyoteRequest.action(ActionCode.REQ_HOST_ADDR_ATTRIBUTE, coyoteRequest);
remoteAddr = coyoteRequest.remoteAddr().toString();
} return remoteAddr;
}
/** * @return the connection peer IP address making this Request.
*/ public String getPeerAddr() { if (peerAddr == null) {
coyoteRequest.action(ActionCode.REQ_PEER_ADDR_ATTRIBUTE, coyoteRequest);
peerAddr = coyoteRequest.peerAddr().toString();
} return peerAddr;
}
/** * @return the remote host name making this Request.
*/
@Override public String getRemoteHost() { if (remoteHost == null) { if (!connector.getEnableLookups()) {
remoteHost = getRemoteAddr();
} else {
coyoteRequest.action(ActionCode.REQ_HOST_ATTRIBUTE, coyoteRequest);
remoteHost = coyoteRequest.remoteHost().toString();
}
} return remoteHost;
}
/** * @return the Internet Protocol (IP) source port of the client or last proxy that sent the request.
*/
@Override publicint getRemotePort() { if (remotePort == -1) {
coyoteRequest.action(ActionCode.REQ_REMOTEPORT_ATTRIBUTE, coyoteRequest);
remotePort = coyoteRequest.getRemotePort();
} return remotePort;
}
/** * @return the host name of the Internet Protocol (IP) interface on which the request was received.
*/
@Override public String getLocalName() { if (localName == null) {
coyoteRequest.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, coyoteRequest);
localName = coyoteRequest.localName().toString();
} return localName;
}
/** * @return the Internet Protocol (IP) address of the interface on which the request was received.
*/
@Override public String getLocalAddr() { if (localAddr == null) {
coyoteRequest.action(ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE, coyoteRequest);
localAddr = coyoteRequest.localAddr().toString();
} return localAddr;
}
/** * @return the Internet Protocol (IP) port number of the interface on which the request was received.
*/
@Override publicint getLocalPort() { if (localPort == -1) {
coyoteRequest.action(ActionCode.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
*/
@Override public RequestDispatcher getRequestDispatcher(String path) {
int fragmentPos = path.indexOf('#'); if (fragmentPos > -1) {
log.warn(sm.getString("request.fragmentInDispatchPath", path));
path = path.substring(0, fragmentPos);
}
// If the path is already context-relative, just pass it through if (path.startsWith("/")) { return context.getServletContext().getRequestDispatcher(path);
}
/* * Relative to what, exactly? * * From the Servlet 4.0 Javadoc: - The pathname specified may be relative, although it cannot extend outside the * current servlet context. - If it is relative, it must be relative against the current servlet * * From Section 9.1 of the spec: - The servlet container uses information in the request object to transform the * given relative path against the current servlet to a complete path. * * It is undefined whether the requestURI is used or whether servletPath and pathInfo are used. Given that the * RequestURI includes the contextPath (and extracting that is messy) , using the servletPath and pathInfo looks * to be the more reasonable choice.
*/
// Convert a request-relative path to a context-relative one
String servletPath = (String) getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); if (servletPath == null) {
servletPath = getServletPath();
}
// Add the path info, if there is any
String pathInfo = getPathInfo();
String requestPath = null;
/** * @return the scheme used to make this Request.
*/
@Override public String getScheme() { return coyoteRequest.scheme().toStringType();
}
/** * @return the server name responding to this Request.
*/
@Override public String getServerName() { return coyoteRequest.serverName().toString();
}
/** * @return the server port responding to this Request.
*/
@Override publicint getServerPort() { return coyoteRequest.getServerPort();
}
/** * @return <code>true</code> if this request was received on a secure connection.
*/
@Override publicboolean isSecure() { return secure;
}
/** * Remove the specified request attribute if it exists. * * @param name Name of the request attribute to remove
*/
@Override publicvoid removeAttribute(String name) { // Remove the specified attribute // Pass special attributes to the native layer if (name.startsWith("org.apache.tomcat.")) {
coyoteRequest.getAttributes().remove(name);
}
boolean found = attributes.containsKey(name); if (found) {
Object value = attributes.get(name);
attributes.remove(name);
/** * Set the specified request attribute to the specified value. * * @param name Name of the request attribute to set * @param value The associated value
*/
@Override publicvoid setAttribute(String name, Object value) {
// Name cannot be null if (name == null) { thrownew IllegalArgumentException(sm.getString("coyoteRequest.setAttribute.namenull"));
}
// Null value is the same as removeAttribute() if (value == null) {
removeAttribute(name); return;
}
// Special attributes
SpecialAttributeAdapter adapter = specialAttributes.get(name); if (adapter != null) {
adapter.set(this, name, value); return;
}
// Add or replace the specified attribute // Do the security check before any updates are made if (Globals.IS_SECURITY_ENABLED && name.equals(Globals.SENDFILE_FILENAME_ATTR)) { // Use the canonical file name to avoid any possible symlink and // relative path issues
String canonicalPath; try {
canonicalPath = new File(value.toString()).getCanonicalPath();
} catch (IOException e) { thrownew SecurityException(sm.getString("coyoteRequest.sendfileNotCanonical", value), e);
} // Sendfile is performed in Tomcat's security context so need to // check if the web app is permitted to access the file while still // in the web app's security context
System.getSecurityManager().checkRead(canonicalPath); // Update the value so the canonical path is used
value = canonicalPath;
}
Object oldValue = attributes.put(name, value);
// Pass special attributes to the native layer if (name.startsWith("org.apache.tomcat.")) {
coyoteRequest.setAttribute(name, value);
}
/** * Notify interested listeners that attribute has been assigned a value. * * @param name Attribute name * @param value New attribute value * @param oldValue Old attribute value
*/ privatevoid notifyAttributeAssigned(String name, Object value, Object oldValue) {
Context context = getContext(); if (context == null) { return;
}
Object listeners[] = context.getApplicationEventListeners(); if (listeners == null || listeners.length == 0) { return;
} boolean replaced = (oldValue != null);
ServletRequestAttributeEvent event = null; if (replaced) {
event = new ServletRequestAttributeEvent(context.getServletContext(), getRequest(), name, oldValue);
} else {
event = new ServletRequestAttributeEvent(context.getServletContext(), getRequest(), name, value);
}
for (Object o : listeners) { if (!(o instanceof ServletRequestAttributeListener)) { continue;
}
ServletRequestAttributeListener listener = (ServletRequestAttributeListener) o; try { if (replaced) {
listener.attributeReplaced(event);
} else {
listener.attributeAdded(event);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t); // Error valve will pick this exception up and display it to user
attributes.put(RequestDispatcher.ERROR_EXCEPTION, t);
context.getLogger().error(sm.getString("coyoteRequest.attributeEvent"), t);
}
}
}
/** * Notify interested listeners that attribute has been removed. * * @param name Attribute name * @param value Attribute value
*/ privatevoid notifyAttributeRemoved(String name, Object value) {
Context context = getContext();
Object listeners[] = context.getApplicationEventListeners(); if (listeners == null || listeners.length == 0) { return;
}
ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(context.getServletContext(), getRequest(), name, value); for (Object o : listeners) { if (!(o instanceof ServletRequestAttributeListener)) { continue;
}
ServletRequestAttributeListener listener = (ServletRequestAttributeListener) o; try {
listener.attributeRemoved(event);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t); // Error valve will pick this exception up and display it to user
attributes.put(RequestDispatcher.ERROR_EXCEPTION, t);
context.getLogger().error(sm.getString("coyoteRequest.attributeEvent"), 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
*/
@Override publicvoid setCharacterEncoding(String enc) throws UnsupportedEncodingException {
if (usingReader) { return;
}
// Confirm that the encoding name is valid
Charset charset = B2CConverter.getCharset(enc);
// Save the validated encoding
coyoteRequest.setCharset(charset);
}
@Override public ServletContext getServletContext() { return getContext().getServletContext();
}
@Override public AsyncContext startAsync() { return startAsync(getRequest(), response.getResponse());
}
@Override public AsyncContext startAsync(ServletRequest request, ServletResponse response) { if (!isAsyncSupported()) {
IllegalStateException ise = new IllegalStateException(sm.getString("request.asyncNotSupported"));
log.warn(sm.getString("coyoteRequest.noAsync", StringUtils.join(getNonAsyncClassNames())), ise); throw ise;
}
if (asyncContext == null) {
asyncContext = new AsyncContextImpl(this);
}
/** * 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
*/ publicvoid addLocale(Locale locale) {
locales.add(locale);
}
/** * Clear the collection of Cookies associated with this Request.
*/ publicvoid clearCookies() {
cookiesParsed = true;
cookiesConverted = true;
cookies = null;
}
/** * Clear the collection of Locales associated with this Request.
*/ publicvoid clearLocales() {
locales.clear();
}
/** * 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
*/ publicvoid setAuthType(String type) { this.authType = type;
}
/** * 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
*/ publicvoid 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
*/ publicvoid 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
*/ publicvoid 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
*/ publicvoid 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
*/ publicvoid 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 coyoteRequest.decodedURI();
}
/** * Set the Principal who has been authenticated for this Request. This value is also used to calculate the value to * be returned by the <code>getRemoteUser()</code> method. * * @param principal The user Principal
*/ publicvoid setUserPrincipal(final Principal principal) { if (Globals.IS_SECURITY_ENABLED && principal != null) { if (subject == null) { final HttpSession session = getSession(false); if (session == null) { // Cache the subject in the request
subject = newSubject(principal);
} else { // Cache the subject in the request and the session
subject = (Subject) session.getAttribute(Globals.SUBJECT_ATTR); if (subject == null) {
subject = newSubject(principal);
session.setAttribute(Globals.SUBJECT_ATTR, subject);
} else {
subject.getPrincipals().add(principal);
}
}
} else {
subject.getPrincipals().add(principal);
}
}
userPrincipal = principal;
}
private Subject newSubject(final Principal principal) { final Subject result = new Subject();
result.getPrincipals().add(principal); return result;
}
@Override public Map<String,String> getTrailerFields() { if (!isTrailerFieldsReady()) { thrownew IllegalStateException(sm.getString("coyoteRequest.trailersNotReady"));
}
Map<String,String> result = new HashMap<>(coyoteRequest.getTrailerFields()); return result;
}
@Override public PushBuilder newPushBuilder() { return newPushBuilder(this);
}
public PushBuilder newPushBuilder(HttpServletRequest request) {
AtomicBoolean result = new AtomicBoolean();
coyoteRequest.action(ActionCode.IS_PUSH_SUPPORTED, result); if (result.get()) { returnnew ApplicationPushBuilder(this, request);
} else { returnnull;
}
}
@SuppressWarnings("unchecked")
@Override public <T extends HttpUpgradeHandler> T upgrade(Class<T> httpUpgradeHandlerClass) throws IOException, ServletException {
T handler;
InstanceManager instanceManager = null; try { // Do not go through the instance manager for internal Tomcat classes since they don't // need injection if (InternalHttpUpgradeHandler.class.isAssignableFrom(httpUpgradeHandlerClass)) {
handler = httpUpgradeHandlerClass.getConstructor().newInstance();
} else {
instanceManager = getContext().getInstanceManager();
handler = (T) instanceManager.newInstance(httpUpgradeHandlerClass);
}
} catch (ReflectiveOperationException | NamingException | IllegalArgumentException | SecurityException e) { thrownew ServletException(e);
}
UpgradeToken upgradeToken = new UpgradeToken(handler, getContext(), instanceManager,
getUpgradeProtocolName(httpUpgradeHandlerClass));
// Output required by RFC2616. Protocol specific headers should have // already been set.
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
return handler;
}
private String getUpgradeProtocolName(Class<? extends HttpUpgradeHandler> httpUpgradeHandlerClass) { // Ideal - the caller has already explicitly set the selected protocol // on the response
String result = response.getHeader(HTTP_UPGRADE_HEADER_NAME);
if (result == null) { // If the request's upgrade header contains a single protocol that // is the protocol that must have been selected
List<Upgrade> upgradeProtocols = Upgrade.parse(getHeaders(HTTP_UPGRADE_HEADER_NAME)); if (upgradeProtocols != null && upgradeProtocols.size() == 1) {
result = upgradeProtocols.get(0).toString();
}
}
if (result == null) { // Ugly but use the class name - it is better than nothing
result = httpUpgradeHandlerClass.getName();
} return result;
}
/** * Return the authentication type used for this Request.
*/
@Override public String getAuthType() { return authType;
}
/** * Return the portion of the request URI used to select the Context of the Request. The value returned is not * decoded which also implies it is not normalised.
*/
@Override public String getContextPath() { int lastSlash = mappingData.contextSlashCount; // Special case handling for the root context if (lastSlash == 0) { return"";
}
String uri = getRequestURI(); int pos = 0; if (!getContext().getAllowMultipleLeadingForwardSlashInPath()) { // Ensure that the returned value only starts with a single '/'. // This prevents the value being misinterpreted as a protocol- // relative URI if used with sendRedirect(). do {
pos++;
} while (pos < uri.length() && uri.charAt(pos) == '/');
pos--;
uri = uri.substring(pos);
}
char[] uriChars = uri.toCharArray(); // Need at least the number of slashes in the context path while (lastSlash > 0) {
pos = nextSlash(uriChars, pos + 1); if (pos == -1) { break;
}
lastSlash--;
} // Now allow for path parameters, normalization and/or encoding. // Essentially, keep extending the candidate path up to the next slash // until the decoded and normalized candidate path (with the path // parameters removed) is the same as the canonical path.
String candidate; if (pos == -1) {
candidate = uri;
} else {
candidate = uri.substring(0, pos);
}
candidate = removePathParameters(candidate);
candidate = UDecoder.URLDecode(candidate, connector.getURICharset());
candidate = org.apache.tomcat.util.http.RequestUtil.normalize(candidate); boolean match = canonicalContextPath.equals(candidate); while (!match && pos != -1) {
pos = nextSlash(uriChars, pos + 1); if (pos == -1) {
candidate = uri;
} else {
candidate = uri.substring(0, pos);
}
candidate = removePathParameters(candidate);
candidate = UDecoder.URLDecode(candidate, connector.getURICharset());
candidate = org.apache.tomcat.util.http.RequestUtil.normalize(candidate);
match = canonicalContextPath.equals(candidate);
} if (match) { if (pos == -1) { return uri;
} else { return uri.substring(0, pos);
}
} else { // Should never happen thrownew IllegalStateException(
sm.getString("coyoteRequest.getContextPath.ise", canonicalContextPath, uri));
}
}
private String removePathParameters(String input) { int nextSemiColon = input.indexOf(';'); // Shortcut if (nextSemiColon == -1) { return input;
}
StringBuilder result = new StringBuilder(input.length());
result.append(input.substring(0, nextSemiColon)); while (true) { int nextSlash = input.indexOf('/', nextSemiColon); if (nextSlash == -1) { break;
}
nextSemiColon = input.indexOf(';', nextSlash); if (nextSemiColon == -1) {
result.append(input.substring(nextSlash)); break;
} else {
result.append(input.substring(nextSlash, nextSemiColon));
}
}
return result.toString();
}
privateint nextSlash(char[] uri, int startPos) { int len = uri.length; int pos = startPos; while (pos < len) { if (uri[pos] == '/') { return pos;
} elseif (connector.getEncodedSolidusHandlingInternal() == EncodedSolidusHandling.DECODE &&
uri[pos] == '%' && pos + 2 < len && uri[pos + 1] == '2' &&
(uri[pos + 2] == 'f' || uri[pos + 2] == 'F')) { return pos;
}
pos++;
} return -1;
}
/** * Return the set of Cookies received with this Request. Triggers parsing of the Cookie HTTP headers followed by * conversion to Cookie objects if this has not already been performed. * * @return the array of cookies
*/
@Override public Cookie[] getCookies() { if (!cookiesConverted) {
convertCookies();
} return cookies;
}
/** * Return the server representation of the cookies associated with this request. Triggers parsing of the Cookie HTTP * headers (but not conversion to Cookie objects) if the headers have not yet been parsed. * * @return the server cookies
*/ public ServerCookies getServerCookies() {
parseCookies(); return coyoteRequest.getCookies();
}
/** * Return the value of the specified date header, if any; otherwise return -1. * * @param name Name of the requested date header *
--> --------------------
--> maximum size reached
--> --------------------
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.29Angebot
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.