This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 55aa76a0cd5e259714a307cbe49462a6afa16c09 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sat Nov 9 10:58:38 2024 -0500 Add support to ChecksumInputStream for setting a consumer for ProxyInputStream.afterRead(int) --- src/changes/changes.xml | 1 + .../commons/io/input/ChecksumInputStream.java | 23 ++++++--------- .../commons/io/input/CountingInputStream.java | 11 +++++++- .../commons/io/input/ChecksumInputStreamTest.java | 33 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ea1be6752..f44b4d8f8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -69,6 +69,7 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="add" due-to="Gary Gregory">Add support to AutoCloseInputStream for setting a consumer for ProxyInputStream.afterRead(int).</action> <action dev="ggregory" type="add" due-to="Gary Gregory">Add support to BOMInputStream for setting a consumer for ProxyInputStream.afterRead(int).</action> <action dev="ggregory" type="add" issue="IO-861" due-to="Gary Gregory">Add support to BoundedInputStream for setting a consumer for ProxyInputStream.afterRead(int).</action> + <action dev="ggregory" type="add" due-to="Gary Gregory">Add support to ChecksumInputStream for setting a consumer for ProxyInputStream.afterRead(int).</action> <!-- UPDATE --> <action dev="ggregory" type="update" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 74 to 78 #670, #676, #679, #688.</action> <action dev="ggregory" type="update" due-to="Gary Gregory">Bump commons.bytebuddy.version from 1.15.1 to 1.15.10 #672, #673, #685, #686, #694, #696, #698.</action> diff --git a/src/main/java/org/apache/commons/io/input/ChecksumInputStream.java b/src/main/java/org/apache/commons/io/input/ChecksumInputStream.java index 8af6c80ac..0f9a213a6 100644 --- a/src/main/java/org/apache/commons/io/input/ChecksumInputStream.java +++ b/src/main/java/org/apache/commons/io/input/ChecksumInputStream.java @@ -24,8 +24,6 @@ import java.util.Objects; import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; -import org.apache.commons.io.build.AbstractStreamBuilder; - /** * Automatically verifies a {@link Checksum} value once the stream is exhausted or the count threshold is reached. * <p> @@ -98,7 +96,7 @@ public final class ChecksumInputStream extends CountingInputStream { * @see #get() */ // @formatter:on - public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> { + public static class Builder extends AbstractBuilder<ChecksumInputStream, Builder> { /** * There is no default {@link Checksum}, you MUST provide one. This avoids any issue with a default {@link Checksum} being proven deficient or insecure @@ -141,10 +139,9 @@ public final class ChecksumInputStream extends CountingInputStream { * @throws IOException if an I/O error occurs. * @see #getInputStream() */ - @SuppressWarnings("resource") @Override public ChecksumInputStream get() throws IOException { - return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold); + return new ChecksumInputStream(this); } /** @@ -211,17 +208,13 @@ public final class ChecksumInputStream extends CountingInputStream { /** * Constructs a new instance. * - * @param in the stream to wrap. - * @param checksum a Checksum implementation. - * @param expectedChecksumValue the expected checksum. - * @param countThreshold the count threshold to limit how much input is consumed, a negative number means the - * threshold is unbound. + * @param builder build parameters. */ - private ChecksumInputStream(final InputStream in, final Checksum checksum, final long expectedChecksumValue, - final long countThreshold) { - super(new CheckedInputStream(in, Objects.requireNonNull(checksum, "checksum"))); - this.countThreshold = countThreshold; - this.expectedChecksumValue = expectedChecksumValue; + @SuppressWarnings("resource") + private ChecksumInputStream(final Builder builder) throws IOException { + super(new CheckedInputStream(builder.getInputStream(), Objects.requireNonNull(builder.checksum, "builder.checksum")), builder); + this.countThreshold = builder.countThreshold; + this.expectedChecksumValue = builder.expectedChecksumValue; } @Override diff --git a/src/main/java/org/apache/commons/io/input/CountingInputStream.java b/src/main/java/org/apache/commons/io/input/CountingInputStream.java index 661d79dc0..790b48976 100644 --- a/src/main/java/org/apache/commons/io/input/CountingInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CountingInputStream.java @@ -33,7 +33,7 @@ import java.io.InputStream; @Deprecated public class CountingInputStream extends ProxyInputStream { - /** The count of bytes that have passed. */ + /** The count of bytes read. */ private long count; /** @@ -45,6 +45,14 @@ public class CountingInputStream extends ProxyInputStream { super(in); } + CountingInputStream(final InputStream in, final ProxyInputStream.AbstractBuilder<?, ?> builder) { + super(in, builder); + } + + CountingInputStream(final ProxyInputStream.AbstractBuilder<?, ?> builder) throws IOException { + super(builder); + } + /** * Adds the number of read bytes to the count. * @@ -57,6 +65,7 @@ public class CountingInputStream extends ProxyInputStream { if (n != EOF) { count += n; } + super.afterRead(n); } /** diff --git a/src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java index ec1dcfeb8..c92d0433d 100644 --- a/src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java +++ b/src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java @@ -19,15 +19,18 @@ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.Adler32; import java.util.zip.CRC32; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.test.CustomIOException; import org.junit.jupiter.api.Test; /** @@ -39,6 +42,36 @@ public class ChecksumInputStreamTest { return ChecksumInputStream.builder().setCharSequence("Hi").setChecksum(new CRC32()).get(); } + @Test + public void testAfterReadConsumer() throws Exception { + final AtomicBoolean boolRef = new AtomicBoolean(); + // @formatter:off + try (InputStream bounded = ChecksumInputStream.builder() + .setCharSequence("Hi") + .setChecksum(new CRC32()) + .setExpectedChecksumValue(1293356558) + .setAfterRead(i -> boolRef.set(true)) + .get()) { + IOUtils.consume(bounded); + } + // @formatter:on + assertTrue(boolRef.get()); + // Throwing + final String message = "test exception message"; + // @formatter:off + try (InputStream bounded = ChecksumInputStream.builder() + .setCharSequence("Hi") + .setChecksum(new CRC32()) + .setExpectedChecksumValue(1293356558) + .setAfterRead(i -> { + throw new CustomIOException(message); + }) + .get()) { + assertEquals(message, assertThrowsExactly(CustomIOException.class, () -> IOUtils.consume(bounded)).getMessage()); + } + // @formatter:on + } + @SuppressWarnings("resource") @Test public void testAvailableAfterClose() throws Exception {