From a19fa21de7a100109b56cda53652fccfdc30477f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 09:19:25 +0000 Subject: [PATCH 1/4] Bump grpc-core from 1.42.1 to 1.43.0 Bumps [grpc-core](https://github.com/grpc/grpc-java) from 1.42.1 to 1.43.0. - [Release notes](https://github.com/grpc/grpc-java/releases) - [Commits](https://github.com/grpc/grpc-java/compare/v1.42.1...v1.43.0) --- updated-dependencies: - dependency-name: io.grpc:grpc-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33ccea23aa1..93fbf9ffa3c 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ 7.0.3 3.0.2 2.10.0 - 1.42.1 + 1.43.0 2.8.9 31.0.1-jre 5.0.1 From 81c1bda815baaa038de4122cc782ebd72f8e238c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 05:34:39 -0600 Subject: [PATCH 2/4] Bump hazelcast.version from 4.2.2 to 4.2.3 (#7289) Bumps `hazelcast.version` from 4.2.2 to 4.2.3. Updates `hazelcast` from 4.2.2 to 4.2.3 - [Release notes](https://github.com/hazelcast/hazelcast/releases) - [Commits](https://github.com/hazelcast/hazelcast/compare/v4.2.2...v4.2.3) Updates `hazelcast-all` from 4.2.2 to 4.2.3 --- updated-dependencies: - dependency-name: com.hazelcast:hazelcast dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.hazelcast:hazelcast-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 33ccea23aa1..2ecc8445458 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 5.0.1 2.2 2.14.2 - 4.2.2 + 4.2.3 11.0.11.Final 4.3.4.Final 2.13.0 From c7cec39ff5980392ce77dcdf9ef5cbb426793094 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 16 Dec 2021 07:05:30 -0600 Subject: [PATCH 3/4] Issue #7063 - Remove logging requirement from Password / Credential (#7227) * Issue #7063 - Remove logging requirement from Password / Credential + Adding testcase for Password command line + Moved hex/string methods from TypeUtil to StringUtil so that they can be reused in non-logging applications. Signed-off-by: Joakim Erdfelt --- .../org/eclipse/jetty/util/StringUtil.java | 42 ++++++++++++++++ .../java/org/eclipse/jetty/util/TypeUtil.java | 49 +++++++++---------- .../jetty/util/security/Credential.java | 32 ++++++------ .../eclipse/jetty/util/security/Password.java | 11 ++--- .../eclipse/jetty/util/StringUtilTest.java | 32 ++++++++++++ .../jetty/util/security/CredentialTest.java | 15 ++++++ .../jetty/util/security/PasswordTest.java | 49 +++++++++++++++++++ 7 files changed, 184 insertions(+), 46 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index 2dbfa0ce016..2f240bd9e18 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -18,6 +18,7 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Fast String Utilities. @@ -774,6 +775,47 @@ public class StringUtil return true; } + public static byte[] fromHexString(String s) + { + if (s.length() % 2 != 0) + throw new IllegalArgumentException(s); + byte[] array = new byte[s.length() / 2]; + for (int i = 0; i < array.length; i++) + { + int b = Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16); + array[i] = (byte)(0xff & b); + } + return array; + } + + public static String toHexString(byte b) + { + return toHexString(new byte[]{b}, 0, 1); + } + + public static String toHexString(byte[] b) + { + return toHexString(Objects.requireNonNull(b, "ByteBuffer cannot be null"), 0, b.length); + } + + public static String toHexString(byte[] b, int offset, int length) + { + StringBuilder buf = new StringBuilder(); + for (int i = offset; i < offset + length; i++) + { + int bi = 0xff & b[i]; + int c = '0' + (bi / 16) % 16; + if (c > '9') + c = 'A' + (c - '0' - 10); + buf.append((char)c); + c = '0' + bi % 16; + if (c > '9') + c = 'a' + (c - '0' - 10); + buf.append((char)c); + } + return buf.toString(); + } + public static String printable(String name) { if (name == null) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java index 5d937f809d1..3f5e1c35041 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java @@ -400,6 +400,10 @@ public class TypeUtil return value; } + /** + * @deprecated use {@link StringUtil#fromHexString(String)} instead + */ + @Deprecated public static byte[] parseBytes(String s, int base) { byte[] bytes = new byte[s.length() / 2]; @@ -507,45 +511,40 @@ public class TypeUtil toHex((int)value, buf); } + /** + * @deprecated use {@link StringUtil#toHexString(byte)} instead + */ + @Deprecated public static String toHexString(byte b) { - return toHexString(new byte[]{b}, 0, 1); + return StringUtil.toHexString(b); } + /** + * @deprecated use {@link StringUtil#toHexString(byte[])} instead + */ + @Deprecated public static String toHexString(byte[] b) { - return toHexString(b, 0, b.length); + return StringUtil.toHexString(b); } + /** + * @deprecated use {@link StringUtil#toHexString(byte[], int, int)} instead + */ + @Deprecated public static String toHexString(byte[] b, int offset, int length) { - StringBuilder buf = new StringBuilder(); - for (int i = offset; i < offset + length; i++) - { - int bi = 0xff & b[i]; - int c = '0' + (bi / 16) % 16; - if (c > '9') - c = 'A' + (c - '0' - 10); - buf.append((char)c); - c = '0' + bi % 16; - if (c > '9') - c = 'a' + (c - '0' - 10); - buf.append((char)c); - } - return buf.toString(); + return StringUtil.toHexString(b, offset, length); } + /** + * @deprecated use {@link StringUtil#fromHexString(String)} + */ + @Deprecated public static byte[] fromHexString(String s) { - if (s.length() % 2 != 0) - throw new IllegalArgumentException(s); - byte[] array = new byte[s.length() / 2]; - for (int i = 0; i < array.length; i++) - { - int b = Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16); - array[i] = (byte)(0xff & b); - } - return array; + return StringUtil.fromHexString(s); } public static void dump(Class c) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java index f4876ef2936..a555edc2e28 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java @@ -19,12 +19,9 @@ import java.security.MessageDigest; import java.util.List; import java.util.ServiceLoader; import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.thread.AutoLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Credentials. The Credential class represents an abstract mechanism for checking authentication credentials. A credential instance either represents a secret, @@ -39,10 +36,12 @@ import org.slf4j.LoggerFactory; */ public abstract class Credential implements Serializable { + // NOTE: DO NOT INTRODUCE LOGGING TO THIS CLASS private static final long serialVersionUID = -7760551052768181572L; - private static final Logger LOG = LoggerFactory.getLogger(Credential.class); - private static final List CREDENTIAL_PROVIDERS = TypeUtil.serviceProviderStream(ServiceLoader.load(CredentialProvider.class)) - .flatMap(p -> Stream.of(p.get())) + // Intentionally NOT using TypeUtil.serviceProviderStream + // as that introduces a Logger requirement that command line Password cannot use. + private static final List CREDENTIAL_PROVIDERS = ServiceLoader.load(CredentialProvider.class).stream() + .map(ServiceLoader.Provider::get) .collect(Collectors.toList()); /** @@ -154,8 +153,7 @@ public abstract class Credential implements Serializable { if (credentials instanceof char[]) credentials = new String((char[])credentials); - if (!(credentials instanceof String) && !(credentials instanceof Password)) - LOG.warn("Can't check {} against CRYPT", credentials.getClass()); + return stringEquals(_cooked, UnixCrypt.crypt(credentials.toString(), _cooked)); } @@ -189,7 +187,7 @@ public abstract class Credential implements Serializable MD5(String digest) { digest = digest.startsWith(__TYPE) ? digest.substring(__TYPE.length()) : digest; - _digest = TypeUtil.parseBytes(digest, 16); + _digest = StringUtil.fromHexString(digest); } public byte[] getDigest() @@ -229,13 +227,12 @@ public abstract class Credential implements Serializable } else { - LOG.warn("Can't check {} against MD5", credentials.getClass()); + // Not a MD5 or Credential class return false; } } catch (Exception e) { - LOG.warn("Failed message digest", e); return false; } } @@ -248,6 +245,9 @@ public abstract class Credential implements Serializable return false; } + /** + * Used only by Command Line Password utility + */ public static String digest(String password) { try @@ -263,7 +263,8 @@ public abstract class Credential implements Serializable } catch (Exception e) { - LOG.warn("Unable to access MD5 message digest", e); + System.err.println("Unable to access MD5 message digest"); + e.printStackTrace(); return null; } } @@ -273,11 +274,12 @@ public abstract class Credential implements Serializable digest = __md.digest(); } - return __TYPE + TypeUtil.toString(digest, 16); + return __TYPE + StringUtil.toHexString(digest); } catch (Exception e) { - LOG.warn("Message Digest failure", e); + System.err.println("Message Digest Failure"); + e.printStackTrace(); return null; } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java index 510880f99ce..323f6b31597 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java @@ -17,9 +17,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Locale; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Password utility class. * @@ -47,8 +44,7 @@ import org.slf4j.LoggerFactory; */ public class Password extends Credential { - private static final Logger LOG = LoggerFactory.getLogger(Password.class); - + // NOTE: DO NOT INTRODUCE LOGGING TO THIS CLASS private static final long serialVersionUID = 5062906681431569445L; public static final String __OBFUSCATE = "OBF:"; @@ -224,7 +220,9 @@ public class Password extends Credential } catch (IOException e) { - LOG.warn("EXCEPTION", e); + // only seen with command line input style + System.err.println("ERROR: Bad/Invalid password."); + e.printStackTrace(); } if (passwd == null || passwd.length() == 0) passwd = promptDft; @@ -247,5 +245,6 @@ public class Password extends Credential System.err.println(Credential.MD5.digest(p)); if (arg.length == 2) System.err.println(Credential.Crypt.crypt(arg[0], pw.toString())); + System.exit(0); } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java index 85e19fb17df..4dc4781d8e4 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java @@ -26,8 +26,10 @@ import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; // @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck @@ -266,4 +268,34 @@ public class StringUtilTest assertThat(StringUtil.csvSplit("\"aaa\", \" b,\\\"\",\"\""), arrayContaining("aaa", " b,\"", "")); } + + @Test + public void testFromHexStringGood() + { + assertArrayEquals(new byte[]{0x12, 0x34, 0x56, 0x78, (byte)0x9A}, StringUtil.fromHexString("123456789A")); + } + + @Test + public void testFromHexStringBad() + { + assertThrows(NumberFormatException.class, () -> StringUtil.fromHexString("Hello World ")); + } + + @Test + public void testToHexStringGood() + { + assertThat(StringUtil.toHexString(new byte[]{0x12, 0x34, 0x56, 0x78, (byte)0x9A}), is("123456789a")); + } + + @Test + public void testToHexStringNull() + { + assertThrows(NullPointerException.class, () -> StringUtil.toHexString(null)); + } + + @Test + public void testToHexStringEmpty() + { + assertThat(StringUtil.toHexString(new byte[0]), is("")); + } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java index 171bdade206..a3e2c5bd0f0 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java @@ -16,6 +16,8 @@ package org.eclipse.jetty.util.security; import org.eclipse.jetty.util.security.Credential.Crypt; import org.eclipse.jetty.util.security.Credential.MD5; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -99,4 +101,17 @@ public class CredentialTest assertFalse(Credential.byteEquals("".getBytes(), "fooo".getBytes())); assertTrue(Credential.byteEquals("".getBytes(), "".getBytes())); } + + @ParameterizedTest + @ValueSource(strings = { + "OBF:1v2j1uum1xtv1zej1zer1xtn1uvk1v1v", + "MD5:5f4dcc3b5aa765d61d8327deb882cf99", + "CRYPT:usjRS48E8ZADM" + }) + public void testGetCredential(String encoded) + { + Credential credential = Credential.getCredential(encoded); + assertTrue(credential.check(Credential.getCredential("password"))); + assertTrue(credential.check("password")); + } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java index dab2d6749bf..ff8a71052b1 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java @@ -13,9 +13,22 @@ package org.eclipse.jetty.util.security; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class PasswordTest { @@ -44,4 +57,40 @@ public class PasswordTest String obfuscate = Password.obfuscate(password); assertEquals(password, Password.deobfuscate(obfuscate)); } + + @Test + public void testCommandLineUsage() throws IOException, InterruptedException + { + ProcessBuilder passwordBuilder = new ProcessBuilder() + .directory(MavenTestingUtils.getTargetDir()) + .command("java", + "-cp", MavenTestingUtils.getTargetPath("classes").toString(), + Password.class.getName(), + "user", "password") + .redirectErrorStream(true); + + Process passwordProcess = passwordBuilder.start(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(passwordProcess.getInputStream()))) + { + String output = reader.lines().collect(Collectors.joining(System.lineSeparator())); + if (passwordProcess.waitFor(5, TimeUnit.SECONDS)) + { + int exitCode = passwordProcess.exitValue(); + assertThat("Non-error exit code: " + output, exitCode, is(0)); + assertThat("Output", output, not(containsString("Exception"))); + assertThat("Output", output, allOf( + containsString("password"), + containsString("OBF:"), + containsString("MD5:"), + containsString("CRYPT:") + )); + } + else + { + System.out.println(output); + passwordProcess.destroy(); + fail("Process didn't exit properly (was forcibly destroyed)"); + } + } + } } From 44fb63e541a3be999b8488f4dd43278c20bc8c5b Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Wed, 15 Dec 2021 11:31:18 +0100 Subject: [PATCH 4/4] #7284 cleanup HttpInput reopen/recycle Signed-off-by: Ludovic Orban --- .../jetty/server/AsyncContentProducer.java | 22 +++++++++++++++++++ .../jetty/server/BlockingContentProducer.java | 8 +++++++ .../eclipse/jetty/server/ContentProducer.java | 14 +++++++++--- .../org/eclipse/jetty/server/HttpInput.java | 10 ++++++--- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContentProducer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContentProducer.java index b18b91c8b73..74c0e7b22db 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContentProducer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContentProducer.java @@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory; class AsyncContentProducer implements ContentProducer { private static final Logger LOG = LoggerFactory.getLogger(AsyncContentProducer.class); + private static final HttpInput.ErrorContent RECYCLED_ERROR_CONTENT = new HttpInput.ErrorContent(new IllegalStateException("ContentProducer has been recycled")); private static final Throwable UNCONSUMED_CONTENT_EXCEPTION = new IOException("Unconsumed content") { @Override @@ -66,9 +67,30 @@ class AsyncContentProducer implements ContentProducer assertLocked(); if (LOG.isDebugEnabled()) LOG.debug("recycling {}", this); + + // Make sure that the content has been fully consumed before destroying the interceptor and also make sure + // that asking this instance for content between recycle and reopen will only produce error'ed content. + if (_rawContent == null) + _rawContent = RECYCLED_ERROR_CONTENT; + else if (!_rawContent.isSpecial()) + throw new IllegalStateException("ContentProducer with unconsumed content cannot be recycled"); + + if (_transformedContent == null) + _transformedContent = RECYCLED_ERROR_CONTENT; + else if (!_transformedContent.isSpecial()) + throw new IllegalStateException("ContentProducer with unconsumed content cannot be recycled"); + if (_interceptor instanceof Destroyable) ((Destroyable)_interceptor).destroy(); _interceptor = null; + } + + @Override + public void reopen() + { + assertLocked(); + if (LOG.isDebugEnabled()) + LOG.debug("reopening {}", this); _rawContent = null; _transformedContent = null; _error = false; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingContentProducer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingContentProducer.java index a4a499c2dd5..7cd901a0520 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingContentProducer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingContentProducer.java @@ -46,6 +46,14 @@ class BlockingContentProducer implements ContentProducer if (LOG.isDebugEnabled()) LOG.debug("recycling {}", this); _asyncContentProducer.recycle(); + } + + @Override + public void reopen() + { + if (LOG.isDebugEnabled()) + LOG.debug("reopening {}", this); + _asyncContentProducer.reopen(); _semaphore.drainPermits(); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ContentProducer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ContentProducer.java index 9678f02b3da..b14baa1c1cf 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ContentProducer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ContentProducer.java @@ -13,6 +13,7 @@ package org.eclipse.jetty.server; +import org.eclipse.jetty.util.component.Destroyable; import org.eclipse.jetty.util.thread.AutoLock; /** @@ -27,17 +28,24 @@ import org.eclipse.jetty.util.thread.AutoLock; public interface ContentProducer { /** - * Lock this instance. The lock must be held before any method of this instance's - * method be called, and must be manually released afterward. + * Lock this instance. The lock must be held before any of this instance's + * method can be called, and must be released afterward. * @return the lock that is guarding this instance. */ AutoLock lock(); /** - * Reset all internal state and clear any held resources. + * Clear the interceptor and call {@link Destroyable#destroy()} on it if it implements {@link Destroyable}. + * A recycled {@link ContentProducer} will only produce special content with a non-null error until + * {@link #reopen()} is called. */ void recycle(); + /** + * Reset all internal state, making this is instance logically equivalent to a freshly allocated one. + */ + void reopen(); + /** * Fail all content currently available in this {@link ContentProducer} instance * as well as in the underlying {@link HttpChannel}. diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java index e41362b3a1c..c123af4e6f3 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java @@ -55,8 +55,12 @@ public class HttpInput extends ServletInputStream implements Runnable public void recycle() { - if (LOG.isDebugEnabled()) - LOG.debug("recycle {}", this); + try (AutoLock lock = _contentProducer.lock()) + { + if (LOG.isDebugEnabled()) + LOG.debug("recycle {}", this); + _blockingContentProducer.recycle(); + } } public void reopen() @@ -65,7 +69,7 @@ public class HttpInput extends ServletInputStream implements Runnable { if (LOG.isDebugEnabled()) LOG.debug("reopen {}", this); - _blockingContentProducer.recycle(); + _blockingContentProducer.reopen(); _contentProducer = _blockingContentProducer; _consumedEof = false; _readListener = null;