You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "garydgregory (via GitHub)" <gi...@apache.org> on 2024/01/01 14:09:51 UTC
[PR] Add ChecksumInputStream and test [commons-io]
garydgregory opened a new pull request, #548:
URL: https://github.com/apache/commons-io/pull/548
Should replace the Apache Commons Compress version.
@elharo
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1439081782
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
+ * @return this.
+ */
+ public Builder setCountThreshold(final long countThreshold) {
+ this.countThreshold = countThreshold;
+ return this;
+ }
+
+ /**
+ * The expected {@link Checksum} value once the input is consumed or the threshold is reached.
+ *
+ * @param expectedChecksumValue The expected Checksum value.
+ * @return this.
+ */
+ public Builder setExpectedChecksumValue(final long expectedChecksumValue) {
+ this.expectedChecksumValue = expectedChecksumValue;
+ return this;
+ }
+
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** The expected checksum. */
+ private final long expectedChecksumValue;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream
+ * validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private final long countThreshold;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param in the stream to wrap.
+ * @param checksum Checksum implementation.
+ * @param expectedChecksumValue the expected checksum.
+ * @param countThreshold the of the stream's content, a negative number means the threshold is unbound.
+ */
+ private ChecksumInputStream(final InputStream in, final Checksum checksum, final long expectedChecksumValue,
+ final long countThreshold) {
+ super(new CheckedInputStream(in, checksum));
+ this.countThreshold = countThreshold;
+ this.expectedChecksumValue = expectedChecksumValue;
+ }
+
+ @Override
+ protected synchronized void afterRead(final int n) throws IOException {
+ super.afterRead(n);
+ if (getByteCount() >= countThreshold && expectedChecksumValue != getChecksum().getValue()) {
Review Comment:
I'll update one of the tests with a computed checksum. The `afterRead()` method now checks for EOF.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "codecov-commenter (via GitHub)" <gi...@apache.org>.
codecov-commenter commented on PR #548:
URL: https://github.com/apache/commons-io/pull/548#issuecomment-1873345370
## [Codecov](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
Attention: `1 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`0fbae67`)](https://app.codecov.io/gh/apache/commons-io/commit/0fbae67fba0a39cf0d96712b71b3afcc713003bd?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) 85.95% compared to head [(`d5a04cd`)](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) 85.97%.
| [Files](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Patch % | Lines |
|---|---|---|
| [...g/apache/commons/io/input/ChecksumInputStream.java](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2NvbW1vbnMvaW8vaW5wdXQvQ2hlY2tzdW1JbnB1dFN0cmVhbS5qYXZh) | 95.00% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
<details><summary>Additional details and impacted files</summary>
```diff
@@ Coverage Diff @@
## master #548 +/- ##
============================================
+ Coverage 85.95% 85.97% +0.02%
- Complexity 3480 3486 +6
============================================
Files 230 231 +1
Lines 8225 8245 +20
Branches 960 961 +1
============================================
+ Hits 7070 7089 +19
Misses 865 865
- Partials 290 291 +1
```
</details>
[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/apache/commons-io/pull/548?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on PR #548:
URL: https://github.com/apache/commons-io/pull/548#issuecomment-1873431026
- You can't use a `DigestInputStream` with a `Checksum`.
- You can't use a `CheckedInputStream` with a `MessageDigest`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "elharo (via GitHub)" <gi...@apache.org>.
elharo commented on PR #548:
URL: https://github.com/apache/commons-io/pull/548#issuecomment-1873474093
I did see that in the comments. I just couldn't work out where/how that's happening in the code.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "elharo (via GitHub)" <gi...@apache.org>.
elharo commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1442912130
##########
src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java:
##########
@@ -0,0 +1,163 @@
+/*
+ * 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.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 java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.Adler32;
+import java.util.zip.CRC32;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ChecksumInputStream}.
+ */
+public class ChecksumInputStreamTest {
+
+ @Test
+ public void testDefaultThresholdFailure() throws IOException {
+ final byte[] byteArray = new byte[3];
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ // Ask to read one more byte than there is, we get the correct byte count.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testDefaultThresholdSuccess() throws IOException {
+ // sanity-check
+ final Adler32 sanityCheck = new Adler32();
+ final byte[] byteArray = new byte[3];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ assertEquals(3, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ assertEquals(-1, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingByteArrayThrowsException() throws IOException {
+ final Adler32 adler32 = new Adler32();
+ final byte[] byteArray = new byte[3];
+ final long sizeThreshold = -1859L;
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .setCountThreshold(sizeThreshold)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(sizeThreshold, checksum.getRemaining());
+ // Ask to read one more byte than there is.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(sizeThreshold - byteArray.length, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingNoArgumentsThrowsException() throws IOException {
+ final CRC32 crc32 = new CRC32();
+ final byte[] byteArray = new byte[9];
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue((byte) 1)
+ .setCountThreshold(1)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(1, checksum.getRemaining());
+ assertThrows(IOException.class, () -> checksum.read());
+ assertEquals(1, checksum.getByteCount());
+ assertEquals(0, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testSkip() throws IOException {
+ // sanity-check
+ final CRC32 sanityCheck = new CRC32();
+ final byte[] byteArray = new byte[4];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final CRC32 crc32 = new CRC32();
+ final InputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setInputStream(byteArrayInputStream)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .setCountThreshold(33)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ @SuppressWarnings("unused")
Review Comment:
The warning doesn't need to be suppressed. Just remove the variable and leave the read.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on PR #548:
URL: https://github.com/apache/commons-io/pull/548#issuecomment-1873472444
TY for your review.
> How is the checksum verified if the threshold isn't reached or is unbounded?
The first line of the class Javadoc already states "Automatically verifies a {@link Checksum} value once the stream is exhausted."
I'll update it to "once the stream is exhausted or the count threshold is reached."
The `setExpectedChecksumValue()` already states a version of the above. I'll make the wording consistent though.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory merged PR #548:
URL: https://github.com/apache/commons-io/pull/548
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "elharo (via GitHub)" <gi...@apache.org>.
elharo commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1439070485
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
+ * @return this.
+ */
+ public Builder setCountThreshold(final long countThreshold) {
+ this.countThreshold = countThreshold;
+ return this;
+ }
+
+ /**
+ * The expected {@link Checksum} value once the input is consumed or the threshold is reached.
+ *
+ * @param expectedChecksumValue The expected Checksum value.
+ * @return this.
+ */
+ public Builder setExpectedChecksumValue(final long expectedChecksumValue) {
+ this.expectedChecksumValue = expectedChecksumValue;
+ return this;
+ }
+
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** The expected checksum. */
+ private final long expectedChecksumValue;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream
Review Comment:
validates
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
Review Comment:
validates
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
Review Comment:
throws a --> throws an
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
+ * @return this.
+ */
+ public Builder setCountThreshold(final long countThreshold) {
+ this.countThreshold = countThreshold;
+ return this;
+ }
+
+ /**
+ * The expected {@link Checksum} value once the input is consumed or the threshold is reached.
+ *
+ * @param expectedChecksumValue The expected Checksum value.
+ * @return this.
+ */
+ public Builder setExpectedChecksumValue(final long expectedChecksumValue) {
+ this.expectedChecksumValue = expectedChecksumValue;
+ return this;
+ }
+
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** The expected checksum. */
+ private final long expectedChecksumValue;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream
+ * validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private final long countThreshold;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param in the stream to wrap.
+ * @param checksum Checksum implementation.
+ * @param expectedChecksumValue the expected checksum.
+ * @param countThreshold the of the stream's content, a negative number means the threshold is unbound.
+ */
+ private ChecksumInputStream(final InputStream in, final Checksum checksum, final long expectedChecksumValue,
+ final long countThreshold) {
+ super(new CheckedInputStream(in, checksum));
+ this.countThreshold = countThreshold;
+ this.expectedChecksumValue = expectedChecksumValue;
+ }
+
+ @Override
+ protected synchronized void afterRead(final int n) throws IOException {
+ super.afterRead(n);
+ if (getByteCount() >= countThreshold && expectedChecksumValue != getChecksum().getValue()) {
Review Comment:
seems like the checksum might not count the right number of bytes. That is, it might not end on the boundary. Immediate problem if there's no threshold.
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
Review Comment:
I think you'd want to supply an actual value here with setExpectedChecksumValue, not only a blank CRC32 object
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
Review Comment:
; you MUST
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
Review Comment:
threshold. A negative
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
+ * @return this.
+ */
+ public Builder setCountThreshold(final long countThreshold) {
+ this.countThreshold = countThreshold;
+ return this;
+ }
+
+ /**
+ * The expected {@link Checksum} value once the input is consumed or the threshold is reached.
+ *
+ * @param expectedChecksumValue The expected Checksum value.
+ * @return this.
+ */
+ public Builder setExpectedChecksumValue(final long expectedChecksumValue) {
+ this.expectedChecksumValue = expectedChecksumValue;
+ return this;
+ }
+
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** The expected checksum. */
+ private final long expectedChecksumValue;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream
+ * validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private final long countThreshold;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param in the stream to wrap.
+ * @param checksum Checksum implementation.
+ * @param expectedChecksumValue the expected checksum.
+ * @param countThreshold the of the stream's content, a negative number means the threshold is unbound.
Review Comment:
a word is missing?
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
Review Comment:
I don't understand this
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1442921573
##########
src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java:
##########
@@ -0,0 +1,163 @@
+/*
+ * 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.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 java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.Adler32;
+import java.util.zip.CRC32;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ChecksumInputStream}.
+ */
+public class ChecksumInputStreamTest {
+
+ @Test
+ public void testDefaultThresholdFailure() throws IOException {
+ final byte[] byteArray = new byte[3];
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ // Ask to read one more byte than there is, we get the correct byte count.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testDefaultThresholdSuccess() throws IOException {
+ // sanity-check
+ final Adler32 sanityCheck = new Adler32();
+ final byte[] byteArray = new byte[3];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ assertEquals(3, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ assertEquals(-1, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingByteArrayThrowsException() throws IOException {
+ final Adler32 adler32 = new Adler32();
+ final byte[] byteArray = new byte[3];
+ final long sizeThreshold = -1859L;
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .setCountThreshold(sizeThreshold)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(sizeThreshold, checksum.getRemaining());
+ // Ask to read one more byte than there is.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(sizeThreshold - byteArray.length, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingNoArgumentsThrowsException() throws IOException {
+ final CRC32 crc32 = new CRC32();
+ final byte[] byteArray = new byte[9];
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue((byte) 1)
+ .setCountThreshold(1)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(1, checksum.getRemaining());
+ assertThrows(IOException.class, () -> checksum.read());
+ assertEquals(1, checksum.getByteCount());
+ assertEquals(0, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testSkip() throws IOException {
+ // sanity-check
+ final CRC32 sanityCheck = new CRC32();
+ final byte[] byteArray = new byte[4];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final CRC32 crc32 = new CRC32();
+ final InputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setInputStream(byteArrayInputStream)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .setCountThreshold(33)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ @SuppressWarnings("unused")
Review Comment:
I replaced the suppression with an an assertion. Some static analysis tools flag ignored read() values as a problem because it can indicate a lack of EOF detection.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1439081782
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
+ * </p>
+ * <p>
+ * You must provide an origin that can be converted to an InputStream by this builder, otherwise, this call will
+ * throw an {@link UnsupportedOperationException}.
+ * </p>
+ *
+ * @return a new instance.
+ * @throws UnsupportedOperationException if the origin cannot provide an InputStream.
+ * @see #getInputStream()
+ */
+ @SuppressWarnings("resource")
+ @Override
+ public ChecksumInputStream get() throws IOException {
+ return new ChecksumInputStream(getInputStream(), checksum, expectedChecksumValue, countThreshold);
+ }
+
+ /**
+ * Sets the Checksum.
+ *
+ * @param checksum the Checksum.
+ * @return this.
+ */
+ public Builder setChecksum(final Checksum checksum) {
+ this.checksum = checksum;
+ return this;
+ }
+
+ /**
+ * Sets the count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ *
+ * @param countThreshold the count threshold, a negative number means the threshold is unbound.
+ * @return this.
+ */
+ public Builder setCountThreshold(final long countThreshold) {
+ this.countThreshold = countThreshold;
+ return this;
+ }
+
+ /**
+ * The expected {@link Checksum} value once the input is consumed or the threshold is reached.
+ *
+ * @param expectedChecksumValue The expected Checksum value.
+ * @return this.
+ */
+ public Builder setExpectedChecksumValue(final long expectedChecksumValue) {
+ this.expectedChecksumValue = expectedChecksumValue;
+ return this;
+ }
+
+ }
+
+ /**
+ * Constructs a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /** The expected checksum. */
+ private final long expectedChecksumValue;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input stream
+ * validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private final long countThreshold;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param in the stream to wrap.
+ * @param checksum Checksum implementation.
+ * @param expectedChecksumValue the expected checksum.
+ * @param countThreshold the of the stream's content, a negative number means the threshold is unbound.
+ */
+ private ChecksumInputStream(final InputStream in, final Checksum checksum, final long expectedChecksumValue,
+ final long countThreshold) {
+ super(new CheckedInputStream(in, checksum));
+ this.countThreshold = countThreshold;
+ this.expectedChecksumValue = expectedChecksumValue;
+ }
+
+ @Override
+ protected synchronized void afterRead(final int n) throws IOException {
+ super.afterRead(n);
+ if (getByteCount() >= countThreshold && expectedChecksumValue != getChecksum().getValue()) {
Review Comment:
I'll update one of the tests with a computed checksum.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1439080863
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
Review Comment:
Right! I'll also document using a threshold separately.
##########
src/main/java/org/apache/commons/io/input/ChecksumInputStream.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.
+ * <p>
+ * If the {@link Checksum} does not meet the expected value when exhausted, then the input stream throws a
+ * {@link IOException}.
+ * </p>
+ * <p>
+ * If you do not need the verification or threshold feature, then use a plain {@link CheckedInputStream}.
+ * </p>
+ *
+ * @since 2.16.0
+ */
+public final class ChecksumInputStream extends CountingInputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link ChecksumInputStream} instance.
+ * <p>
+ * There is no default {@link Checksum}, you MUST provide one.
+ * </p>
+ * <h2>Using NIO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setPath(Paths.get("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ *
+ * <h2>Using IO</h2>
+ *
+ * <pre>{@code
+ * ChecksumInputStream s = ChecksumInputStream.builder()
+ * .setFile(new File("MyFile.xml"))
+ * .setChecksum(new CRC32())
+ * .get();
+ * }</pre>
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder<ChecksumInputStream, Builder> {
+
+ /**
+ * There is no default checksum, you MUST provide one. This avoids any issue with a default {@link Checksum}
+ * being proven deficient or insecure in the future.
+ */
+ private Checksum checksum;
+
+ /**
+ * The count threshold to limit how much input is consumed to update the {@link Checksum} before the input
+ * stream validate its value.
+ * <p>
+ * By default, all input updates the {@link Checksum}.
+ * </p>
+ */
+ private long countThreshold = -1;
+
+ /**
+ * The expected {@link Checksum} value.
+ */
+ private long expectedChecksumValue;
+
+ /**
+ * Constructs a new instance.
+ * <p>
+ * This builder use the aspect InputStream.
Review Comment:
I'll rephrase.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add ChecksumInputStream and test [commons-io]
Posted by "garydgregory (via GitHub)" <gi...@apache.org>.
garydgregory commented on code in PR #548:
URL: https://github.com/apache/commons-io/pull/548#discussion_r1442921573
##########
src/test/java/org/apache/commons/io/input/ChecksumInputStreamTest.java:
##########
@@ -0,0 +1,163 @@
+/*
+ * 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.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 java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.Adler32;
+import java.util.zip.CRC32;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ChecksumInputStream}.
+ */
+public class ChecksumInputStreamTest {
+
+ @Test
+ public void testDefaultThresholdFailure() throws IOException {
+ final byte[] byteArray = new byte[3];
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ // Ask to read one more byte than there is, we get the correct byte count.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testDefaultThresholdSuccess() throws IOException {
+ // sanity-check
+ final Adler32 sanityCheck = new Adler32();
+ final byte[] byteArray = new byte[3];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final Adler32 adler32 = new Adler32();
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(-1, checksum.getRemaining());
+ assertEquals(3, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ assertEquals(-1, checksum.read(byteArray));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(-4, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingByteArrayThrowsException() throws IOException {
+ final Adler32 adler32 = new Adler32();
+ final byte[] byteArray = new byte[3];
+ final long sizeThreshold = -1859L;
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(adler32)
+ .setExpectedChecksumValue((byte) -68)
+ .setCountThreshold(sizeThreshold)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(sizeThreshold, checksum.getRemaining());
+ // Ask to read one more byte than there is.
+ assertEquals(byteArray.length, checksum.read(new byte[byteArray.length + 1]));
+ // Next read is at EOF
+ assertThrows(IOException.class, () -> checksum.read(new byte[1]));
+ assertEquals(byteArray.length, checksum.getByteCount());
+ assertEquals(sizeThreshold - byteArray.length, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testReadTakingNoArgumentsThrowsException() throws IOException {
+ final CRC32 crc32 = new CRC32();
+ final byte[] byteArray = new byte[9];
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setByteArray(byteArray)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue((byte) 1)
+ .setCountThreshold(1)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ assertEquals(1, checksum.getRemaining());
+ assertThrows(IOException.class, () -> checksum.read());
+ assertEquals(1, checksum.getByteCount());
+ assertEquals(0, checksum.getRemaining());
+ }
+ }
+
+ @Test
+ public void testSkip() throws IOException {
+ // sanity-check
+ final CRC32 sanityCheck = new CRC32();
+ final byte[] byteArray = new byte[4];
+ sanityCheck.update(byteArray);
+ final long expectedChecksum = sanityCheck.getValue();
+ // actual
+ final CRC32 crc32 = new CRC32();
+ final InputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
+ try (ChecksumInputStream checksum = ChecksumInputStream.builder()
+ // @formatter:off
+ .setInputStream(byteArrayInputStream)
+ .setChecksum(crc32)
+ .setExpectedChecksumValue(expectedChecksum)
+ .setCountThreshold(33)
+ .get()) {
+ // @formatter:on
+ assertEquals(0, checksum.getByteCount());
+ @SuppressWarnings("unused")
Review Comment:
I replaced the suppression with an an assertion. Some static analysis tools flag ignored read() values as a problem because it indicates a lack of EOF detection.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org