diff --git a/CVE-2018-11784.patch b/CVE-2018-11784.patch
new file mode 100644
index 0000000..4bf1bb2
--- /dev/null
+++ b/CVE-2018-11784.patch
@@ -0,0 +1,27 @@
+--- a/webapps/docs/changelog.xml 2018-06-20 13:35:40.000000000 -0400
++++ b/webapps/docs/changelog_1.xml 2019-06-24 08:35:44.801000000 -0400
+@@ -164,6 +164,10 @@
+ the authenticated Subject to include at least one Principal of a type
+ specified by userClassNames. (markt)
+
++
++ When generating a redirect to a directory in the Default Servlet, avoid
++ generating a protocol relative redirect. (markt)
++
+
+
+
+--- a/java/org/apache/catalina/servlets/DefaultServlet.java 2018-06-20 13:35:34.000000000 -0400
++++ b/java/org/apache/catalina/servlets/DefaultServlet_1.java 2019-06-24 08:40:08.699000000 -0400
+@@ -1324,6 +1324,10 @@ public class DefaultServlet extends Http
+ location.append('?');
+ location.append(request.getQueryString());
+ }
++ // Avoid protocol relative redirects
++ while (location.length() > 1 && location.charAt(1) == '/') {
++ location.deleteCharAt(0);
++ }
+ response.sendRedirect(response.encodeRedirectURL(location.toString()));
+ }
+
+
diff --git a/CVE-2019-0199-1.patch b/CVE-2019-0199-1.patch
new file mode 100644
index 0000000..d05be52
--- /dev/null
+++ b/CVE-2019-0199-1.patch
@@ -0,0 +1,75 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:17:08 1852697
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:01 1852698
+@@ -42,8 +42,10 @@
+ public class Http2Protocol implements UpgradeProtocol {
+
+ static final long DEFAULT_READ_TIMEOUT = 10000;
+- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
+ static final long DEFAULT_WRITE_TIMEOUT = 10000;
++ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
++ static final long DEFAULT_STREAM_READ_TIMEOUT = 20000;
++ static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000;
+ // The HTTP/2 specification recommends a minimum default of 100
+ static final long DEFAULT_MAX_CONCURRENT_STREAMS = 200;
+ // Maximum amount of streams which can be concurrently executed over
+@@ -57,9 +59,14 @@
+ private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8);
+
+ // All timeouts in milliseconds
++ // These are the socket level timeouts
+ private long readTimeout = DEFAULT_READ_TIMEOUT;
+- private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
+ private long writeTimeout = DEFAULT_WRITE_TIMEOUT;
++ private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
++ // These are the stream level timeouts
++ private long streamReadTimeout = DEFAULT_STREAM_READ_TIMEOUT;
++ private long streamWriteTimeout = DEFAULT_STREAM_WRITE_TIMEOUT;
++
+ private long maxConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS;
+ private int maxConcurrentStreamExecution = DEFAULT_MAX_CONCURRENT_STREAM_EXECUTION;
+ // If a lower initial value is required, set it here but DO NOT change the
+@@ -145,6 +152,16 @@
+ }
+
+
++ public long getWriteTimeout() {
++ return writeTimeout;
++ }
++
++
++ public void setWriteTimeout(long writeTimeout) {
++ this.writeTimeout = writeTimeout;
++ }
++
++
+ public long getKeepAliveTimeout() {
+ return keepAliveTimeout;
+ }
+@@ -155,13 +172,23 @@
+ }
+
+
+- public long getWriteTimeout() {
+- return writeTimeout;
++ public long getStreamReadTimeout() {
++ return streamReadTimeout;
+ }
+
+
+- public void setWriteTimeout(long writeTimeout) {
+- this.writeTimeout = writeTimeout;
++ public void setStreamReadTimeout(long streamReadTimeout) {
++ this.streamReadTimeout = streamReadTimeout;
++ }
++
++
++ public long getStreamWriteTimeout() {
++ return streamWriteTimeout;
++ }
++
++
++ public void setStreamWriteTimeout(long streamWriteTimeout) {
++ this.streamWriteTimeout = streamWriteTimeout;
+ }
+
+
diff --git a/CVE-2019-0199-10.patch b/CVE-2019-0199-10.patch
new file mode 100644
index 0000000..fef53b2
--- /dev/null
+++ b/CVE-2019-0199-10.patch
@@ -0,0 +1,13 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:03:54.790000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:05:12.133000000 -0400
+@@ -905,7 +905,7 @@ class Stream extends AbstractStream impl
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+ }
+
+- if (inBuffer.position() == 0) {
++ if (inBuffer.position() == 0 && isActive() && !isInputFinished()) {
+ String msg = sm.getString("stream.inputBuffer.readTimeout");
+ StreamException se = new StreamException(
+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
+
diff --git a/CVE-2019-0199-11.patch b/CVE-2019-0199-11.patch
new file mode 100644
index 0000000..33e7526
--- /dev/null
+++ b/CVE-2019-0199-11.patch
@@ -0,0 +1,21 @@
+--- a/java/org/apache/coyote/http2/Stream.java 2019-06-11 21:24:19.998000000 -0400
++++ b/java/org/apache/coyote/http2/Stream_1.java 2019-06-11 21:26:18.329000000 -0400
+@@ -221,7 +221,7 @@ class Stream extends AbstractStream impl
+ if (windowSize == 0) {
+ String msg = sm.getString("stream.writeTimeout");
+ StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+ // Prevent the application making further writes
+ streamOutputBuffer.closed = true;
+ // Prevent Tomcat's error handling trying to write
+@@ -908,7 +908,7 @@ class Stream extends AbstractStream impl
+ if (inBuffer.position() == 0 && isActive() && !isInputFinished()) {
+ String msg = sm.getString("stream.inputBuffer.readTimeout");
+ StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+ // Trigger a reset once control returns to Tomcat
+ coyoteResponse.setError();
+ streamOutputBuffer.reset = se;
+
diff --git a/CVE-2019-0199-2.patch b/CVE-2019-0199-2.patch
new file mode 100644
index 0000000..c1c1fda
--- /dev/null
+++ b/CVE-2019-0199-2.patch
@@ -0,0 +1,246 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java
+--- apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java 2018-06-20 13:35:33.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java 2019-06-09 20:28:02.836000000 -0400
+@@ -33,6 +33,7 @@ import javax.servlet.http.HttpServletRes
+
+ import org.apache.catalina.Globals;
+ import org.apache.coyote.ActionCode;
++import org.apache.coyote.CloseNowException;
+ import org.apache.coyote.Response;
+ import org.apache.tomcat.util.buf.C2BConverter;
+ import org.apache.tomcat.util.res.StringManager;
+@@ -326,6 +327,13 @@ public class OutputBuffer extends Writer
+ // real write to the adapter
+ try {
+ coyoteResponse.doWrite(buf);
++ } catch (CloseNowException e) {
++ // Catch this sub-class as it requires specific handling.
++ // Examples where this exception is thrown:
++ // - HTTP/2 stream timeout
++ // Prevent further output for this response
++ closed = true;
++ throw e;
+ } catch (IOException e) {
+ // An IOException on a write is almost always due to
+ // the remote client aborting the request. Wrap this
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java
+--- apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java 2018-06-20 13:35:34.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java 2019-06-09 20:33:27.596000000 -0400
+@@ -36,6 +36,7 @@ import org.apache.catalina.connector.Cli
+ import org.apache.catalina.connector.Request;
+ import org.apache.catalina.connector.Response;
+ import org.apache.catalina.valves.ValveBase;
++import org.apache.coyote.CloseNowException;
+ import org.apache.tomcat.util.ExceptionUtils;
+ import org.apache.tomcat.util.buf.MessageBytes;
+ import org.apache.tomcat.util.log.SystemLogHandler;
+@@ -201,7 +202,7 @@ final class StandardWrapperValve
+ }
+
+ }
+- } catch (ClientAbortException e) {
++ } catch (ClientAbortException | CloseNowException e) {
+ throwable = e;
+ exception(request, response, e);
+ } catch (IOException e) {
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:34:32.307000000 -0400
+@@ -93,6 +93,7 @@ stream.reset.fail=Connection [{0}], Stre
+ stream.reset.receive=Connection [{0}], Stream [{1}], Reset received due to [{2}]
+ stream.reset.send=Connection [{0}], Stream [{1}], Reset sent due to [{2}]
+ stream.trailerHeader.noEndOfStream=Connection [{0}], Stream [{1}], The trailer headers did not include the end of stream flag
++stream.writeTimeout=Timeout waiting for client to increase flow control window to permit stream data to be written
+
+ stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer
+ stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch
+@@ -149,4 +150,4 @@ upgradeHandler.writeHeaders=Connection [
+ upgradeHandler.writePushHeaders=Connection [{0}], Stream [{1}], Pushed stream [{2}], EndOfStream [{3}]
+
+ writeStateMachine.endWrite.ise=It is illegal to specify [{0}] for the new state once a write has completed
+-writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}]
+\ No newline at end of file
++writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}]
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:38:30.109000000 -0400
+@@ -211,7 +211,21 @@ class Stream extends AbstractStream impl
+ }
+ try {
+ if (block) {
+- wait();
++ wait(handler.getProtocol().getStreamWriteTimeout());
++ windowSize = getWindowSize();
++ if (windowSize == 0) {
++ String msg = sm.getString("stream.writeTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ // Prevent the application making further writes
++ streamOutputBuffer.closed = true;
++ // Prevent Tomcat's error handling trying to write
++ coyoteResponse.setError();
++ coyoteResponse.setErrorReported();
++ // Trigger a reset once control returns to Tomcat
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
+ } else {
+ return 0;
+ }
+@@ -221,7 +235,6 @@ class Stream extends AbstractStream impl
+ // Stream.
+ throw new IOException(e);
+ }
+- windowSize = getWindowSize();
+ }
+ int allocation;
+ if (windowSize < reservation) {
+@@ -660,6 +673,9 @@ class Stream extends AbstractStream impl
+ return !streamOutputBuffer.endOfStreamSent;
+ }
+
++ StreamException getResetException() {
++ return streamOutputBuffer.reset;
++ }
+
+ private static void push(final Http2UpgradeHandler handler, final Request request,
+ final Stream stream) throws IOException {
+@@ -707,6 +723,7 @@ class Stream extends AbstractStream impl
+ private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
+ private volatile long written = 0;
+ private volatile boolean closed = false;
++ private volatile StreamException reset = null;
+ private volatile boolean endOfStreamSent = false;
+
+ /* The write methods are synchronized to ensure that only one thread at
+@@ -800,9 +817,14 @@ class Stream extends AbstractStream impl
+
+ @Override
+ public final void end() throws IOException {
+- closed = true;
+- flush(true);
+- writeTrailers();
++ if (reset != null) {
++ throw new CloseNowException(reset);
++ }
++ if (!closed) {
++ closed = true;
++ flush(true);
++ writeTrailers();
++ }
+ }
+
+ /**
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java 2019-06-09 20:40:08.789000000 -0400
+@@ -78,10 +78,13 @@ class StreamProcessor extends AbstractPr
+ stream.getIdentifier()), Http2Error.INTERNAL_ERROR);
+ stream.close(ce);
+ } else if (!getErrorState().isIoAllowed()) {
+- StreamException se = new StreamException(sm.getString(
+- "streamProcessor.error.stream", stream.getConnectionId(),
+- stream.getIdentifier()), Http2Error.INTERNAL_ERROR,
+- stream.getIdentifier().intValue());
++ StreamException se = stream.getResetException();
++ if (se == null) {
++ se = new StreamException(sm.getString(
++ "streamProcessor.error.stream", stream.getConnectionId(),
++ stream.getIdentifier()), Http2Error.INTERNAL_ERROR,
++ stream.getIdentifier().intValue());
++ }
+ stream.close(se);
+ }
+ }
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2018-06-20 13:35:38.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:41:45.113000000 -0400
+@@ -486,8 +486,10 @@ public abstract class Http2TestBase exte
+ Http2Protocol http2Protocol = new Http2Protocol();
+ // Short timeouts for now. May need to increase these for CI systems.
+ http2Protocol.setReadTimeout(2000);
+- http2Protocol.setKeepAliveTimeout(5000);
+ http2Protocol.setWriteTimeout(2000);
++ http2Protocol.setKeepAliveTimeout(5000);
++ http2Protocol.setStreamReadTimeout(1000);
++ http2Protocol.setStreamWriteTimeout(1000);
+ http2Protocol.setMaxConcurrentStreams(maxConcurrentStreams);
+ connector.addUpgradeProtocol(http2Protocol);
+ }
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 1969-12-31 19:00:00.000000000 -0500
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:42:38.095000000 -0400
+@@ -0,0 +1,73 @@
++/*
++ * 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.coyote.http2;
++
++import org.junit.Assert;
++import org.junit.Before;
++import org.junit.Test;
++
++public class TestHttp2Timeouts extends Http2TestBase {
++
++ @Override
++ @Before
++ public void http2Connect() throws Exception {
++ super.http2Connect();
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
++ }
++
++
++ /*
++ * Simple request won't fill buffer so timeout will occur in Tomcat internal
++ * code during response completion.
++ */
++ @Test
++ public void testClientWithEmptyWindow() throws Exception {
++ sendSimpleGetRequest(3);
++
++ // Settings
++ parser.readFrame(false);
++ // Headers
++ parser.readFrame(false);
++
++ output.clearTrace();
++
++ parser.readFrame(false);
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++
++ /*
++ * Large request will fill buffer so timeout will occur in application code
++ * during response write (when Tomcat commits the response and flushes the
++ * buffer as a result of the buffer filling).
++ */
++ @Test
++ public void testClientWithEmptyWindowLargeResponse() throws Exception {
++ sendLargeGetRequest(3);
++
++ // Settings
++ parser.readFrame(false);
++ // Headers
++ parser.readFrame(false);
++
++ output.clearTrace();
++
++ parser.readFrame(false);
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++}
diff --git a/CVE-2019-0199-3.patch b/CVE-2019-0199-3.patch
new file mode 100644
index 0000000..0494f3b
--- /dev/null
+++ b/CVE-2019-0199-3.patch
@@ -0,0 +1,202 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:45:15.320000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:46:36.793000000 -0400
+@@ -98,6 +98,7 @@ stream.writeTimeout=Timeout waiting for
+ stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer
+ stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch
+ stream.inputBuffer.empty=The Stream input buffer is empty. Waiting for more data
++stream.inputBuffer.readTimeout=Timeout waiting to read data from client
+ stream.inputBuffer.reset=Stream reset
+ stream.inputBuffer.signal=Data added to inBuffer when read thread is waiting. Signalling that thread to continue
+
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:45:15.321000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:48:21.509000000 -0400
+@@ -888,10 +888,22 @@ class Stream extends AbstractStream impl
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("stream.inputBuffer.empty"));
+ }
+- inBuffer.wait();
++
++ inBuffer.wait(handler.getProtocol().getStreamReadTimeout());
++
+ if (reset) {
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+ }
++
++ if (inBuffer.position() == 0) {
++ String msg = sm.getString("stream.inputBuffer.readTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ // Trigger a reset once control returns to Tomcat
++ coyoteResponse.setError();
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
+ } catch (InterruptedException e) {
+ // Possible shutdown / rst or similar. Use an
+ // IOException to signal to the client that further I/O
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:45:15.323000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:53:54.809000000 -0400
+@@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Locale;
++import java.util.Map;
+ import java.util.Random;
+
+ import javax.net.SocketFactory;
+@@ -300,6 +301,22 @@ public abstract class Http2TestBase exte
+ }
+ }
+
++ protected void sendParameterPostRequest(int streamId, byte[] padding, String body,
++ long contentLength, boolean useExpectation) throws IOException {
++ byte[] headersFrameHeader = new byte[9];
++ ByteBuffer headersPayload = ByteBuffer.allocate(128);
++ byte[] dataFrameHeader = new byte[9];
++ ByteBuffer dataPayload = ByteBuffer.allocate(128);
++
++ buildPostRequest(headersFrameHeader, headersPayload, useExpectation,
++ "application/x-www-form-urlencoded", contentLength, "/parameter", dataFrameHeader,
++ dataPayload, padding, null, null, streamId);
++ writeFrame(headersFrameHeader, headersPayload);
++ if (body != null) {
++ dataPayload.put(body.getBytes(StandardCharsets.ISO_8859_1));
++ writeFrame(dataFrameHeader, dataPayload);
++ }
++ }
+
+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
+@@ -311,14 +328,29 @@ public abstract class Http2TestBase exte
+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
+ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) {
++ buildPostRequest(headersFrameHeader, headersPayload, useExpectation, null, -1, "/simple",
++ dataFrameHeader, dataPayload, padding, trailersFrameHeader, trailersPayload, streamId);
++ }
++
++ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
++ boolean useExpectation, String contentType, long contentLength, String path,
++ byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
++ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) {
++
+ MimeHeaders headers = new MimeHeaders();
+ headers.addValue(":method").setString("POST");
+ headers.addValue(":scheme").setString("http");
+- headers.addValue(":path").setString("/simple");
++ headers.addValue(":path").setString(path);
+ headers.addValue(":authority").setString("localhost:" + getPort());
+ if (useExpectation) {
+ headers.addValue("expect").setString("100-continue");
+ }
++ if (contentType != null) {
++ headers.addValue("content-type").setString(contentType);
++ }
++ if (contentLength > -1) {
++ headers.addValue("content-length").setLong(contentLength);
++ }
+ hpackEncoder.encode(headers, headersPayload);
+
+ headersPayload.flip();
+@@ -507,6 +539,8 @@ public abstract class Http2TestBase exte
+ ctxt.addServletMappingDecoded("/large", "large");
+ Tomcat.addServlet(ctxt, "cookie", new CookieServlet());
+ ctxt.addServletMappingDecoded("/cookie", "cookie");
++ Tomcat.addServlet(ctxt, "parameter", new ParameterServlet());
++ ctxt.addServletMappingDecoded("/parameter", "parameter");
+
+ tomcat.start();
+ }
+@@ -1205,6 +1239,24 @@ public abstract class Http2TestBase exte
+ }
+ }
+
++
++ static class ParameterServlet extends HttpServlet {
++
++ private static final long serialVersionUID = 1L;
++
++ @Override
++ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
++ throws ServletException, IOException {
++
++ Map params = req.getParameterMap();
++
++ resp.setContentType("text/plain");
++ resp.setCharacterEncoding("UTF-8");
++
++ resp.getWriter().print(params.size());
++ }
++ }
++
+
+ static class SettingValue {
+ private final int setting;
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:45:15.323000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:57:22.652000000 -0400
+@@ -26,7 +26,6 @@ public class TestHttp2Timeouts extends H
+ @Before
+ public void http2Connect() throws Exception {
+ super.http2Connect();
+- sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+ }
+
+
+@@ -36,7 +35,7 @@ public class TestHttp2Timeouts extends H
+ */
+ @Test
+ public void testClientWithEmptyWindow() throws Exception {
+- sendSimpleGetRequest(3);
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+
+ // Settings
+ parser.readFrame(false);
+@@ -57,6 +56,7 @@ public class TestHttp2Timeouts extends H
+ */
+ @Test
+ public void testClientWithEmptyWindowLargeResponse() throws Exception {
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+ sendLargeGetRequest(3);
+
+ // Settings
+@@ -70,4 +70,36 @@ public class TestHttp2Timeouts extends H
+ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
+ }
+
++ /*
++ * Timeout with app reading request body directly.
++ */
++ @Test
++ public void testClientPostsNoBody() throws Exception {
++ sendSimplePostRequest(3, null, false);
++
++ // Headers
++ parser.readFrame(false);
++ output.clearTrace();
++
++ parser.readFrame(false);
++
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++
++ /*
++ * Timeout with app processing parameters.
++ */
++ @Test
++ public void testClientPostsNoParameters() throws Exception {
++ sendParameterPostRequest(3, null, null, 10, false);
++
++ // Headers
++ parser.readFrame(false);
++ output.clearTrace();
++
++ parser.readFrame(false);
++
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
+ }
diff --git a/CVE-2019-0199-4.patch b/CVE-2019-0199-4.patch
new file mode 100644
index 0000000..78e7858
--- /dev/null
+++ b/CVE-2019-0199-4.patch
@@ -0,0 +1,38 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:14 1852700
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701
+@@ -41,9 +41,9 @@
+
+ public class Http2Protocol implements UpgradeProtocol {
+
+- static final long DEFAULT_READ_TIMEOUT = 10000;
+- static final long DEFAULT_WRITE_TIMEOUT = 10000;
+- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
++ static final long DEFAULT_READ_TIMEOUT = 5000;
++ static final long DEFAULT_WRITE_TIMEOUT = 5000;
++ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = 20000;
+ static final long DEFAULT_STREAM_READ_TIMEOUT = 20000;
+ static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000;
+ // The HTTP/2 specification recommends a minimum default of 100
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:14 1852700
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701
+@@ -329,9 +329,16 @@
+ }
+ }
+ }
+- // No more frames to read so switch to the keep-alive
+- // timeout.
+- socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout());
++
++ if (activeRemoteStreamCount.get() == 0) {
++ // No streams currently active. Use the keep-alive
++ // timeout for the connection.
++ socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout());
++ } else {
++ // Streams currently active. Individual streams have
++ // timeouts so keep the connection open.
++ socketWrapper.setReadTimeout(-1);
++ }
+ } catch (Http2Exception ce) {
+ // Really ConnectionException
+ if (log.isDebugEnabled()) {
+
diff --git a/CVE-2019-0199-5.patch b/CVE-2019-0199-5.patch
new file mode 100644
index 0000000..a21d1a3
--- /dev/null
+++ b/CVE-2019-0199-5.patch
@@ -0,0 +1,143 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:22 1852702
+@@ -54,6 +54,8 @@
+ // This default is defined by the HTTP/2 specification
+ static final int DEFAULT_INITIAL_WINDOW_SIZE = (1 << 16) - 1;
+
++ static final int DEFAULT_OVERHEAD_COUNT_FACTOR = 1;
++
+ private static final String HTTP_UPGRADE_NAME = "h2c";
+ private static final String ALPN_NAME = "h2";
+ private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8);
+@@ -79,6 +81,8 @@
+ private int maxHeaderSize = Constants.DEFAULT_MAX_HEADER_SIZE;
+ private int maxTrailerCount = Constants.DEFAULT_MAX_TRAILER_COUNT;
+ private int maxTrailerSize = Constants.DEFAULT_MAX_TRAILER_SIZE;
++ private int overheadCountFactor = DEFAULT_OVERHEAD_COUNT_FACTOR;
++
+ private boolean initiatePingDisabled = false;
+ private boolean useSendfile = true;
+ // Compression
+@@ -306,6 +310,16 @@
+ }
+
+
++ public int getOverheadCountFactor() {
++ return overheadCountFactor;
++ }
++
++
++ public void setOverheadCountFactor(int overheadCountFactor) {
++ this.overheadCountFactor = overheadCountFactor;
++ }
++
++
+ public void setInitiatePingDisabled(boolean initiatePingDisabled) {
+ this.initiatePingDisabled = initiatePingDisabled;
+ }
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:22 1852702
+@@ -30,6 +30,7 @@
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentLinkedQueue;
+ import java.util.concurrent.atomic.AtomicInteger;
++import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicReference;
+
+ import javax.servlet.http.WebConnection;
+@@ -139,6 +140,9 @@
+ private AtomicInteger streamConcurrency = null;
+ private Queue queuedRunnable = null;
+
++ // Track 'overhead' frames vs 'request/response' frames
++ private final AtomicLong overheadCount = new AtomicLong(-10);
++
+
+ Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest) {
+ super (STREAM_ID_ZERO);
+@@ -330,6 +334,10 @@
+ }
+ }
+
++ if (overheadCount.get() > 0) {
++ throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM);
++ }
++
+ if (activeRemoteStreamCount.get() == 0) {
+ // No streams currently active. Use the keep-alive
+ // timeout for the connection.
+@@ -638,6 +646,9 @@
+ log.debug(sm.getString("upgradeHandler.writeBody", connectionId, stream.getIdentifier(),
+ Integer.toString(len)));
+ }
++
++ reduceOverheadCount();
++
+ // Need to check this now since sending end of stream will change this.
+ boolean writeable = stream.canWrite();
+ byte[] header = new byte[9];
+@@ -1193,6 +1204,16 @@
+ }
+
+
++ private void reduceOverheadCount() {
++ overheadCount.decrementAndGet();
++ }
++
++
++ private void increaseOverheadCount() {
++ overheadCount.addAndGet(getProtocol().getOverheadCountFactor());
++ }
++
++
+ // ----------------------------------------------- Http2Parser.Input methods
+
+ @Override
+@@ -1247,6 +1268,7 @@
+
+ @Override
+ public ByteBuffer startRequestBodyFrame(int streamId, int payloadSize) throws Http2Exception {
++ reduceOverheadCount();
+ Stream stream = getStream(streamId, true);
+ stream.checkState(FrameType.DATA);
+ stream.receivedData(payloadSize);
+@@ -1291,6 +1313,8 @@
+ // determines if a new stream is created or if this stream is ignored.
+ checkPauseState();
+
++ reduceOverheadCount();
++
+ if (connectionState.get().isNewStreamAllowed()) {
+ Stream stream = getStream(streamId, false);
+ if (stream == null) {
+@@ -1340,6 +1364,9 @@
+ throw new ConnectionException(sm.getString("upgradeHandler.dependency.invalid",
+ getConnectionId(), Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR);
+ }
++
++ increaseOverheadCount();
++
+ Stream stream = getStream(streamId, false);
+ if (stream == null) {
+ stream = createRemoteStream(streamId);
+@@ -1384,6 +1411,9 @@
+
+ @Override
+ public void setting(Setting setting, long value) throws ConnectionException {
++
++ increaseOverheadCount();
++
+ // Special handling required
+ if (setting == Setting.INITIAL_WINDOW_SIZE) {
+ long oldValue = remoteSettings.getInitialWindowSize();
+@@ -1425,6 +1455,9 @@
+
+ @Override
+ public void pingReceive(byte[] payload, boolean ack) throws IOException {
++ if (!ack) {
++ increaseOverheadCount();
++ }
+ pingManager.receivePing(payload, ack);
+ }
+
+
diff --git a/CVE-2019-0199-6.patch b/CVE-2019-0199-6.patch
new file mode 100644
index 0000000..ef1ed8d
--- /dev/null
+++ b/CVE-2019-0199-6.patch
@@ -0,0 +1,51 @@
+--- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:22 1852702
++++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:26 1852703
+@@ -125,9 +125,9 @@
+
+
+ The time, in milliseconds, that Tomcat will wait between HTTP/2 frames
+- before closing the connection. Negative values will be treated as an
+- infinite timeout. If not specified, a default value of -1
+- will be used.
++ when there is no active Stream before closing the connection. Negative
++ values will be treated as an infinite timeout. If not specified, a default
++ value of 20000 will be used.
+
+
+
+@@ -192,7 +192,24 @@
+ The time, in milliseconds, that Tomcat will wait for additional data
+ when a partial HTTP/2 frame has been received. Negative values will be
+ treated as an infinite timeout. If not specified, a default value of
+- 10000 will be used.
++ 5000 will be used.
++
++
++
++ The time, in milliseconds, that Tomcat will wait for additional data
++ frames to arrive for the stream when an application is performing a
++ blocking I/O read and additional data is required. Negative values will be
++ treated as an infinite timeout. If not specified, a default value of
++ 20000 will be used.
++
++
++
++ The time, in milliseconds, that Tomcat will wait for additional window
++ update frames to arrive for the stream and/or conenction when an
++ application is performing a blocking I/O write and the stream and/or
++ connection flow control window is too small for the write to complete.
++ Negative values will be treated as an infinite timeout. If not specified,
++ a default value of 20000 will be used.
+
+
+
+@@ -204,7 +221,7 @@
+ The time, in milliseconds, that Tomcat will wait to write additional
+ data when an HTTP/2 frame has been partially written. Negative values will
+ be treated as an infinite timeout. If not specified, a default value of
+- 10000 will be used.
++ 5000 will be used.
+
+
+
+
diff --git a/CVE-2019-0199-7.patch b/CVE-2019-0199-7.patch
new file mode 100644
index 0000000..0369108
--- /dev/null
+++ b/CVE-2019-0199-7.patch
@@ -0,0 +1,32 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:59:53.027000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:02:31.878000000 -0400
+@@ -211,7 +211,12 @@ class Stream extends AbstractStream impl
+ }
+ try {
+ if (block) {
+- wait(handler.getProtocol().getStreamWriteTimeout());
++ long writeTimeout = handler.getProtocol().getStreamWriteTimeout();
++ if (writeTimeout < 0) {
++ wait();
++ } else {
++ wait(writeTimeout);
++ }
+ windowSize = getWindowSize();
+ if (windowSize == 0) {
+ String msg = sm.getString("stream.writeTimeout");
+@@ -889,7 +894,12 @@ class Stream extends AbstractStream impl
+ log.debug(sm.getString("stream.inputBuffer.empty"));
+ }
+
+- inBuffer.wait(handler.getProtocol().getStreamReadTimeout());
++ long readTimeout = handler.getProtocol().getStreamReadTimeout();
++ if (readTimeout < 0) {
++ inBuffer.wait();
++ } else {
++ inBuffer.wait(readTimeout);
++ }
+
+ if (reset) {
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+
diff --git a/CVE-2019-0199-8.patch b/CVE-2019-0199-8.patch
new file mode 100644
index 0000000..f921ed2
--- /dev/null
+++ b/CVE-2019-0199-8.patch
@@ -0,0 +1,24 @@
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:30 1852704
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:34 1852705
+@@ -335,7 +335,9 @@
+ }
+
+ if (overheadCount.get() > 0) {
+- throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM);
++ throw new ConnectionException(
++ sm.getString("upgradeHandler.tooMuchOverhead", connectionId),
++ Http2Error.ENHANCE_YOUR_CALM);
+ }
+
+ if (activeRemoteStreamCount.get() == 0) {
+--- tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:30 1852704
++++ tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:34 1852705
+@@ -141,6 +141,7 @@
+ upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is not writable
+ upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}]
+ upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams
++upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed
+ upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected
+ upgradeHandler.unexpectedEos=Unexpected end of stream
+ upgradeHandler.upgrade=Connection [{0}], HTTP/1.1 upgrade to stream [1]
+
diff --git a/CVE-2019-0199-9.patch b/CVE-2019-0199-9.patch
new file mode 100644
index 0000000..78c22a1
--- /dev/null
+++ b/CVE-2019-0199-9.patch
@@ -0,0 +1,24 @@
+--- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:34 1852705
++++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:38 1852706
+@@ -188,6 +188,20 @@
+ The default value is an empty String (regexp matching disabled).
+
+
++
++ The factor to apply when counting overhead frames to determine if a
++ connection has too high an overhead and should be closed. The overhead
++ count starts at -10. The count is decreased for each
++ data frame sent or received and each headers frame received. The count is
++ increased by the overheadCountFactorfor each setting
++ received, priority frame received and ping received. If the overhead count
++ exceeds zero, the connection is closed. A value of less than
++ 1 disables this protection. In normal usage a value of
++ 3 or more will close the connection before any streams can
++ complete. If not specified, a default value of 1 will be
++ used.
++
++
+
+ The time, in milliseconds, that Tomcat will wait for additional data
+ when a partial HTTP/2 frame has been received. Negative values will be
+
diff --git a/CVE-2019-0221.patch b/CVE-2019-0221.patch
new file mode 100644
index 0000000..cc2c366
--- /dev/null
+++ b/CVE-2019-0221.patch
@@ -0,0 +1,44 @@
+From 15fcd166ea2c1bb79e8541b8e1a43da9c452ceea Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Mon, 11 Mar 2019 11:33:03 +0000
+Subject: [PATCH] Escape debug output to aid readability
+
+reason: Escape debug output to aid readability, fix CVE CVE-2019-0221
+https://github.com/apache/tomcat/commit/15fcd16
+
+---
+ java/org/apache/catalina/ssi/SSIPrintenv.java | 3 +--
+ webapps/docs/changelog.xml | 3 +++
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/java/org/apache/catalina/ssi/SSIPrintenv.java b/java/org/apache/catalina/ssi/SSIPrintenv.java
+index 97470b2..092542f 100644
+--- a/java/org/apache/catalina/ssi/SSIPrintenv.java
++++ b/java/org/apache/catalina/ssi/SSIPrintenv.java
+@@ -41,8 +41,7 @@ public class SSIPrintenv implements SSICommand {
+ } else {
+ Collection variableNames = ssiMediator.getVariableNames();
+ for (String variableName : variableNames) {
+- String variableValue = ssiMediator
+- .getVariableValue(variableName);
++ String variableValue = ssiMediator.getVariableValue(variableName, "entity");
+ //This shouldn't happen, since all the variable names must
+ // have values
+ if (variableValue == null) {
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 697cf07..cbd3961 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -52,6 +52,9 @@
+ Expires header as required by HTTP specification
+ (RFC 7231, 7234). (kkolinko)
+
++
++ Encode the output of the SSI printenv command. (markt)
++
+
+
+
+--
+1.8.3.1
+
diff --git a/CVE-2019-10072-1.patch b/CVE-2019-10072-1.patch
new file mode 100644
index 0000000..93ea148
--- /dev/null
+++ b/CVE-2019-10072-1.patch
@@ -0,0 +1,129 @@
+From 7f748eb6bfaba5207c89dbd7d5adf50fae847145 Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Tue, 30 Apr 2019 22:18:12 +0100
+Subject: [PATCH] Expand HTTP/2 timeout handling to connection window
+ exhaustion on write.
+
+https://github.com/apache/tomcat/commit/7f748eb
+---
+ .../coyote/http2/Http2UpgradeHandler.java | 32 +++++++++++++++++--
+ java/org/apache/coyote/http2/Stream.java | 27 +++++++++-------
+ webapps/docs/changelog.xml | 4 +++
+ 3 files changed, 50 insertions(+), 13 deletions(-)
+
+diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+index 1d8770a..ab0369a 100644
+--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
++++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+@@ -794,7 +794,26 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+ }
+ if (allocation == 0) {
+ try {
+- stream.wait();
++ // Connection level window is empty. Although this
++ // request is for a stream, use the connection
++ // timeout
++ long writeTimeout = protocol.getWriteTimeout();
++ if (writeTimeout < 0) {
++ stream.wait();
++ } else {
++ stream.wait(writeTimeout);
++ }
++ // Has this stream been granted an allocation
++ int[] value = backLogStreams.get(stream);
++ if (value[1] == 0) {
++ // No allocation
++ // Close the connection. Do this first since
++ // closing the stream will raise an exception
++ close();
++ // Close the stream (in app code so need to
++ // signal to app stream is closing)
++ stream.doWriteTimeout();
++ }
+ } catch (InterruptedException e) {
+ throw new IOException(sm.getString(
+ "upgradeHandler.windowSizeReservationInterrupted", connectionId,
+@@ -985,11 +1004,20 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+
+
+ private void close() {
+- connectionState.set(ConnectionState.CLOSED);
++ ConnectionState previous = connectionState.getAndSet(ConnectionState.CLOSED);
++ if (previous == ConnectionState.CLOSED) {
++ // Already closed
++ return;
++ }
++
+ for (Stream stream : streams.values()) {
+ // The connection is closing. Close the associated streams as no
+ // longer required.
+ stream.receiveReset(Http2Error.CANCEL.getCode());
++ // Release any streams waiting for an allocation
++ synchronized (stream) {
++ stream.notifyAll();
++ }
+ }
+ try {
+ socketWrapper.close();
+diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
+index 2c4f67e..8b87b12 100644
+--- a/java/org/apache/coyote/http2/Stream.java
++++ b/java/org/apache/coyote/http2/Stream.java
+@@ -219,17 +219,7 @@ class Stream extends AbstractStream implements HeaderEmitter {
+ }
+ windowSize = getWindowSize();
+ if (windowSize == 0) {
+- String msg = sm.getString("stream.writeTimeout");
+- StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+- // Prevent the application making further writes
+- streamOutputBuffer.closed = true;
+- // Prevent Tomcat's error handling trying to write
+- coyoteResponse.setError();
+- coyoteResponse.setErrorReported();
+- // Trigger a reset once control returns to Tomcat
+- streamOutputBuffer.reset = se;
+- throw new CloseNowException(msg, se);
++ doWriteTimeout();
+ }
+ } else {
+ return 0;
+@@ -252,6 +242,21 @@ class Stream extends AbstractStream implements HeaderEmitter {
+ }
+
+
++ void doWriteTimeout() throws CloseNowException {
++ String msg = sm.getString("stream.writeTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
++ // Prevent the application making further writes
++ streamOutputBuffer.closed = true;
++ // Prevent Tomcat's error handling trying to write
++ coyoteResponse.setError();
++ coyoteResponse.setErrorReported();
++ // Trigger a reset once control returns to Tomcat
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
++
++
+ @Override
+ public final void emitHeader(String name, String value) throws HpackException {
+ if (log.isDebugEnabled()) {
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index a8abf2d..5665df4 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -362,6 +362,10 @@
+
+ Update the internal fork of Commons DBCP 2 to 2.4.0. (markt)
+
++
++ Expand HTTP/2 timeout handling to include connection window exhaustion
++ on write. (markt)
++
+
+
+
+--
+2.19.1
diff --git a/CVE-2019-10072-2.patch b/CVE-2019-10072-2.patch
new file mode 100644
index 0000000..4619c59
--- /dev/null
+++ b/CVE-2019-10072-2.patch
@@ -0,0 +1,28 @@
+From ada725a50a60867af3422c8e612aecaeea856a9a Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Fri, 3 May 2019 21:52:41 +0100
+Subject: [PATCH] Fix test failures. Handle full allocation case.
+
+https://github.com/apache/tomcat/commit/ada725a
+---
+ java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+index ab0369a..cadae44 100644
+--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
++++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+@@ -804,8 +804,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+ stream.wait(writeTimeout);
+ }
+ // Has this stream been granted an allocation
++ // Note: If the stream in not in this Map then the
++ // requested write has been fully allocated
+ int[] value = backLogStreams.get(stream);
+- if (value[1] == 0) {
++ if (value != null && value[1] == 0) {
+ // No allocation
+ // Close the connection. Do this first since
+ // closing the stream will raise an exception
+--
+2.19.1
diff --git a/apache-tomcat-9.0.10-src.tar.gz b/apache-tomcat-9.0.10-src.tar.gz
new file mode 100644
index 0000000..017333d
Binary files /dev/null and b/apache-tomcat-9.0.10-src.tar.gz differ
diff --git a/el-api-OSGi-MANIFEST.MF b/el-api-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..69b797f
--- /dev/null
+++ b/el-api-OSGi-MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Export-Package: javax.el;version="2.2.0"
+Bundle-Vendor: %bundleProvider
+Bundle-ClassPath: .
+Bundle-Version: 2.2.0
+Bundle-Name: %bundleName
+Bundle-Localization: plugin
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: javax.el
+DynamicImport-Package: org.apache.el
+Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J
+ 2SE-1.3
+
diff --git a/jasper-OSGi-MANIFEST.MF b/jasper-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..ad34978
--- /dev/null
+++ b/jasper-OSGi-MANIFEST.MF
@@ -0,0 +1,40 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.jasper;version="8.0.26",org.apache.jasper.c
+ ompiler;version="8.0.26",org.apache.jasper.compiler.tagplugin;version
+ ="8.0.26",org.apache.jasper.resources;version="8.0.26",org.apache.jas
+ per.runtime;version="8.0.26",org.apache.jasper.security;version="7.0.
+ 19",org.apache.jasper.servlet;version="8.0.26",org.apache.jasper.tagp
+ lugins.jstl;version="8.0.26",org.apache.jasper.tagplugins.jstl.core;v
+ ersion="8.0.26",org.apache.jasper.util;version="8.0.26",org.apache.ja
+ sper.xmlparser;version="8.0.26"
+Bundle-Vendor: %bundleProvider
+Bundle-ClassPath: .
+Bundle-Version: 8.0.26
+Bundle-Localization: plugin
+Bundle-Name: %bundleName
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.apache.jasper
+Import-Package: javax.servlet;version="[2.4.0, 3.0.0]",javax.servlet.h
+ ttp;version="[2.4.0, 3.0.0]",javax.servlet.jsp;version="[2.0.0, 2.2.0
+ ]",javax.servlet.jsp.el;version="[2.0.0, 2.2.0]",javax.servlet.jsp.re
+ sources;version="[2.0.0, 2.2.0]",javax.servlet.jsp.tagext;version="[2
+ .0.0, 2.2.0]",javax.servlet.resources;version="[2.4.0, 3.0.0]",javax.
+ xml.parsers,org.apache.commons.el;version="[1.0.0,2.0.0)",org.apache.
+ commons.logging;version="[1.0.0,2.0.0)",org.apache.tools.ant;resoluti
+ on:=optional,org.apache.tools.ant.taskdefs;resolution:=optional,org.a
+ pache.tools.ant.types;resolution:=optional,org.apache.tools.ant.util;
+ resolution:=optional,org.w3c.dom,org.xml.sax,org.xml.sax.ext,org.xml.
+ sax.helpers,org.apache.tomcat;version="8.0.26",org.apache.juli.loggin
+ g;version="8.0.26",javax.el;version="2.2.0",org.eclipse.jdt.internal.
+ compiler,org.eclipse.jdt.internal.compiler.parser,org.eclipse.jdt.int
+ ernal.compiler.parser.diagnose,org.eclipse.jdt.internal.compiler.flow
+ ,org.eclipse.jdt.internal.compiler.util,org.eclipse.jdt.internal.comp
+ iler.impl,org.eclipse.jdt.internal.compiler.lookup,org.eclipse.jdt.in
+ ternal.compiler.codegen,org.eclipse.jdt.internal.compiler.batch,org.e
+ clipse.jdt.internal.compiler.classfmt,org.eclipse.jdt.internal.compil
+ er.ast,org.eclipse.jdt.internal.compiler.problem,org.eclipse.jdt.inte
+ rnal.compiler.env,org.eclipse.jdt.internal.core.util,org.eclipse.jdt.
+ core.compiler
+Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J
+ 2SE-1.3
+
diff --git a/jasper-el-OSGi-MANIFEST.MF b/jasper-el-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..14e4282
--- /dev/null
+++ b/jasper-el-OSGi-MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.el;version="7.0.21"
+Bundle-Vendor: %bundleProvider
+Bundle-ClassPath: .
+Bundle-Version: 8.0.26
+Bundle-Name: %bundleName
+Bundle-Localization: plugin
+Bundle-ManifestVersion: 2
+Import-Package: javax.el;version="2.2"
+Bundle-SymbolicName: org.apache.el
+Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J
+ 2SE-1.3
+
diff --git a/jsp-api-OSGi-MANIFEST.MF b/jsp-api-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..62bc00d
--- /dev/null
+++ b/jsp-api-OSGi-MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-Vendor: %bundleProvider
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
+Bundle-Name: %bundleName
+Bundle-SymbolicName: javax.servlet.jsp
+Export-Package: javax.servlet.jsp; version=2.2,javax.servlet.jsp.el; v
+ ersion=2.2,javax.servlet.jsp.resources; version=2.2,javax.servlet.jsp
+ .tagext; version=2.2
+Bundle-Version: 2.2.0.v200806031607
+Bundle-ManifestVersion: 2
+Import-Package: javax.servlet; version=3.0,javax.servlet.http; version
+ =3.0,javax.servlet.resources; version=3.0,javax.el;version="2.2.0"
diff --git a/servlet-api-OSGi-MANIFEST.MF b/servlet-api-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..3938935
--- /dev/null
+++ b/servlet-api-OSGi-MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1,J2SE-1.4
+Bundle-SymbolicName: javax.servlet
+Bundle-ManifestVersion: 2
+Bundle-Name: %bundleName
+Bundle-Localization: plugin
+Bundle-Version: 3.0.0
+Bundle-Vendor: %bundleProvider
+Export-Package: javax.servlet;version="3.0",
+ javax.servlet;version="2.6",
+ javax.servlet.http;version="3.0",
+ javax.servlet.http;version="2.6",
+ javax.servlet.annotation;version="2.6",
+ javax.servlet.descriptor;version="3.0",
+ javax.servlet.descriptor;version="2.6",
+ javax.servlet.resources;version="3.0",
+ javax.servlet.resources;version="2.6"
diff --git a/tomcat-9.0-bootstrap-MANIFEST.MF.patch b/tomcat-9.0-bootstrap-MANIFEST.MF.patch
new file mode 100644
index 0000000..81ee283
--- /dev/null
+++ b/tomcat-9.0-bootstrap-MANIFEST.MF.patch
@@ -0,0 +1,9 @@
+--- tomcat/res/META-INF/bootstrap.jar.manifest.orig 2010-04-06 10:11:09.000000000 -0600
++++ tomcat/res/META-INF/bootstrap.jar.manifest 2010-04-06 10:45:56.000000000 -0600
+@@ -1,6 +1,5 @@
+ Manifest-Version: 1.0
+ Main-Class: org.apache.catalina.startup.Bootstrap
+-Class-Path: commons-daemon.jar
+ Specification-Title: Apache Tomcat Bootstrap
+ Specification-Version: @VERSION_MAJOR_MINOR@
+ Specification-Vendor: Apache Software Foundation
diff --git a/tomcat-9.0-digest.script b/tomcat-9.0-digest.script
new file mode 100644
index 0000000..ce4aa0f
--- /dev/null
+++ b/tomcat-9.0-digest.script
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# tomcat-digest script
+# JPackage Project
+
+# Source functions library
+if [ -f /usr/share/java-utils/java-functions ] ; then
+ . /usr/share/java-utils/java-functions
+else
+ echo "Can't find functions library, aborting"
+ exit 1
+fi
+
+# Get the tomcat config (use this for environment specific settings)
+if [ -z "${TOMCAT_CFG}" ]; then
+ TOMCAT_CFG="/etc/tomcat/tomcat.conf"
+fi
+
+if [ -r "$TOMCAT_CFG" ]; then
+ . $TOMCAT_CFG
+fi
+
+set_javacmd
+
+# CLASSPATH munging
+if [ -n "$JSSE_HOME" ]; then
+ CLASSPATH="${CLASSPATH}:$(build-classpath jcert jnet jsse 2>/dev/null)"
+fi
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/bootstrap.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar"
+export CLASSPATH
+
+# Configuration
+MAIN_CLASS="org.apache.catalina.startup.Tool"
+BASE_FLAGS="-Dcatalina.home=\"$CATALINA_HOME\""
+BASE_OPTIONS=""
+BASE_JARS="commons-daemon tomcat/catalina servlet tomcat/tomcat-util tomcat/tomcat-coyote tomcat/tomcat-api tomcat/tomcat-util-scan"
+
+# Set parameters
+set_classpath $BASE_JARS
+set_flags $BASE_FLAGS
+set_options $BASE_OPTIONS
+
+# Let's start
+run -server org.apache.catalina.realm.RealmBase "$@"
diff --git a/tomcat-9.0-jsvc.service b/tomcat-9.0-jsvc.service
new file mode 100644
index 0000000..f480324
--- /dev/null
+++ b/tomcat-9.0-jsvc.service
@@ -0,0 +1,22 @@
+# Systemd unit file for tomcat
+#
+# To create clones of this service:
+# 1) By default SERVICE_NAME=tomcat. When cloned, the value must be defined
+# before tomcat-sysd is called.
+# 2) Create /etc/sysconfig/${SERVICE_NAME} from /etc/sysconfig/tomcat
+# to override tomcat defaults
+
+[Unit]
+Description=Apache Tomcat Web Application Container JSVC wrapper
+After=syslog.target network.target
+
+[Service]
+Type=simple
+EnvironmentFile=/etc/tomcat/tomcat.conf
+Environment="NAME=" "USE_JSVC=true"
+EnvironmentFile=-/etc/sysconfig/tomcat
+ExecStart=/usr/libexec/tomcat/server start
+ExecStop=/usr/libexec/tomcat/server stop
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tomcat-9.0-tomcat-users-webapp.patch b/tomcat-9.0-tomcat-users-webapp.patch
new file mode 100644
index 0000000..107040e
--- /dev/null
+++ b/tomcat-9.0-tomcat-users-webapp.patch
@@ -0,0 +1,17 @@
+--- tomcat/conf/tomcat-users.xml~ 2008-01-28 17:41:06.000000000 -0500
++++ tomcat/conf/tomcat-users.xml 2008-03-07 19:40:07.000000000 -0500
+@@ -23,4 +23,14 @@
+
+
+ -->
++
++
++
++
++
++
++
++
++
++
+
diff --git a/tomcat-9.0-tool-wrapper.script b/tomcat-9.0-tool-wrapper.script
new file mode 100644
index 0000000..949d46d
--- /dev/null
+++ b/tomcat-9.0-tool-wrapper.script
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# tomcat-digest script
+# JPackage Project
+
+# Source functions library
+if [ -f /usr/share/java-utils/java-functions ] ; then
+ . /usr/share/java-utils/java-functions
+else
+ echo "Can't find functions library, aborting"
+ exit 1
+fi
+
+# Get the tomcat config (use this for environment specific settings)
+if [ -z "${TOMCAT_CFG}" ]; then
+ TOMCAT_CFG="/etc/tomcat/tomcat.conf"
+fi
+
+if [ -r "$TOMCAT_CFG" ]; then
+ . $TOMCAT_CFG
+fi
+
+set_javacmd
+
+# CLASSPATH munging
+if [ -n "$JSSE_HOME" ]; then
+ CLASSPATH="${CLASSPATH}:$(build-classpath jcert jnet jsse 2>/dev/null)"
+fi
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/bootstrap.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar"
+export CLASSPATH
+
+# Configuration
+MAIN_CLASS="org.apache.catalina.startup.Tool"
+BASE_OPTIONS=""
+BASE_FLAGS="-Dcatalina.home=\"$CATALINA_HOME\""
+BASE_JARS="commons-daemon tomcat/catalina servlet tomcat/tomcat-util tomcat/tomcat-coyote tomcat/tomcat-api tomcat/tomcat-util-scan"
+
+# Set parameters
+set_classpath $BASE_JARS
+set_flags $BASE_FLAGS
+set_options $BASE_OPTIONS
+
+# Let's start
+run "$@"
diff --git a/tomcat-9.0.conf b/tomcat-9.0.conf
new file mode 100644
index 0000000..3f43006
--- /dev/null
+++ b/tomcat-9.0.conf
@@ -0,0 +1,52 @@
+# System-wide configuration file for tomcat services
+# This will be loaded by systemd as an environment file,
+# so please keep the syntax. For shell expansion support
+# place your custom files as /etc/tomcat/conf.d/*.conf
+#
+# There are 2 "classes" of startup behavior in this package.
+# The old one, the default service named tomcat.service.
+# The new named instances are called tomcat@instance.service.
+#
+# Use this file to change default values for all services.
+# Change the service specific ones to affect only one service.
+# For tomcat.service it's /etc/sysconfig/tomcat, for
+# tomcat@instance it's /etc/sysconfig/tomcat@instance.
+
+# This variable is used to figure out if config is loaded or not.
+TOMCAT_CFG_LOADED="1"
+
+# In new-style instances, if CATALINA_BASE isn't specified, it will
+# be constructed by joining TOMCATS_BASE and NAME.
+TOMCATS_BASE="/var/lib/tomcats/"
+
+# Where your java installation lives
+JAVA_HOME="/usr/lib/jvm/jre"
+
+# Where your tomcat installation lives
+CATALINA_HOME="@@@TCHOME@@@"
+
+# System-wide tmp
+CATALINA_TMPDIR="/var/cache/tomcat/temp"
+
+# You can pass some parameters to java here if you wish to
+#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"
+
+# Use JAVA_OPTS to set java.library.path for libtcnative.so
+#JAVA_OPTS="-Djava.library.path=/usr/lib"
+
+# Set default javax.sql.DataSource factory to apache commons one. See rhbz#1214381
+JAVA_OPTS="-Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory"
+
+# You can change your tomcat locale here
+#LANG="en_US"
+
+# Run tomcat under the Java Security Manager
+SECURITY_MANAGER="false"
+
+# Time to wait in seconds, before killing process
+# TODO(stingray): does nothing, fix.
+# SHUTDOWN_WAIT="30"
+
+# If you wish to further customize your tomcat environment,
+# put your own definitions here
+# (i.e. LD_LIBRARY_PATH for some jdbc drivers)
diff --git a/tomcat-9.0.logrotate b/tomcat-9.0.logrotate
new file mode 100644
index 0000000..a87b4c0
--- /dev/null
+++ b/tomcat-9.0.logrotate
@@ -0,0 +1,8 @@
+@@@TCLOG@@@/catalina.out {
+ copytruncate
+ weekly
+ rotate 52
+ compress
+ missingok
+ create 0644 tomcat tomcat
+}
diff --git a/tomcat-9.0.service b/tomcat-9.0.service
new file mode 100644
index 0000000..2b20aa0
--- /dev/null
+++ b/tomcat-9.0.service
@@ -0,0 +1,22 @@
+# Systemd unit file for default tomcat
+#
+# To create clones of this service:
+# DO NOTHING, use tomcat@.service instead.
+
+[Unit]
+Description=Apache Tomcat Web Application Container
+After=syslog.target network.target
+
+[Service]
+Type=simple
+EnvironmentFile=/etc/tomcat/tomcat.conf
+Environment="NAME="
+EnvironmentFile=-/etc/sysconfig/tomcat
+ExecStart=/usr/libexec/tomcat/server start
+SuccessExitStatus=143
+User=tomcat
+Group=tomcat
+
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tomcat-9.0.sysconfig b/tomcat-9.0.sysconfig
new file mode 100644
index 0000000..3117bf7
--- /dev/null
+++ b/tomcat-9.0.sysconfig
@@ -0,0 +1,11 @@
+# Service-specific configuration file for tomcat. This will be sourced by
+# systemd for the default service (tomcat.service)
+# If you want to customize named instance, make a similar file
+# and name it tomcat@instancename.
+
+# You will not need to set this, usually. For default service it equals
+# CATALINA_HOME. For named service, it equals ${TOMCATS_BASE}${NAME}
+#CATALINA_BASE="@@@TCHOME@@@"
+
+# Please take a look at /etc/tomcat/tomcat.conf to have an idea what you
+# can override.
diff --git a/tomcat-9.0.wrapper b/tomcat-9.0.wrapper
new file mode 100644
index 0000000..c97cb85
--- /dev/null
+++ b/tomcat-9.0.wrapper
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+if [ "$1" = "version" ]; then
+ . /usr/libexec/tomcat/preamble
+ exec ${JAVACMD} -classpath ${CATALINA_HOME}/lib/catalina.jar \
+ org.apache.catalina.util.ServerInfo
+fi
+
+SRV="tomcat"
+if [ -n "$2" ]; then
+ SRV="tomcat@$2"
+fi
+
+if [ "$1" = "start" ]; then
+ systemctl start ${SRV}.service
+elif [ "$1" = "stop" ]; then
+ systemctl stop ${SRV}.service
+elif [ "$1" = "version" ]; then
+ ${JAVACMD} -classpath ${CATALINA_HOME}/lib/catalina.jar \
+ org.apache.catalina.util.ServerInfo
+else
+ echo "Usage: $0 {start|stop|version} [server-id]"
+ exit 1
+fi
diff --git a/tomcat-api-OSGi-MANIFEST.MF b/tomcat-api-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..85b12b8
--- /dev/null
+++ b/tomcat-api-OSGi-MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tomcat;version="8.0.26"
+Bundle-Vendor: %bundleProvider
+Bundle-ClassPath: .
+Bundle-Version: 8.0.26
+Bundle-Name: %bundleName
+Bundle-Localization: plugin
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.apache.tomcat
+Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J
+ 2SE-1.3
+
diff --git a/tomcat-build.patch b/tomcat-build.patch
new file mode 100644
index 0000000..cf39361
--- /dev/null
+++ b/tomcat-build.patch
@@ -0,0 +1,12 @@
+--- tomcat/build.xml.orig 2018-08-07 10:32:04.994403913 -0400
++++ tomcat/build.xml 2018-08-07 10:32:30.874319588 -0400
+@@ -2989,6 +2989,9 @@ Read the Building page on the Apache Tom
+
+
+
++
++
++
+
+
+
diff --git a/tomcat-functions b/tomcat-functions
new file mode 100644
index 0000000..ab08fa2
--- /dev/null
+++ b/tomcat-functions
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+if [ -r /usr/share/java-utils/java-functions ]; then
+ . /usr/share/java-utils/java-functions
+else
+ echo "Can't read Java functions library, aborting"
+ exit 1
+fi
+
+_save_function() {
+ local ORIG_FUNC=$(declare -f $1)
+ local NEWNAME_FUNC="$2${ORIG_FUNC#$1}"
+ eval "$NEWNAME_FUNC"
+}
+
+run_jsvc(){
+ if [ -x /usr/bin/jsvc ]; then
+ TOMCAT_USER="${TOMCAT_USER:-tomcat}"
+ JSVC="/usr/bin/jsvc"
+
+ JSVC_OPTS="-nodetach -pidfile /var/run/jsvc-tomcat${NAME}.pid -user ${TOMCAT_USER} -outfile ${CATALINA_BASE}/logs/catalina.out -errfile ${CATALINA_BASE}/logs/catalina.out"
+ if [ "$1" = "stop" ]; then
+ JSVC_OPTS="${JSVC_OPTS} -stop"
+ fi
+
+ exec "${JSVC}" ${JSVC_OPTS} ${FLAGS} -classpath "${CLASSPATH}" ${OPTIONS} "${MAIN_CLASS}" "${@}"
+ else
+ echo "Can't find /usr/bin/jsvc executable"
+ fi
+
+}
+
+_save_function run run_java
+
+run() {
+ if [ "${USE_JSVC}" = "true" ] ; then
+ run_jsvc $@
+ else
+ run_java $@
+ fi
+}
+
diff --git a/tomcat-juli-OSGi-MANIFEST.MF b/tomcat-juli-OSGi-MANIFEST.MF
new file mode 100644
index 0000000..b856d9f
--- /dev/null
+++ b/tomcat-juli-OSGi-MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.juli;version="8.0.26",org.apache.juli.loggi
+ ng;version="8.0.26"
+Bundle-Vendor: %bundleProvider
+Bundle-ClassPath: .
+Bundle-Version: 8.0.26
+Bundle-Name: %bundleName
+Bundle-Localization: plugin
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.apache.juli
+Bundle-RequiredExecutionEnvironment: J2SE-1.4,CDC-1.0/Foundation-1.0,J
+ 2SE-1.3
+
diff --git a/tomcat-named.service b/tomcat-named.service
new file mode 100644
index 0000000..9bbcb17
--- /dev/null
+++ b/tomcat-named.service
@@ -0,0 +1,26 @@
+# Systemd unit file for tomcat instances.
+#
+# To create clones of this service:
+# 0. systemctl enable tomcat@name.service
+# 1. create catalina.base directory structure in
+# /var/lib/tomcats/name
+# 2. profit.
+
+[Unit]
+Description=Apache Tomcat Web Application Container
+After=syslog.target network.target
+
+[Service]
+Type=simple
+EnvironmentFile=/etc/tomcat/tomcat.conf
+Environment="NAME=%I"
+EnvironmentFile=-/etc/sysconfig/tomcat@%I
+ExecStart=/usr/libexec/tomcat/server start
+ExecStop=/usr/libexec/tomcat/server stop
+SuccessExitStatus=143
+User=tomcat
+Group=tomcat
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/tomcat-preamble b/tomcat-preamble
new file mode 100644
index 0000000..1271dca
--- /dev/null
+++ b/tomcat-preamble
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+. /usr/libexec/tomcat/functions
+
+# Get the tomcat config (use this for environment specific settings)
+
+if [ -z "${TOMCAT_CFG_LOADED}" ]; then
+ if [ -z "${TOMCAT_CFG}" ]; then
+ TOMCAT_CFG="/etc/tomcat/tomcat.conf"
+ fi
+ . $TOMCAT_CFG
+fi
+
+if [ -d "${TOMCAT_CONFD=/etc/tomcat/conf.d}" ]; then
+ for file in ${TOMCAT_CONFD}/*.conf ; do
+ if [ -f "$file" ] ; then
+ . "$file"
+ fi
+ done
+fi
+
+if [ -z "$CATALINA_BASE" ]; then
+ if [ -n "$NAME" ]; then
+ if [ -z "$TOMCATS_BASE" ]; then
+ TOMCATS_BASE="/var/lib/tomcats/"
+ fi
+ CATALINA_BASE="${TOMCATS_BASE}${NAME}"
+ else
+ CATALINA_BASE="${CATALINA_HOME}"
+ fi
+fi
+VERBOSE=1
+set_javacmd
+cd ${CATALINA_HOME}
+# CLASSPATH munging
+if [ ! -z "$CLASSPATH" ] ; then
+ CLASSPATH="$CLASSPATH":
+fi
+
+if [ -n "$JSSE_HOME" ]; then
+ CLASSPATH="${CLASSPATH}$(build-classpath jcert jnet jsse 2>/dev/null):"
+fi
+CLASSPATH="${CLASSPATH}${CATALINA_HOME}/bin/bootstrap.jar"
+CLASSPATH="${CLASSPATH}:${CATALINA_HOME}/bin/tomcat-juli.jar"
+CLASSPATH="${CLASSPATH}:$(build-classpath commons-daemon 2>/dev/null)"
+
+if [ -z "$LOGGING_PROPERTIES" ] ; then
+ LOGGING_PROPERTIES="${CATALINA_BASE}/conf/logging.properties"
+ if [ ! -f "${LOGGING_PROPERTIES}" ] ; then
+ LOGGING_PROPERTIES="${CATALINA_HOME}/conf/logging.properties"
+ fi
+fi
diff --git a/tomcat-server b/tomcat-server
new file mode 100644
index 0000000..17ae385
--- /dev/null
+++ b/tomcat-server
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+. /usr/libexec/tomcat/preamble
+
+MAIN_CLASS=org.apache.catalina.startup.Bootstrap
+
+FLAGS="$JAVA_OPTS"
+OPTIONS="-Dcatalina.base=$CATALINA_BASE \
+-Dcatalina.home=$CATALINA_HOME \
+-Djava.endorsed.dirs=$JAVA_ENDORSED_DIRS \
+-Djava.io.tmpdir=$CATALINA_TMPDIR \
+-Djava.util.logging.config.file=${LOGGING_PROPERTIES} \
+-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
+
+if [ "$1" = "start" ] ; then
+ FLAGS="${FLAGS} $CATALINA_OPTS"
+ if [ "${SECURITY_MANAGER}" = "true" ] ; then
+ OPTIONS="${OPTIONS} \
+ -Djava.security.manager \
+ -Djava.security.policy==${CATALINA_BASE}/conf/catalina.policy"
+ fi
+ run start
+elif [ "$1" = "stop" ] ; then
+ run stop
+fi
diff --git a/tomcat.spec b/tomcat.spec
new file mode 100644
index 0000000..bd0b3c9
--- /dev/null
+++ b/tomcat.spec
@@ -0,0 +1,463 @@
+%global jspspec 2.3
+%global major_version 9
+%global minor_version 0
+%global micro_version 10
+%global packdname apache-tomcat-%{version}-src
+%global servletspec 4.0
+%global elspec 3.0
+%global tcuid 91
+
+%{!?_mavendepmapfragdir: %global _mavendepmapfragdir /usr/share/maven-metadata}
+%{?fc24: %global _mavendepmapfragdir /usr/share/maven-metadata}
+
+Name: tomcat
+Epoch: 1
+Version: %{major_version}.%{minor_version}.%{micro_version}
+Release: 11
+Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies
+License: ASL 2.0
+URL: http://tomcat.apache.org/
+
+Source0: https://github.com/apache/tomcat/archive/%{version}.tar.gz
+Source1: %{name}-%{major_version}.%{minor_version}.conf
+Source3: %{name}-%{major_version}.%{minor_version}.sysconfig
+Source4: %{name}-%{major_version}.%{minor_version}.wrapper
+Source5: %{name}-%{major_version}.%{minor_version}.logrotate
+Source6: %{name}-%{major_version}.%{minor_version}-digest.script
+Source7: %{name}-%{major_version}.%{minor_version}-tool-wrapper.script
+Source8: servlet-api-OSGi-MANIFEST.MF
+Source9: jsp-api-OSGi-MANIFEST.MF
+Source11: %{name}-%{major_version}.%{minor_version}.service
+Source12: el-api-OSGi-MANIFEST.MF
+Source13: jasper-el-OSGi-MANIFEST.MF
+Source14: jasper-OSGi-MANIFEST.MF
+Source15: tomcat-api-OSGi-MANIFEST.MF
+Source16: tomcat-juli-OSGi-MANIFEST.MF
+Source20: %{name}-%{major_version}.%{minor_version}-jsvc.service
+Source21: tomcat-functions
+Source30: tomcat-preamble
+Source31: tomcat-server
+Source32: tomcat-named.service
+
+Patch0: %{name}-%{major_version}.%{minor_version}-bootstrap-MANIFEST.MF.patch
+Patch1: %{name}-%{major_version}.%{minor_version}-tomcat-users-webapp.patch
+Patch2: %{name}-build.patch
+Patch6001: CVE-2019-0199-1.patch
+Patch6002: CVE-2019-0199-2.patch
+Patch6003: CVE-2019-0199-3.patch
+Patch6004: CVE-2019-0199-4.patch
+Patch6005: CVE-2019-0199-5.patch
+Patch6006: CVE-2019-0199-6.patch
+Patch6007: CVE-2019-0199-7.patch
+Patch6008: CVE-2019-0199-8.patch
+Patch6009: CVE-2019-0199-9.patch
+Patch6010: CVE-2019-0199-10.patch
+Patch6011: CVE-2019-0199-11.patch
+Patch6012: CVE-2018-11784.patch
+Patch6013: CVE-2019-0221.patch
+Patch6014: CVE-2019-10072-1.patch
+Patch6015: CVE-2019-10072-2.patch
+
+BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon
+BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant
+BuildRequires: jpackage-utils >= 0:1.7.0 java-devel >= 1:1.8.0 junit javapackages-local
+BuildRequires: geronimo-saaj aqute-bndlib aqute-bnd systemd-units wsdl4j geronimo-jaxrpc
+
+Requires: procps jpackage-utils java-headless >= 1:1.8.0 apache-commons-daemon
+Requires: tomcat-taglibs-standard >= 0:1.1
+
+Recommends: tomcat-native >= 1.2.14
+
+Requires(pre): shadow-utils
+Requires(post): chkconfig
+Requires(preun): chkconfig
+Requires(postun): chkconfig
+
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+
+Provides: %{name}-log4j = %{epoch}:%{version}-%{release}
+Provides: servlet = %{servletspec} servlet6 servlet3 el_api = %{elspec} jsp = %{jspspec}
+Obsoletes: %{name}-el-2.2-api %{name}-servlet-3.1-api %{name}-jsp-2.2-api
+
+Provides: %{name}-lib = %{epoch}:%{version}-%{release}
+Provides: %{name}-servlet-%{servletspec}-api = %{epoch}:%{version}-%{release}
+Provides: %{name}-el-%{elspec}-api = %{epoch}:%{version}-%{release}
+Provides: %{name}-jsp-%{jspspec}-api = %{epoch}:%{version}-%{release}
+Provides: %{name}-webapps = %{epoch}:%{version}-%{release}
+Provides: %{name}-admin-webapps = %{epoch}:%{version}-%{release}
+
+Obsoletes: %{name}-lib < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-servlet-%{servletspec}-api < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-el-%{elspec}-api < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-jsp-%{jspspec}-api < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-webapps < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-admin-webapps < %{epoch}:%{version}-%{release}
+
+BuildArch: noarch
+
+%description
+The Apache Tomcat software is developed in an open and participatory environment
+and released under the Apache License version 2. The Apache Tomcat project is
+intended to be a collaboration of the best-of-breed developers from around the
+world. We invite you to participate in this open development project
+
+%package jsvc
+Summary: Apache jsvc wrapper for Apache Tomcat as separate service
+Requires: %{name} = %{epoch}:%{version}-%{release}
+Requires: apache-commons-daemon-jsvc
+
+%description jsvc
+Systemd service to start tomcat with jsvc,
+which allows tomcat to perform some privileged operations
+(e.g. bind to a port < 1024) and then switch identity to a non-privileged user.
+
+%package help
+Summary: Documents for %{name}
+Buildarch: noarch
+Requires: man info jpackage-utils
+Requires: %{name} = %{epoch}:%{version}-%{release}
+Provides: %{name}-docs-webapp = %{epoch}:%{version}-%{release}
+Provides: %{name}-javadoc = %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-docs-webapp < %{epoch}:%{version}-%{release}
+Obsoletes: %{name}-javadoc < %{epoch}:%{version}-%{release}
+
+%description help
+Man pages and other related documents for %{name}.
+
+%prep
+find . -type f \( -name "*.bat" -o -name "*.class" -o -name Thumbs.db -o -name "*.gz" -o \
+ -name "*.jar" -o -name "*.war" -o -name "*.zip" \) -delete
+
+%autosetup -p1 -n %{packdname}
+
+ln -s $(build-classpath tomcat-taglibs-standard/taglibs-standard-impl) webapps/examples/WEB-INF/lib/jstl.jar
+ln -s $(build-classpath tomcat-taglibs-standard/taglibs-standard-compat) webapps/examples/WEB-INF/lib/standard.jar
+
+%build
+export OPT_JAR_LIST="xalan-j2-serializer"
+ touch HACK
+ %{ant} -Dbase.path="." \
+ -Dbuild.compiler="modern" \
+ -Dcommons-collections.jar="$(build-classpath apache-commons-collections)" \
+ -Dcommons-daemon.jar="$(build-classpath apache-commons-daemon)" \
+ -Dcommons-daemon.native.src.tgz="HACK" \
+ -Djdt.jar="$(build-classpath ecj)" \
+ -Dtomcat-native.tar.gz="HACK" \
+ -Dtomcat-native.home="." \
+ -Dcommons-daemon.native.win.mgr.exe="HACK" \
+ -Dnsis.exe="HACK" \
+ -Djaxrpc-lib.jar="$(build-classpath jaxrpc)" \
+ -Dwsdl4j-lib.jar="$(build-classpath wsdl4j)" \
+ -Dsaaj-api.jar="$(build-classpath geronimo-saaj)" \
+ -Dbnd.jar="$(build-classpath aqute-bnd/biz.aQute.bnd)" \
+ -Dbndlib.jar="$(build-classpath aqute-bnd/biz.aQute.bndlib)" \
+ -Dbndlibg.jar="$(build-classpath aqute-bnd/aQute.libg)" \
+ -Dbndannotation.jar="$(build-classpath aqute-bnd/biz.aQute.bnd.annotation)" \
+ -Dslf4j-api.jar="$(build-classpath slf4j/slf4j-api)" \
+ -Dno.build.dbcp=true \
+ -Dversion="%{version}" \
+ -Dversion.build="%{micro_version}" \
+ -Djava.7.home=%{java_home} \
+ -Dexecute.validate=false \
+ deploy dist-prepare dist-source javadoc
+ rm output/build/bin/commons-daemon.jar output/build/lib/ecj.jar
+pushd output/dist/src/webapps/docs/appdev/sample/src
+mkdir -p ../web/WEB-INF/classes
+%{javac} -cp ../../../../../../../../output/build/lib/servlet-api.jar -d ../web/WEB-INF/classes mypackage/Hello.java
+pushd ../web
+%{jar} cf ../../../../../../../../output/build/webapps/docs/appdev/sample/sample.war *
+popd
+popd
+
+mkdir -p META-INF
+cp -p %{SOURCE8} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/servlet-api.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE9} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/jsp-api.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE12} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/el-api.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE13} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/jasper-el.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE14} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/jasper.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE15} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/lib/tomcat-api.jar META-INF/MANIFEST.MF
+cp -p %{SOURCE16} META-INF/MANIFEST.MF
+touch META-INF/MANIFEST.MF
+zip output/build/bin/tomcat-juli.jar META-INF/MANIFEST.MF
+
+%install
+install -d -m 0755 %{buildroot}%{_bindir}
+install -d -m 0755 %{buildroot}%{_sbindir}
+install -d -m 0755 %{buildroot}%{_javadocdir}/%{name}
+install -d -m 0755 %{buildroot}%{_sysconfdir}/init.d
+install -d -m 0755 %{buildroot}/lib/systemd/system
+install -d -m 0755 %{buildroot}%{_sysconfdir}/logrotate.d
+install -d -m 0755 %{buildroot}%{_sysconfdir}/sysconfig
+install -d -m 0755 %{buildroot}%{_var}/lib/%{name}/webapps
+install -d -m 0755 %{buildroot}%{_datadir}/%{name}/bin
+install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name}
+install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name}/Catalina/localhost
+install -d -m 0775 %{buildroot}%{_sysconfdir}/%{name}/conf.d
+/bin/echo "Place your custom *.conf files here. Shell expansion is supported." > %{buildroot}%{_sysconfdir}/%{name}/conf.d/README
+install -d -m 0755 %{buildroot}%{_javadir}/%{name}
+install -d -m 0775 %{buildroot}%{_var}/log/%{name}
+/bin/touch %{buildroot}%{_var}/log/%{name}/catalina.out
+install -d -m 0775 %{buildroot}%{_localstatedir}/lib/tomcats
+install -d -m 0775 %{buildroot}%{_datadir}/%{name}
+install -d -m 0775 %{buildroot}%{_var}/cache/%{name}/temp
+install -d -m 0775 %{buildroot}%{_var}/cache/%{name}/work
+install -d -m 0755 %{buildroot}%{_unitdir}
+install -d -m 0755 %{buildroot}%{_libexecdir}/%{name}
+
+pushd output/build
+ cp -a bin/*.{jar,xml} %{buildroot}%{_datadir}/%{name}/bin
+ cp -a conf/*.{policy,properties,xml,xsd} %{buildroot}%{_sysconfdir}/%{name}
+ cp -a lib/*.jar %{buildroot}%{_javadir}/%{name}
+ cp -a webapps/* %{buildroot}%{_var}/lib/%{name}/webapps
+popd
+
+cp -a output/dist/webapps/docs/api/* %{buildroot}%{_javadocdir}/%{name}
+
+sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \
+ -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \
+ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE1} \
+ > %{buildroot}%{_sysconfdir}/%{name}/%{name}.conf
+sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \
+ -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \
+ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE3} \
+ > %{buildroot}%{_sysconfdir}/sysconfig/%{name}
+install -m 0644 %{SOURCE4} %{buildroot}%{_sbindir}/%{name}
+install -m 0644 %{SOURCE11} %{buildroot}%{_unitdir}/%{name}.service
+install -m 0644 %{SOURCE20} %{buildroot}%{_unitdir}/%{name}-jsvc.service
+sed -e "s|\@\@\@TCLOG\@\@\@|%{_var}/log/%{name}|g" %{SOURCE5} > %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
+sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \
+ -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \
+ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE6} \
+ > %{buildroot}%{_bindir}/%{name}-digest
+sed -e "s|\@\@\@TCHOME\@\@\@|%{_datadir}/%{name}|g" \
+ -e "s|\@\@\@TCTEMP\@\@\@|%{_var}/cache/%{name}/temp|g" \
+ -e "s|\@\@\@LIBDIR\@\@\@|%{_libdir}|g" %{SOURCE7} \
+ > %{buildroot}%{_bindir}/%{name}-tool-wrapper
+
+install -m 0644 %{SOURCE21} %{buildroot}%{_libexecdir}/%{name}/functions
+install -m 0755 %{SOURCE30} %{buildroot}%{_libexecdir}/%{name}/preamble
+install -m 0755 %{SOURCE31} %{buildroot}%{_libexecdir}/%{name}/server
+install -m 0644 %{SOURCE32} %{buildroot}%{_unitdir}/%{name}@.service
+
+sed -i \
+ "s,el-api.jar,%{name}-el-%{elspec}-api.jar,;
+ s,servlet-api.jar,%{name}-servlet-%{servletspec}-api.jar,;
+ s,jsp-api.jar,%{name}-jsp-%{jspspec}-api.jar,;" \
+ %{buildroot}%{_datadir}/%{name}/bin/catalina-tasks.xml
+
+pushd %{buildroot}%{_javadir}
+ mv %{name}/jsp-api.jar %{name}-jsp-%{jspspec}-api.jar
+ ln -s %{name}-jsp-%{jspspec}-api.jar %{name}-jsp-api.jar
+ mv %{name}/servlet-api.jar %{name}-servlet-%{servletspec}-api.jar
+ ln -s %{name}-servlet-%{servletspec}-api.jar %{name}-servlet-api.jar
+ mv %{name}/el-api.jar %{name}-el-%{elspec}-api.jar
+ ln -s %{name}-el-%{elspec}-api.jar %{name}-el-api.jar
+popd
+
+pushd output/build
+ %{_bindir}/build-jar-repository lib apache-commons-collections apache-commons-dbcp apache-commons-pool ecj 2>&1
+ %{_bindir}/build-jar-repository -p webapps/examples/WEB-INF/lib \
+ tomcat-taglibs-standard/taglibs-standard-impl.jar tomcat-taglibs-standard/taglibs-standard-compat.jar 2>&1
+popd
+
+pushd %{buildroot}%{_javadir}/%{name}
+ ln -s ../../java/%{name}-jsp-%{jspspec}-api.jar .
+ ln -s ../../java/%{name}-servlet-%{servletspec}-api.jar .
+ ln -s ../../java/%{name}-el-%{elspec}-api.jar .
+ ln -s $(build-classpath apache-commons-collections) commons-collections.jar
+ ln -s $(build-classpath apache-commons-dbcp) commons-dbcp.jar
+ ln -s $(build-classpath apache-commons-pool) commons-pool.jar
+ ln -s $(build-classpath ecj) jasper-jdt.jar
+ cp -a %{buildroot}%{_datadir}/%{name}/bin/tomcat-juli.jar ./
+popd
+
+pushd %{buildroot}%{_datadir}/%{name}
+ ln -s %{_var}/lib/%{name}/webapps webapps
+ ln -s %{_sysconfdir}/%{name} conf
+ ln -s %{_javadir}/%{name} lib
+ ln -s %{_var}/log/%{name} logs
+ ln -s %{_var}/cache/%{name}/temp temp
+ ln -s %{_var}/cache/%{name}/work work
+popd
+
+mkdir -p %{buildroot}%{_var}/lib/%{name}/webapps/sample
+pushd %{buildroot}%{_var}/lib/%{name}/webapps/sample
+%{jar} xf %{buildroot}%{_var}/lib/%{name}/webapps/docs/appdev/sample/sample.war
+popd
+rm %{buildroot}%{_var}/lib/%{name}/webapps/docs/appdev/sample/sample.war
+
+mkdir -p %{buildroot}%{_var}/lib/%{name}/webapps/examples/META-INF
+pushd %{buildroot}%{_var}/lib/%{name}/webapps/examples/META-INF
+echo '' > context.xml
+echo '' >> context.xml
+echo ' ' >> context.xml
+echo '' >> context.xml
+popd
+
+pushd %{buildroot}%{_var}/lib/%{name}/webapps/examples/WEB-INF/lib
+ln -s -f $(build-classpath tomcat-taglibs-standard/taglibs-standard-impl) jstl.jar
+ln -s -f $(build-classpath tomcat-taglibs-standard/taglibs-standard-compat) standard.jar
+popd
+
+install -d -m 0755 %{buildroot}%{_mavenpomdir}
+pushd output/dist/src/res/maven
+for pom in *.pom; do
+ sed -i 's/@MAVEN.DEPLOY.VERSION@/%{version}/g' $pom
+done
+
+for libname in annotations-api catalina jasper-el jasper catalina-ha; do
+ cp -a %{name}-$libname.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-$libname.pom
+ %add_maven_depmap JPP.%{name}-$libname.pom %{name}/$libname.jar -f "tomcat-lib"
+done
+
+cp -a %{name}-util-scan.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-util-scan.pom
+%add_maven_depmap JPP.%{name}-util-scan.pom %{name}/%{name}-util-scan.jar -f "tomcat-lib"
+cp -a %{name}-jni.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-jni.pom
+%add_maven_depmap JPP.%{name}-jni.pom %{name}/%{name}-jni.jar -f "tomcat-lib"
+cp -a tomcat-jsp-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-jsp-api.pom
+%add_maven_depmap JPP-tomcat-jsp-api.pom tomcat-jsp-api.jar -f "tomcat-jsp-api" -a "org.eclipse.jetty.orbit:javax.servlet.jsp"
+cp -a tomcat-el-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-el-api.pom
+%add_maven_depmap JPP-tomcat-el-api.pom tomcat-el-api.jar -f "tomcat-el-api" -a "org.eclipse.jetty.orbit:javax.el"
+cp -a tomcat-servlet-api.pom %{buildroot}%{_mavenpomdir}/JPP-tomcat-servlet-api.pom
+%add_maven_depmap JPP-tomcat-servlet-api.pom tomcat-servlet-api.jar -f "tomcat-servlet-api"
+ln -s -f $(abs2rel %{_datadir}/%{name}/bin/tomcat-juli.jar %{_javadir}/%{name}) %{buildroot}%{_javadir}/%{name}/
+cp -a tomcat-tribes.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-catalina-tribes.pom
+%add_maven_depmap JPP.%{name}-catalina-tribes.pom %{name}/catalina-tribes.jar
+cp -a tomcat-coyote.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-coyote.pom
+%add_maven_depmap JPP.%{name}-tomcat-coyote.pom %{name}/tomcat-coyote.jar
+cp -a tomcat-juli.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-juli.pom
+%add_maven_depmap JPP.%{name}-tomcat-juli.pom %{name}/tomcat-juli.jar
+cp -a tomcat-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-api.pom
+%add_maven_depmap JPP.%{name}-tomcat-api.pom %{name}/tomcat-api.jar
+cp -a tomcat-util.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-util.pom
+%add_maven_depmap JPP.%{name}-tomcat-util.pom %{name}/tomcat-util.jar
+cp -a tomcat-jdbc.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-jdbc.pom
+%add_maven_depmap JPP.%{name}-tomcat-jdbc.pom %{name}/tomcat-jdbc.jar
+cp -a tomcat-websocket-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-websocket-api.pom
+%add_maven_depmap JPP.%{name}-websocket-api.pom %{name}/websocket-api.jar
+cp -a tomcat-websocket.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-tomcat-websocket.pom
+%add_maven_depmap JPP.%{name}-tomcat-websocket.pom %{name}/tomcat-websocket.jar
+cp -a tomcat-jaspic-api.pom %{buildroot}%{_mavenpomdir}/JPP.%{name}-jaspic-api.pom
+%add_maven_depmap JPP.%{name}-jaspic-api.pom %{name}/jaspic-api.jar
+
+%pre
+%{_sbindir}/groupadd -g %{tcuid} -r tomcat 2>/dev/null || :
+%{_sbindir}/useradd -c "Apache Tomcat" -u %{tcuid} -g tomcat -s /sbin/nologin -r -d %{_datadir}/%{name} tomcat 2>/dev/null || :
+
+%post
+%systemd_post %{name}.service
+%{_sbindir}/update-alternatives --install %{_javadir}/servlet.jar servlet %{_javadir}/%{name}-servlet-%{servletspec}-api.jar 30000
+%{_sbindir}/update-alternatives --install %{_javadir}/elspec.jar elspec %{_javadir}/%{name}-el-%{elspec}-api.jar 20300
+%{_sbindir}/update-alternatives --install %{_javadir}/jsp.jar jsp %{_javadir}/%{name}-jsp-%{jspspec}-api.jar 20200
+
+%preun
+rm -rf %{_var}/cache/%{name}/work/* %{_var}/cache/%{name}/temp/*
+%systemd_preun %{name}.service
+
+%postun
+%systemd_postun_with_restart %{name}.service
+if [ "$1" = "0" ]; then
+ %{_sbindir}/update-alternatives --remove servlet %{_javadir}/%{name}-servlet-%{servletspec}-api.jar
+ %{_sbindir}/update-alternatives --remove elspec %{_javadir}/%{name}-el-%{elspec}-api.jar
+ %{_sbindir}/update-alternatives --remove jsp %{_javadir}/%{name}-jsp-%{jspspec}-api.jar
+fi
+
+%triggerun -- tomcat < 0:7.0.22-2
+/usr/bin/systemd-sysv-convert -- save tomcat > /dev/null 2>&1 || :
+/sbin/chkconfig --del tomcat > /dev/null 2>&1 || :
+/bin/systemctl try-restart tomcat.service > /dev/null 2>&1 || :
+
+%files
+%doc LICENSE
+%{_javadir}/%{name}-servlet-%{servletspec}*.jar
+%dir %{_javadir}/%{name}
+%{_javadir}/%{name}/*.jar
+%{_javadir}/*.jar
+%{_datadir}/%{name}/bin/tomcat-juli.jar
+%{_mavenpomdir}/JPP*%{name}-*.pom
+%{_datadir}/maven-metadata/*.xml
+%{_javadir}/%{name}-el-%{elspec}-api.jar
+%{_javadir}/%{name}/%{name}-el-%{elspec}-api.jar
+%{_javadir}/%{name}-jsp-%{jspspec}*.jar
+%defattr(0664,root,tomcat,0755)
+%doc {LICENSE,NOTICE,RELEASE*}
+%attr(0755,root,root) %{_bindir}/%{name}-digest
+%attr(0755,root,root) %{_bindir}/%{name}-tool-wrapper
+%attr(0755,root,root) %{_sbindir}/%{name}
+%attr(0644,root,root) %{_unitdir}/%{name}.service
+%attr(0644,root,root) %{_unitdir}/%{name}@.service
+%attr(0755,root,root) %dir %{_libexecdir}/%{name}
+%attr(0755,root,root) %dir %{_localstatedir}/lib/tomcats
+%attr(0644,root,root) %{_libexecdir}/%{name}/functions
+%attr(0755,root,root) %{_libexecdir}/%{name}/preamble
+%attr(0755,root,root) %{_libexecdir}/%{name}/server
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/%{name}
+%attr(0755,root,tomcat) %dir %{_var}/lib/%{name}
+%attr(0755,root,tomcat) %dir %{_sysconfdir}/%{name}
+%defattr(0664,tomcat,root,0770)
+%attr(0770,tomcat,root) %dir %{_var}/log/%{name}
+%defattr(0664,root,tomcat,0770)
+%attr(0770,root,tomcat) %dir %{_var}/cache/%{name}
+%attr(0770,root,tomcat) %dir %{_var}/cache/%{name}/temp
+%attr(0770,root,tomcat) %dir %{_var}/cache/%{name}/work
+%defattr(0644,root,tomcat,0775)
+%attr(0775,root,tomcat) %dir %{_var}/lib/%{name}/webapps
+%attr(0775,root,tomcat) %dir %{_sysconfdir}/%{name}/Catalina
+%attr(0775,root,tomcat) %dir %{_sysconfdir}/%{name}/Catalina/localhost
+%attr(0755,root,tomcat) %dir %{_sysconfdir}/%{name}/conf.d
+%{_sysconfdir}/%{name}/conf.d/README
+%config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf
+%config(noreplace) %{_sysconfdir}/%{name}/*.policy
+%config(noreplace) %{_sysconfdir}/%{name}/*.properties
+%config(noreplace) %{_sysconfdir}/%{name}/context.xml
+%config(noreplace) %{_sysconfdir}/%{name}/server.xml
+%attr(0640,root,tomcat) %config(noreplace) %{_sysconfdir}/%{name}/tomcat-users.xml
+%attr(0664,root,tomcat) %{_sysconfdir}/%{name}/tomcat-users.xsd
+%attr(0664,root,tomcat) %config(noreplace) %{_sysconfdir}/%{name}/jaspic-providers.xml
+%attr(0664,root,tomcat) %{_sysconfdir}/%{name}/jaspic-providers.xsd
+%config(noreplace) %{_sysconfdir}/%{name}/web.xml
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/bin/bootstrap.jar
+%{_datadir}/%{name}/bin/catalina-tasks.xml
+%{_datadir}/%{name}/lib
+%{_datadir}/%{name}/temp
+%{_datadir}/%{name}/webapps
+%{_datadir}/%{name}/work
+%{_datadir}/%{name}/logs
+%{_datadir}/%{name}/conf
+%defattr(0664,root,tomcat,0755)
+%{_var}/lib/%{name}/webapps/host-manager
+%{_var}/lib/%{name}/webapps/manager
+%defattr(0644,tomcat,tomcat,0755)
+%{_var}/lib/%{name}/webapps/ROOT
+%{_var}/lib/%{name}/webapps/examples
+%{_var}/lib/%{name}/webapps/sample
+
+%files jsvc
+%defattr(755,root,root,0755)
+%attr(0644,root,root) %{_unitdir}/%{name}-jsvc.service
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
+%attr(0660,tomcat,tomcat) %verify(not size md5 mtime) %{_var}/log/%{name}/catalina.out
+
+%files help
+%{_var}/lib/%{name}/webapps/docs
+%{_javadocdir}/%{name}
+
+%changelog
+* Fri Feb 28 2020 Senlin Xia - 1:9.0.10-11
+- Package init
+