Skip to content
Commits on Source (5)
......@@ -33,14 +33,6 @@
# will be redirected.
# Default is $CATALINA_BASE/logs/catalina.out
#
# CATALINA_OUT_CMD (Optional) Command which will be executed and receive
# as its stdin the stdout and stderr from the Tomcat java
# process. If CATALINA_OUT_CMD is set, the value of
# CATALINA_OUT will be ignored.
# No default.
# Example (all one line)
# CATALINA_OUT_CMD="cronolog $CATALINA_BASE/logs/catalina.%Y-%m-%d.out >/dev/null 2>&1"
#
# CATALINA_OPTS (Optional) Java runtime options used when the "start",
# "run" or "debug" command is executed.
# Include here and not in JAVA_OPTS all options, that should
......@@ -451,23 +443,13 @@ elif [ "$1" = "start" ] ; then
fi
shift
if [ -z "$CATALINA_OUT_CMD" ] ; then
touch "$CATALINA_OUT"
catalina_out_command=">> \"$CATALINA_OUT\" 2>&1"
else
catalina_out_command="| $CATALINA_OUT_CMD"
fi
if [ ! -z "$CATALINA_PID" ]; then
catalina_pid_file="$CATALINA_PID"
else
catalina_pid_file=/dev/null
fi
if [ "$1" = "-security" ] ; then
if [ $have_tty -eq 1 ]; then
echo "Using Security Manager"
fi
shift
eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......@@ -476,20 +458,24 @@ elif [ "$1" = "start" ] ; then
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
2\>\&1 \&\& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
>> "$CATALINA_OUT" 2>&1 "&"
else
eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
2\>\&1 \&\& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
>> "$CATALINA_OUT" 2>&1 "&"
fi
if [ ! -z "$CATALINA_PID" ]; then
echo $! > "$CATALINA_PID"
fi
echo "Tomcat started."
elif [ "$1" = "stop" ] ; then
......
......@@ -25,7 +25,7 @@
# ----- Version Control Flags -----
version.major=8
version.minor=5
version.build=38
version.build=39
version.patch=0
version.suffix=
......
......@@ -1116,7 +1116,7 @@
source="${compile.source}"
target="${compile.target}"
release="${compile.release}"
classpath="$tomcat.lcasses}"
classpath="${tomcat.classes}"
excludes="**/CVS/**,**/.svn/**"
encoding="ISO-8859-1"
includeantruntime="false">
......@@ -2617,7 +2617,7 @@ skip.installer property in build.properties" />
</target>
<target name="download-compile"
description="Download (and build) components necessary to compile" >
description="Download components necessary to compile" >
<!-- Download Commons Daemon -->
<antcall target="downloadgz-2">
......
......@@ -172,11 +172,7 @@ tagsoup-*.jar,\
tomcat-api.jar,\
tomcat-coyote.jar,\
tomcat-dbcp.jar,\
tomcat-i18n-en.jar,\
tomcat-i18n-es.jar,\
tomcat-i18n-fr.jar,\
tomcat-i18n-ja.jar,\
tomcat-i18n-ru.jar,\
tomcat-i18n-*.jar,\
tomcat-jdbc.jar,\
tomcat-jni.jar,\
tomcat-juli-adapters.jar,\
......
tomcat8 (8.5.39-1) experimental; urgency=medium
* Team upload.
* New upstream release
- Refreshed the patches
* Track and download the new releases from GitHub
-- Emmanuel Bourg <ebourg@apache.org> Mon, 25 Mar 2019 10:47:43 +0100
tomcat8 (8.5.38-2) unstable; urgency=high
* Team upload.
......
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Apache Tomcat 8
Source: http://tomcat.apache.org/download-80.cgi
Files-Excluded: */taglibs-standard*.jar
Upstream-Authors:
Alex Chaffee
Alex Cruikshank [alex@epitonic.com]
......
#!/bin/sh -e
VERSION=$2
TAR=../tomcat8_$VERSION.orig.tar.xz
DIR=tomcat8-$VERSION
TAG=$(echo TOMCAT_$VERSION | sed -e 's/[\.~]/_/g')
svn export https://svn.apache.org/repos/asf/tomcat/tc8.5.x/tags/$TAG $DIR
tar -c -J -f $TAR --exclude 'taglibs-standard-*.jar' $DIR
rm -rf $DIR ../$TAG $3
......@@ -9,7 +9,7 @@ Bug-Debian: http://bugs.debian.org/585379
Forwarded: not-needed
--- a/bin/catalina.sh
+++ b/bin/catalina.sh
@@ -364,7 +364,7 @@
@@ -356,7 +356,7 @@
-classpath "$CLASSPATH" \
-sourcepath "$CATALINA_HOME"/../../java \
-Djava.security.manager \
......@@ -18,7 +18,7 @@ Forwarded: not-needed
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
@@ -393,7 +393,7 @@
@@ -385,7 +385,7 @@
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......@@ -27,7 +27,7 @@ Forwarded: not-needed
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
@@ -471,7 +471,7 @@
@@ -453,7 +453,7 @@
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......
Description: Unbreak startup script
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63041
Revert the changes for BZ 53930 that added support for the
CATALINA_OUT_CMD environment variable as they prevented correct
operation with systemd configurations that did not explicitly
specify a PID file.
Origin: upstream, commit:r1853509
Bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=63063
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=922863
Author: markt
--- a/bin/catalina.sh
+++ b/bin/catalina.sh
@@ -33,14 +33,6 @@
# will be redirected.
# Default is $CATALINA_BASE/logs/catalina.out
#
-# CATALINA_OUT_CMD (Optional) Command which will be executed and receive
-# as its stdin the stdout and stderr from the Tomcat java
-# process. If CATALINA_OUT_CMD is set, the value of
-# CATALINA_OUT will be ignored.
-# No default.
-# Example (all one line)
-# CATALINA_OUT_CMD="cronolog $CATALINA_BASE/logs/catalina.%Y-%m-%d.out >/dev/null 2>&1"
-#
# CATALINA_OPTS (Optional) Java runtime options used when the "start",
# "run" or "debug" command is executed.
# Include here and not in JAVA_OPTS all options, that should
@@ -451,23 +443,13 @@ elif [ "$1" = "start" ] ; then
fi
shift
- if [ -z "$CATALINA_OUT_CMD" ] ; then
- touch "$CATALINA_OUT"
- catalina_out_command=">> \"$CATALINA_OUT\" 2>&1"
- else
- catalina_out_command="| $CATALINA_OUT_CMD"
- fi
- if [ ! -z "$CATALINA_PID" ]; then
- catalina_pid_file="$CATALINA_PID"
- else
- catalina_pid_file=/dev/null
- fi
+ touch "$CATALINA_OUT"
if [ "$1" = "-security" ] ; then
if [ $have_tty -eq 1 ]; then
echo "Using Security Manager"
fi
shift
- eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
+ eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
@@ -476,20 +458,24 @@ elif [ "$1" = "start" ] ; then
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
- 2\>\&1 \&\& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
+ >> "$CATALINA_OUT" 2>&1 "&"
else
- eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
+ eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
- 2\>\&1 \&\& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
+ >> "$CATALINA_OUT" 2>&1 "&"
fi
+ if [ ! -z "$CATALINA_PID" ]; then
+ echo $! > "$CATALINA_PID"
+ fi
+
echo "Tomcat started."
elif [ "$1" = "stop" ] ; then
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -360,6 +360,12 @@
environment variable that defines a command to which captured stdout and
stderr will be redirected. Patch provided by Casey Lucas. (markt)
</add>
+ <fix>
+ <bug>63041</bug>: Revert the changes for <bug>53930</bug> that added
+ support for the <code>CATALINA_OUT_CMD</code> environment variable as
+ they prevented correct operation with systemd configurations that did
+ not explicitly specify a PID file. (markt)
+ </fix>
</changelog>
</subsection>
</section>
......@@ -12,4 +12,3 @@
0024-systemd-log-formatter.patch
0025-invalid-configuration-exit-status.patch
0026-easymock4-compatibility.patch
0027-fix-catalina_sh.patch
version=3
opts="uversionmangle=s/-(alpha|beta|RC)/~$1/" \
https://archive.apache.org/dist/tomcat/tomcat-8/v([\d\.]+)/src/apache-tomcat-([\d\.]+)-src.zip debian debian/orig-tar.sh
version=4
opts="mode=git,repack=true,compression=xz,uversionmangle=s/-(alpha|beta|RC)/~$1/" \
https://github.com/apache/tomcat refs/tags/(8\.[\d\.]+)
......@@ -701,8 +701,8 @@ public interface Context extends Container, ContextBind {
public void setJarScanner(JarScanner jarScanner);
/**
* @return the {@link Authenticator} that is used by this context or
* <code>null</code> if none is used.
* @return the {@link Authenticator} that is used by this context. This is
* always non-{@code null} for a started Context
*/
public Authenticator getAuthenticator();
......@@ -1001,14 +1001,31 @@ public interface Context extends Container, ContextBind {
/**
* @param exceptionType Exception type to look up
*
* @return the error page entry for the specified Java exception type,
* if any; otherwise return <code>null</code>.
* if any; otherwise return {@code null}.
*
* @param exceptionType Exception type to look up
* @deprecated Unused. Will be removed in Tomcat 10.
* Use {@link #findErrorPage(Throwable)} instead.
*/
@Deprecated
public ErrorPage findErrorPage(String exceptionType);
/**
* Find and return the ErrorPage instance for the specified exception's
* class, or an ErrorPage instance for the closest superclass for which
* there is such a definition. If no associated ErrorPage instance is
* found, return <code>null</code>.
*
* @param throwable The exception type for which to find an ErrorPage
*
* @return the error page entry for the specified Java exception type,
* if any; otherwise return {@code null}.
*/
public ErrorPage findErrorPage(Throwable throwable);
/**
* @return the set of defined error pages for all specified error codes
......@@ -1119,7 +1136,11 @@ public interface Context extends Container, ContextBind {
* HTTP status code, if any; otherwise return <code>null</code>.
*
* @param status HTTP status code to look up
*
* @deprecated Unused. Will be removed in Tomcat 10.
* Use {@link #findErrorPage(int)} instead.
*/
@Deprecated
public String findStatusPage(int status);
......@@ -1127,7 +1148,11 @@ public interface Context extends Container, ContextBind {
* @return the set of HTTP status codes for which error pages have
* been specified. If none are specified, a zero-length array
* is returned.
*
* @deprecated Unused. Will be removed in Tomcat 10.
* Use {@link #findErrorPages()} instead.
*/
@Deprecated
public int[] findStatusPages();
......@@ -1876,4 +1901,26 @@ public interface Context extends Container, ContextBind {
public void decrementInProgressAsyncCount();
/**
* Configure whether Tomcat will attempt to create an upload target used by
* this web application if it does not exist when the web application
* attempts to use it.
*
* @param createUploadTargets {@code true} if Tomcat should attempt to
* create the upload target, otherwise {@code false}
*/
public void setCreateUploadTargets(boolean createUploadTargets);
/**
* Will Tomcat attempt to create an upload target used by this web
* application if it does not exist when the web application attempts to use
* it?
*
* @return {@code true} if Tomcat will attempt to create an upload target
* otherwise {@code false}
*/
public boolean getCreateUploadTargets();
}
......@@ -287,6 +287,7 @@ public class CoyoteAdapter implements Adapter {
req.getRequestProcessor().setWorkerThreadName(null);
// Recycle the wrapper request and response
if (!success || !request.isAsync()) {
updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
......@@ -392,14 +393,25 @@ public class CoyoteAdapter implements Adapter {
// Log only if processing was invoked.
// If postParseRequest() failed, it has already logged it.
Context context = request.getContext();
Host host = request.getHost();
// If the context is null, it is likely that the endpoint was
// shutdown, this connection closed and the request recycled in
// a different thread. That thread will have updated the access
// log so it is OK not to update the access log here in that
// case.
// The other possibility is that an error occurred early in
// processing and the request could not be mapped to a Context.
// Log via the host or engine in that case.
long time = System.currentTimeMillis() - req.getStartTime();
if (context != null) {
context.logAccess(request, response,
System.currentTimeMillis() - req.getStartTime(), false);
context.logAccess(request, response, time, false);
} else if (response.isError()) {
if (host != null) {
host.logAccess(request, response, time, false);
} else {
connector.getService().getContainer().logAccess(
request, response, time, false);
}
}
}
......@@ -407,6 +419,7 @@ public class CoyoteAdapter implements Adapter {
// Recycle the wrapper request and response
if (!async) {
updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
......@@ -414,6 +427,16 @@ public class CoyoteAdapter implements Adapter {
}
private void updateWrapperErrorCount(Request request, Response response) {
if (response.isError()) {
Wrapper wrapper = request.getWrapper();
if (wrapper != null) {
wrapper.incrementErrorCount();
}
}
}
@Override
public boolean prepare(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws IOException, ServletException {
......@@ -470,6 +493,7 @@ public class CoyoteAdapter implements Adapter {
ExceptionUtils.handleThrowable(t);
log.warn(sm.getString("coyoteAdapter.accesslogFail"), t);
} finally {
updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
......@@ -588,13 +612,12 @@ public class CoyoteAdapter implements Adapter {
// Always allow options
allow.append(", OPTIONS");
res.setHeader("Allow", allow.toString());
// Access log entry as processing won't reach AccessLogValve
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
} else {
res.setStatus(404);
res.setMessage("Not found");
response.sendError(400, "Invalid URI");
}
connector.getService().getContainer().logAccess(
request, response, 0, true);
return false;
}
MessageBytes decodedURI = req.decodedURI();
......@@ -613,29 +636,17 @@ public class CoyoteAdapter implements Adapter {
try {
req.getURLDecoder().convert(decodedURI, false);
} catch (IOException ioe) {
res.setStatus(400);
res.setMessage("Invalid URI: " + ioe.getMessage());
connector.getService().getContainer().logAccess(
request, response, 0, true);
return false;
response.sendError(400, "Invalid URI: " + ioe.getMessage());
}
// Normalization
if (!normalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI");
connector.getService().getContainer().logAccess(
request, response, 0, true);
return false;
response.sendError(400, "Invalid URI");
}
// Character decoding
convertURI(decodedURI, request);
// Check that the URI is still normalized
if (!checkNormalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI character encoding");
connector.getService().getContainer().logAccess(
request, response, 0, true);
return false;
response.sendError(400, "Invalid URI");
}
} else {
/* The URI is chars or String, and has been sent using an in-memory
......@@ -651,8 +662,7 @@ public class CoyoteAdapter implements Adapter {
CharChunk uriCC = decodedURI.getCharChunk();
int semicolon = uriCC.indexOf(';');
if (semicolon > 0) {
decodedURI.setChars
(uriCC.getBuffer(), uriCC.getStart(), semicolon);
decodedURI.setChars(uriCC.getBuffer(), uriCC.getStart(), semicolon);
}
}
......@@ -674,23 +684,30 @@ public class CoyoteAdapter implements Adapter {
Context versionContext = null;
boolean mapRequired = true;
if (response.isError()) {
// An error this early means the URI is invalid. Ensure invalid data
// is not passed to the mapper. Note we still want the mapper to
// find the correct host.
decodedURI.recycle();
}
while (mapRequired) {
// This will map the the latest version by default
connector.getService().getMapper().map(serverName, decodedURI,
version, request.getMappingData());
// If there is no context at this point, it is likely no ROOT context
// has been deployed
// If there is no context at this point, either this is a 404
// because no ROOT context has been deployed or the URI was invalid
// so no context could be mapped.
if (request.getContext() == null) {
res.setStatus(404);
res.setMessage("Not found");
// No context, so use host
Host host = request.getHost();
// Make sure there is a host (might not be during shutdown)
if (host != null) {
host.logAccess(request, response, 0, true);
// Don't overwrite an existing error
if (!response.isError()) {
response.sendError(404, "Not found");
}
return false;
// Allow processing to continue.
// If present, the error reporting valve will provide a response
// body.
return true;
}
// Now we have the context, we can parse the session ID from the URL
......@@ -834,12 +851,7 @@ public class CoyoteAdapter implements Adapter {
}
if (req.getRemoteUserNeedsAuthorization()) {
Authenticator authenticator = request.getContext().getAuthenticator();
if (authenticator == null) {
// No security constraints configured for the application so
// no need to authorize the user. Use the CoyotePrincipal to
// provide the authenticated user.
request.setUserPrincipal(new CoyotePrincipal(username));
} else if (!(authenticator instanceof AuthenticatorBase)) {
if (!(authenticator instanceof AuthenticatorBase)) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("coyoteAdapter.authorize", username));
}
......
......@@ -50,6 +50,8 @@ coyoteRequest.postTooLarge=Parameters were not parsed because the size of the po
coyoteRequest.chunkedPostTooLarge=Parameters were not parsed because the size of the posted data was too big. Because this request was a chunked request, it could not be processed further. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs.
coyoteRequest.alreadyAuthenticated=This request has already been authenticated
coyoteRequest.authenticate.ise=Cannot call authenticate() after the response has been committed
coyoteRequest.uploadCreate=Creating the temporary upload location [{0}] as it is required by the servlet [{1}]
coyoteRequest.uploadCreateFail=Failed to create the upload location [{0}]
coyoteRequest.uploadLocationInvalid=The temporary upload location [{0}] is not valid
coyoteRequest.sessionEndAccessFail=Exception triggered ending access to session while recycling request
coyoteRequest.sendfileNotCanonical=Unable to determine canonical name of file [{0}] specified for use with sendfile
......
......@@ -2785,12 +2785,7 @@ public class Request implements org.apache.catalina.servlet4preview.http.HttpSer
sm.getString("coyoteRequest.alreadyAuthenticated"));
}
Context context = getContext();
if (context.getAuthenticator() == null) {
throw new ServletException("no authenticator");
}
context.getAuthenticator().login(username, password, this);
getContext().getAuthenticator().login(username, password, this);
}
/**
......@@ -2872,6 +2867,15 @@ public class Request implements org.apache.catalina.servlet4preview.http.HttpSer
}
}
if (!location.exists() && context.getCreateUploadTargets()) {
log.warn(sm.getString("coyoteRequest.uploadCreate",
location.getAbsolutePath(), getMappingData().wrapper.getName()));
if (!location.mkdirs()) {
log.warn(sm.getString("coyoteRequest.uploadCreateFail",
location.getAbsolutePath()));
}
}
if (!location.isDirectory()) {
parameters.setParseFailedReason(FailReason.MULTIPART_CONFIG_INVALID);
partsParseException = new IOException(
......
......@@ -45,7 +45,6 @@ import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Session;
import org.apache.catalina.Wrapper;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.SessionConfig;
import org.apache.coyote.ActionCode;
......@@ -409,14 +408,7 @@ public class Response implements HttpServletResponse {
* @return <code>false</code> if the error flag was already set
*/
public boolean setError() {
boolean result = getCoyoteResponse().setError();
if (result) {
Wrapper wrapper = getRequest().getWrapper();
if (wrapper != null) {
wrapper.incrementErrorCount();
}
}
return result;
return getCoyoteResponse().setError();
}
......@@ -851,7 +843,11 @@ public class Response implements HttpServletResponse {
return;
}
String charset = getContext().getCharset(locale);
// In some error handling scenarios, the context is unknown
// (e.g. a 404 when a ROOT context is not present)
Context context = getContext();
if (context != null) {
String charset = context.getCharset(locale);
if (charset != null) {
try {
getCoyoteResponse().setCharacterEncoding(charset);
......@@ -860,6 +856,7 @@ public class Response implements HttpServletResponse {
}
}
}
}
// --------------------------------------------------- HttpResponse Methods
......
......@@ -23,6 +23,7 @@ import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
......@@ -32,11 +33,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.catalina.Context;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.servlet4preview.http.PushBuilder;
import org.apache.catalina.util.SessionConfig;
import org.apache.coyote.ActionCode;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.http.parser.HttpParser;
......@@ -70,6 +73,7 @@ public class ApplicationPushBuilder implements PushBuilder {
private String path;
private String queryString;
private String sessionId;
private String userName;
public ApplicationPushBuilder(Request catalinaRequest, HttpServletRequest request) {
......@@ -108,7 +112,6 @@ public class ApplicationPushBuilder implements PushBuilder {
if (request.getQueryString() != null) {
referer.append('?');
referer.append(request.getQueryString());
}
addHeader("referer", referer.toString());
......@@ -156,6 +159,21 @@ public class ApplicationPushBuilder implements PushBuilder {
cookies.add(new Cookie(responseCookie.getName(), responseCookie.getValue()));
}
}
List<String> cookieValues = new ArrayList<>(1);
cookieValues.add(generateCookieHeader(cookies,
catalinaRequest.getContext().getCookieProcessor()));
headers.put("cookie", cookieValues);
// Authentication
if (catalinaRequest.getPrincipal() != null) {
if ((session == null) || catalinaRequest.getSessionInternal(false).getPrincipal() == null
|| !(context.getAuthenticator() instanceof AuthenticatorBase)
|| !((AuthenticatorBase) context.getAuthenticator()).getCache()) {
// Set a username only if there is no session cache for the principal
userName = catalinaRequest.getPrincipal().getName();
}
setHeader("authorization", "x-push");
}
}
@Override
......@@ -183,8 +201,8 @@ public class ApplicationPushBuilder implements PushBuilder {
@Override
public ApplicationPushBuilder method(String method) {
String upperMethod = method.trim().toUpperCase();
if (DISALLOWED_METHODS.contains(upperMethod)) {
String upperMethod = method.trim().toUpperCase(Locale.ENGLISH);
if (DISALLOWED_METHODS.contains(upperMethod) || upperMethod.length() == 0) {
throw new IllegalArgumentException(
sm.getString("applicationPushBuilder.methodInvalid", upperMethod));
}
......@@ -326,7 +344,14 @@ public class ApplicationPushBuilder implements PushBuilder {
pushTarget.addPathParameter(sessionPathParameterName, sessionId);
}
if (addSessionCookie) {
cookies.add(new Cookie(sessionCookieName, sessionId));
String sessionCookieHeader = sessionCookieName + "=" + sessionId;
MessageBytes mb = pushTarget.getMimeHeaders().getValue("cookie");
if (mb == null) {
mb = pushTarget.getMimeHeaders().addValue("cookie");
mb.setString(sessionCookieHeader);
} else {
mb.setString(mb.getString() + ";" + sessionCookieHeader);
}
}
}
......@@ -344,14 +369,15 @@ public class ApplicationPushBuilder implements PushBuilder {
pushTarget.queryString().setString(pushQueryString + "&" +queryString);
}
// Cookies
setHeader("cookie", generateCookieHeader(cookies,
catalinaRequest.getContext().getCookieProcessor()));
// Authorization
if (userName != null) {
pushTarget.getRemoteUser().setString(userName);
pushTarget.setRemoteUserNeedsAuthorization(true);
}
coyoteRequest.action(ActionCode.PUSH_REQUEST, pushTarget);
// Reset for next call to this method
pushTarget = null;
path = null;
headers.remove("if-none-match");
headers.remove("if-modified-since");
......
......@@ -180,7 +180,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
}
@Override
public void dispatch(ServletContext context, String path) {
public void dispatch(ServletContext servletContext, String path) {
synchronized (asyncContextLock) {
if (log.isDebugEnabled()) {
logDebug("dispatch ");
......@@ -197,7 +197,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
request.setAttribute(ASYNC_PATH_INFO, request.getPathInfo());
request.setAttribute(ASYNC_QUERY_STRING, request.getQueryString());
}
final RequestDispatcher requestDispatcher = context.getRequestDispatcher(path);
final RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
if (!(requestDispatcher instanceof AsyncDispatcher)) {
throw new UnsupportedOperationException(
sm.getString("asyncContextImpl.noAsyncDispatcher"));
......@@ -206,11 +206,16 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
(AsyncDispatcher) requestDispatcher;
final ServletRequest servletRequest = getRequest();
final ServletResponse servletResponse = getResponse();
// https://bz.apache.org/bugzilla/show_bug.cgi?id=63246
// Take a local copy as the dispatch may complete the
// request/response and that in turn may trigger recycling of this
// object before the in-progress count can be decremented
final Context context = this.context;
this.dispatch = new AsyncRunnable(
request, applicationDispatcher, servletRequest, servletResponse);
this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, null);
clearServletRequestResponse();
this.context.decrementInProgressAsyncCount();
context.decrementInProgressAsyncCount();
}
}
......
......@@ -191,7 +191,6 @@ standardEngine.jvmRouteFail=Failed to set Engine's jvmRoute attribute from syste
standardEngine.noHost=No Host matches server name [{0}]
standardEngine.notHost=Child of an Engine must be a Host
standardEngine.notParent=Engine cannot have a parent Container
standardHost.asyncStateError=An asynchronous request was received for processing that was neither an async dispatch nor an error to process
standardHost.clientAbort=Remote Client Aborted Request, IOException: [{0}]
standardHost.invalidErrorReportValveClass=Couldn''t load specified error report valve class: [{0}]
standardHost.noContext=No Context configured to process this request
......
......@@ -60,6 +60,7 @@ import org.apache.naming.ResourceLinkRef;
import org.apache.naming.ResourceRef;
import org.apache.naming.ServiceRef;
import org.apache.naming.TransactionRef;
import org.apache.naming.factory.Constants;
import org.apache.naming.factory.ResourceLinkFactory;
import org.apache.tomcat.util.descriptor.web.ContextEjb;
import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
......@@ -1010,16 +1011,21 @@ public class NamingContextListener
if (("javax.sql.DataSource".equals(ref.getClassName()) ||
"javax.sql.XADataSource".equals(ref.getClassName())) &&
resource.getSingleton()) {
Object actualResource = null;
try {
ObjectName on = createObjectName(resource);
Object actualResource = envCtx.lookup(resource.getName());
actualResource = envCtx.lookup(resource.getName());
Registry.getRegistry(null, null).registerComponent(actualResource, on, null);
objectNames.put(resource.getName(), on);
} catch (Exception e) {
log.warn(sm.getString("naming.jmxRegistrationFailed", e));
}
// Bug 63210. DBCP2 DataSources require an explicit close. This goes
// further and cleans up and AutoCloseable DataSource by default.
if (actualResource instanceof AutoCloseable && !resource.getCloseMethodConfigured()) {
resource.setCloseMethod("close");
}
}
}
......