Commit 9cbeed3f authored by Emmanuel Bourg's avatar Emmanuel Bourg

Imported Upstream version 8.0.36

parent 7a55deee
......@@ -269,7 +269,30 @@ You can build them by using the following commands:
open the command prompt used for the build with the "Run as administrator"
option.
3. Build the release:
3. Configure the code signing service
ASF committers performing official releases will need to configure the code
signing service so that the Windows installer is signed during the build
process. The following properties need to be added to the build.properties
file:
# Location of GPG executable (used only for releases)
# Code signing of Windows installer
do.codesigning=true
codesigning.user=request-via-pmc
codesigning.pwd=request-via-pmc
codesigning.partnercode=request-via-pmc
codesigning.service=Microsoft Signing
Release managers will be provided with the necessary credentials by the PMC.
It will also be necessary to enable TLS 1.1 and TLS 1.2 by default (they are
disabled by default on Java 7) for the build process to communicate with the
code signing service. The simplest way is by setting the ANT_OPTS
environment variable. E.g. (for Windows):
set ANT_OPTS=-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2
4. Build the release:
cd ${tomcat.source}
ant release
......
......@@ -77,6 +77,10 @@ rem
rem -agentlib:jdwp=transport=%JPDA_TRANSPORT%,
rem address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
rem
rem JSSE_OPTS (Optional) Java runtime options used to control the TLS
rem implementation when JSSE is used. Default is:
rem "-Djdk.tls.ephemeralDHKeySize=2048"
rem
rem LOGGING_CONFIG (Optional) Override Tomcat's logging config file
rem Example (all one line)
rem set LOGGING_CONFIG="-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties"
......@@ -188,6 +192,11 @@ goto juliClasspathDone
set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone
if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
set LOGGING_CONFIG=-Dnop
if not exist "%CATALINA_BASE%\conf\logging.properties" goto noJuliConfig
......
......@@ -82,6 +82,10 @@
# -agentlib:jdwp=transport=$JPDA_TRANSPORT,
# address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND
#
# JSSE_OPTS (Optional) Java runtime options used to control the TLS
# implementation when JSSE is used. Default is:
# "-Djdk.tls.ephemeralDHKeySize=2048"
#
# CATALINA_PID (Optional) Path of the file which should contains the pid
# of the catalina startup java process, when start (fork) is
# used
......@@ -93,16 +97,23 @@
# LOGGING_MANAGER (Optional) Override Tomcat's logging manager
# Example (all one line)
# LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
#
# USE_NOHUP (Optional) If set to the string true the start command will
# use nohup so that the Tomcat process will ignore any hangup
# signals. Default is "false" unless running on HP-UX in which
# case the default is "true"
# -----------------------------------------------------------------------------
# OS specific support. $var _must_ be set to either true or false.
cygwin=false
darwin=false
os400=false
hpux=false
case "`uname`" in
CYGWIN*) cygwin=true;;
Darwin*) darwin=true;;
OS400*) os400=true;;
HP-UX*) hpux=true;;
esac
# resolve links - $0 may be a softlink
......@@ -229,6 +240,11 @@ if $cygwin; then
JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
fi
if [ -z "$JSSE_OPTS" ] ; then
JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
fi
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS"
# Set juli LogManager config file if it is present and an override has not been issued
if [ -z "$LOGGING_CONFIG" ]; then
if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
......@@ -247,6 +263,18 @@ fi
# org.apache.catalina.security.SecurityListener
#JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`"
if [ -z "$USE_NOHUP" ]; then
if $hpux; then
USE_NOHUP="true"
else
USE_NOHUP="false"
fi
fi
unset _NOHUP
if [ "$USE_NOHUP" = "true" ]; then
_NOHUP=nohup
fi
# ----- Execute The Requested Command -----------------------------------------
# Bugzilla 37848: only output this if we have a TTY
......@@ -387,7 +415,7 @@ elif [ "$1" = "start" ] ; then
echo "Using Security Manager"
fi
shift
eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
-Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
......@@ -398,7 +426,7 @@ elif [ "$1" = "start" ] ; then
>> "$CATALINA_OUT" 2>&1 "&"
else
eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
......
......@@ -25,7 +25,7 @@
# ----- Version Control Flags -----
version.major=8
version.minor=0
version.build=33
version.build=36
version.patch=0
version.suffix=
......@@ -157,7 +157,7 @@ jdt.loc.1=http://archive.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj
jdt.loc.2=http://download.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj-${jdt.version}.jar
# ----- Tomcat native library -----
tomcat-native.version=1.2.5
tomcat-native.version=1.2.7
tomcat-native.home=${base.path}/tomcat-native-${tomcat-native.version}
tomcat-native.tar.gz=${tomcat-native.home}/tomcat-native.tar.gz
tomcat-native.loc.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz
......@@ -166,7 +166,7 @@ tomcat-native.win.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-nativ
tomcat-native.win.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-win32-bin.zip
# ----- NSIS, version 2.0 or later -----
nsis.version=2.50
nsis.version=2.51
nsis.home=${base.path}/nsis-${nsis.version}
nsis.exe=${nsis.home}/makensis.exe
nsis.installoptions.dll=${nsis.home}/Plugins/InstallOptions.dll
......@@ -236,11 +236,11 @@ dojo-js.loc=http://download.dojotoolkit.org/release-1.1.1/dojo-release-1.1.1.tar
dojo-js.jar=${dojo-js.home}/dojo/dojo.js
# ----- Cobertura code coverage tool -----
cobertura.version=2.0.3
cobertura.version=2.1.1
cobertura.home=${base.path}/cobertura-${cobertura.version}
cobertura.jar=${cobertura.home}/cobertura-${cobertura.version}.jar
cobertura.lib=${cobertura.home}/lib
cobertura.loc=${base-sf.loc}/cobertura/cobertura-2.0.3-bin.tar.gz
cobertura.loc=${base-sf.loc}/cobertura/cobertura-2.1.1-bin.tar.gz
# ----- Findbugs -----
findbugs.version=3.0.1
......
......@@ -146,7 +146,6 @@
<property name="tomcat-embed-el-sources.jar" value="${tomcat.embed.sources}/tomcat-embed-el-src.jar"/>
<property name="tomcat-embed-websocket-sources.jar" value="${tomcat.embed.sources}/tomcat-embed-websocket-src.jar"/>
<property name="tomcat-embed-juli-sources.jar" value="${tomcat.embed.sources}/tomcat-embed-logging-juli-src.jar"/>
<property name="tomcat-embed-dbcp-sources.jar" value="${tomcat.embed.sources}/tomcat-dbcp-src.jar"/>
<!-- Extras JARs & source JARs -->
<property name="tomcat-juli-extras.jar" value="${tomcat.extras}/tomcat-juli.jar"/>
......@@ -1942,7 +1941,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="256m" >
maxmemory="512m"
failonerror="true">
<classpath>
<path refid="compile.classpath"/>
<path refid="tomcat.webservices.classpath"/>
......@@ -1961,7 +1961,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="256m" >
maxmemory="512m"
failonerror="true">
<classpath>
<path refid="compile.classpath"/>
<path refid="tomcat.webservices.classpath"/>
......@@ -1980,7 +1981,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="256m" >
maxmemory="512m"
failonerror="true">
<classpath>
<path refid="compile.classpath"/>
<path refid="tomcat.webservices.classpath"/>
......@@ -1999,7 +2001,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="256m" >
maxmemory="512m"
failonerror="true">
<classpath>
<path refid="compile.classpath"/>
<path refid="tomcat.webservices.classpath"/>
......@@ -2017,7 +2020,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="256m" >
maxmemory="512m"
failonerror="true">
<classpath>
<path refid="compile.classpath"/>
<path refid="tomcat.webservices.classpath"/>
......
......@@ -136,7 +136,8 @@ xom-*.jar
# has been excluded by a broad file name pattern in the jarsToSkip list.
# The list of JARs to scan may be over-ridden at a Context level for individual
# scan types by configuring a JarScanner with a nested JarScanFilter.
tomcat.util.scan.StandardJarScanFilter.jarsToScan=log4j-core*.jar,log4j-taglib*.jar,log4javascript*.jar
tomcat.util.scan.StandardJarScanFilter.jarsToScan=\
log4j-core*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
# String cache configuration.
tomcat.util.buf.StringCache.byte.enabled=true
......
......@@ -482,9 +482,14 @@ public interface ServletRequest {
public boolean isAsyncSupported();
/**
* @return TODO
* Get the current AsyncContext.
*
* @return The current AsyncContext
*
* @throws IllegalStateException if the request is not in asynchronous mode
* @since Servlet 3.0 TODO SERVLET3 - Add comments
* (i.e. @link #isAsyncStarted() is {@code false})
*
* @since Servlet 3.0
*/
public AsyncContext getAsyncContext();
......
......@@ -314,4 +314,12 @@ public final class Globals {
@Deprecated // Will be removed in Tomcat 8.5.x
public static final boolean IS_IBM_JVM = JreVendor.IS_IBM_JVM;
/**
* Name of the ServletContext attribute under which we store the context
* Realm's CredentialHandler (if both the Realm and the CredentialHandler
* exist).
*/
public static final String CREDENTIAL_HANDLER
= "org.apache.catalina.CredentialHandler";
}
......@@ -23,6 +23,7 @@ import java.io.Serializable;
import java.security.Principal;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpServletRequest;
......@@ -52,7 +53,7 @@ public class SingleSignOnEntry implements Serializable {
// Marked as transient so special handling can be applied to serialization
protected transient Principal principal = null;
protected ConcurrentHashMap<SingleSignOnSessionKey,SingleSignOnSessionKey> sessionKeys =
protected ConcurrentMap<SingleSignOnSessionKey,SingleSignOnSessionKey> sessionKeys =
new ConcurrentHashMap<>();
protected String username = null;
......
......@@ -271,7 +271,7 @@ public class CoyoteAdapter implements Adapter {
}
boolean comet = false;
boolean success = true;
AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
AsyncContextImpl asyncConImpl = request.getAsyncContextInternal();
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
try {
if (!request.isAsync() && !comet) {
......@@ -425,6 +425,12 @@ public class CoyoteAdapter implements Adapter {
AtomicBoolean error = new AtomicBoolean(false);
res.action(ActionCode.IS_ERROR, error);
if (error.get()) {
if (request.isAsyncCompleting()) {
// Connection will be forcibly closed which will prevent
// completion happening at the usual point. Need to trigger
// call to onComplete() here.
res.action(ActionCode.ASYNC_POST_PROCESS, null);
}
success = false;
}
} catch (IOException e) {
......@@ -537,8 +543,7 @@ public class CoyoteAdapter implements Adapter {
}
}
AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
if (asyncConImpl != null) {
if (request.isAsync()) {
async = true;
ReadListener readListener = req.getReadListener();
if (readListener != null && request.isFinished()) {
......@@ -554,6 +559,15 @@ public class CoyoteAdapter implements Adapter {
request.getContext().unbind(false, oldCL);
}
}
Throwable throwable =
(Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// If an async request was started, is not going to end once
// this container thread finishes and an error occurred, trigger
// the async error process
if (!request.isAsyncCompleting() && throwable != null) {
request.getAsyncContextInternal().setErrorState(throwable, true);
}
} else if (!comet) {
request.finishRequest();
response.finishResponse();
......
......@@ -73,6 +73,7 @@ inputBuffer.requiresNonBlocking=Not available in non blocking mode
outputBuffer.writeNull=The String argument to write(String,int,int) may not be null
request.asyncNotSupported=A filter or servlet of the current chain does not support asynchronous operations.
request.notAsync=It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
requestFacade.nullRequest=The request object has been recycled and is no longer associated with this facade
......
......@@ -279,10 +279,13 @@ public class OutputBuffer extends Writer
cb.flushBuffer();
}
if ((!coyoteResponse.isCommitted())
&& (coyoteResponse.getContentLengthLong() == -1)) {
if ((!coyoteResponse.isCommitted()) && (coyoteResponse.getContentLengthLong() == -1) &&
!coyoteResponse.getRequest().method().equals("HEAD")) {
// If this didn't cause a commit of the response, the final content
// length can be calculated
// length can be calculated. Only do this if this is not a HEAD
// request since in that case no body should have been written and
// setting a value of zero here will result in an explicit content
// length of zero being set on the response.
if (!coyoteResponse.isCommitted()) {
coyoteResponse.setContentLength(bb.getLength());
}
......
......@@ -419,7 +419,7 @@ public class Request
/**
* AsyncContext
*/
protected volatile AsyncContextImpl asyncContext = null;
private volatile AsyncContextImpl asyncContext = null;
protected Boolean asyncSupported = null;
......@@ -1682,7 +1682,14 @@ public class Request
@Override
public AsyncContext getAsyncContext() {
return this.asyncContext;
if (!isAsyncStarted()) {
throw new IllegalStateException(sm.getString("request.notAsync"));
}
return asyncContext;
}
public AsyncContextImpl getAsyncContextInternal() {
return asyncContext;
}
@Override
......
......@@ -32,6 +32,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.NamingException;
import javax.servlet.Filter;
......@@ -65,6 +66,7 @@ import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.mapper.MappingData;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.URLEncoder;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
......@@ -81,8 +83,7 @@ import org.apache.tomcat.util.res.StringManager;
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class ApplicationContext
implements ServletContext {
public class ApplicationContext implements ServletContext {
protected static final boolean STRICT_SERVLET_COMPLIANCE;
......@@ -133,8 +134,7 @@ public class ApplicationContext
/**
* List of read only attributes for this context.
*/
private final Map<String,String> readOnlyAttributes =
new ConcurrentHashMap<>();
private final Map<String,String> readOnlyAttributes = new ConcurrentHashMap<>();
/**
......@@ -170,8 +170,7 @@ public class ApplicationContext
/**
* The merged context initialization parameters for this Context.
*/
private final ConcurrentHashMap<String,String> parameters =
new ConcurrentHashMap<>();
private final ConcurrentMap<String,String> parameters = new ConcurrentHashMap<>();
/**
......@@ -520,11 +519,11 @@ public class ApplicationContext
mappingData.recycle();
// Construct a RequestDispatcher to process this request
return new ApplicationDispatcher
(wrapper, uriCC.toString(), wrapperPath, pathInfo,
queryString, null);
String encodedUri = URLEncoder.DEFAULT.encode(uriCC.toString());
// Construct a RequestDispatcher to process this request
return new ApplicationDispatcher(wrapper, encodedUri, wrapperPath, pathInfo,
queryString, null);
}
......
......@@ -391,7 +391,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
processRequest(request,response,state);
}
if (request.getAsyncContext() != null) {
if (request.isAsyncStarted()) {
// An async request was started during the forward, don't close the
// response as it may be written to during the async handling
return;
......
......@@ -97,29 +97,6 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
@Override
public void fireOnComplete() {
// Fire the listeners
doFireOnComplete();
// The application doesn't know it has to stop read and/or writing until
// it receives the complete event so the request and response have to be
// closed after firing the event.
try {
// First of all ensure that any data written to the response is
// written to the I/O layer.
request.getResponse().finishResponse();
// Close the request and the response.
request.getCoyoteRequest().action(ActionCode.END_REQUEST, null);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// Catch this here and allow async context complete to continue
// normally so a dispatch takes place which ensures that the
// request and response objects are correctly recycled.
log.debug(sm.getString("asyncContextImpl.finishResponseError"), t);
}
}
private void doFireOnComplete() {
List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
......@@ -191,7 +168,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
@Override
public void dispatch(String path) {
check();
dispatch(request.getServletContext(),path);
dispatch(getRequest().getServletContext(), path);
}
@Override
......@@ -284,6 +261,8 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
check();
AsyncListenerWrapper wrapper = new AsyncListenerWrapper();
wrapper.setListener(listener);
wrapper.setServletRequest(servletRequest);
wrapper.setServletResponse(servletResponse);
listeners.add(wrapper);
}
......@@ -390,9 +369,7 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
dispatch = null;
runnable.run();
if (!request.isAsync()) {
// Uses internal method since we don't want the request/response
// to be closed. That will be handled in the adapter.
doFireOnComplete();
fireOnComplete();
}
} catch (RuntimeException x) {
// doInternalComplete(true);
......
......@@ -20,29 +20,33 @@ import java.io.IOException;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AsyncListenerWrapper {
private AsyncListener listener = null;
private ServletRequest servletRequest = null;
private ServletResponse servletResponse = null;
public void fireOnStartAsync(AsyncEvent event) throws IOException {
listener.onStartAsync(event);
listener.onStartAsync(customizeEvent(event));
}
public void fireOnComplete(AsyncEvent event) throws IOException {
listener.onComplete(event);
listener.onComplete(customizeEvent(event));
}
public void fireOnTimeout(AsyncEvent event) throws IOException {
listener.onTimeout(event);
listener.onTimeout(customizeEvent(event));
}
public void fireOnError(AsyncEvent event) throws IOException {
listener.onError(event);
listener.onError(customizeEvent(event));
}
......@@ -56,4 +60,22 @@ public class AsyncListenerWrapper {
}
public void setServletRequest(ServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
public void setServletResponse(ServletResponse servletResponse) {
this.servletResponse = servletResponse;
}
private AsyncEvent customizeEvent(AsyncEvent event) {
if (servletRequest != null && servletResponse != null) {
return new AsyncEvent(event.getAsyncContext(), servletRequest, servletResponse,
event.getThrowable());
} else {
return event;
}
}
}
......@@ -816,12 +816,6 @@ public abstract class ContainerBase extends LifecycleMBeanBase
return;
}
synchronized(children) {
if (children.get(child.getName()) == null)
return;
children.remove(child.getName());
}
try {
if (child.getState().isAvailable()) {
child.stop();
......@@ -830,8 +824,6 @@ public abstract class ContainerBase extends LifecycleMBeanBase
log.error("ContainerBase.removeChild: stop: ", e);
}
fireContainerEvent(REMOVE_CHILD_EVENT, child);
try {
// child.destroy() may have already been called which would have
// triggered this call. If that is the case, no need to destroy the
......@@ -843,6 +835,13 @@ public abstract class ContainerBase extends LifecycleMBeanBase
log.error("ContainerBase.removeChild: destroy: ", e);
}
synchronized(children) {
if (children.get(child.getName()) == null)
return;
children.remove(child.getName());
}
fireContainerEvent(REMOVE_CHILD_EVENT, child);
}
......
......@@ -89,19 +89,6 @@ public class JreMemoryLeakPreventionListener implements LifecycleListener {
this.awtThreadProtection = awtThreadProtection;
}
/**
* Protect against the memory leak caused when the