diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/BaseObjectReadSessionStreamRead.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/BaseObjectReadSessionStreamRead.java index 0032d1a2da91..a590f404e57b 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/BaseObjectReadSessionStreamRead.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/BaseObjectReadSessionStreamRead.java @@ -151,7 +151,7 @@ private AccumulatingRead( super(rangeSpec, retryContext, onCloseCallback); this.readId = readId; this.hasher = - (rangeSpec.begin() == 0 && !(hasher instanceof Hasher.NoOpHasher)) + (rangeSpec.begin() == 0) ? new CumulativeHasher(hasher, 0, rangeSpec.maxLength()) : hasher; this.complete = SettableApiFuture.create(); @@ -284,7 +284,7 @@ static class StreamingRead extends BaseObjectReadSessionStreamRead expected = Crc32cValue.of(metadata.getChecksums().getCrc32C()); Crc32cLengthKnown actual = getCumulativeHash(); + if (actual == null) { + return; + } + Crc32cValue expected = Crc32cValue.of(metadata.getChecksums().getCrc32C()); if (!actual.eqValue(expected)) { throw new UncheckedCumulativeChecksumMismatchException(expected, actual); } @@ -132,7 +135,7 @@ void validateCumulativeChecksum(Object metadata) } private void accumulate(Crc32cLengthKnown actual) { - cumulativeHash = cumulativeHash.concat(actual); + cumulativeHash = nullSafeConcat(cumulativeHash, actual); } Crc32cLengthKnown getCumulativeHash() { diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicDownloadSessionBuilder.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicDownloadSessionBuilder.java index 3bbba1d703ea..bb24799b4fe8 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicDownloadSessionBuilder.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicDownloadSessionBuilder.java @@ -67,7 +67,7 @@ private ReadableByteChannelSessionBuilder( this.read = read; this.retrier = retrier; this.resultRetryAlgorithm = resultRetryAlgorithm; - this.hasher = Hasher.defaultHasher(); + this.hasher = Hasher.readHasher(); this.autoGzipDecompression = false; } diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedReadableByteChannel.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedReadableByteChannel.java index f17bd942fd31..4f5e45516ff8 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedReadableByteChannel.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedReadableByteChannel.java @@ -93,7 +93,7 @@ final class GapicUnbufferedReadableByteChannel this.read = read; this.req = req; this.hasher = - (req.getReadOffset() == 0 && !(hasher instanceof Hasher.NoOpHasher)) + (req.getReadOffset() == 0) ? new CumulativeHasher( hasher, 0, diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcBlobReadChannel.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcBlobReadChannel.java index 9113af1e0c91..9dd39dfe47ea 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcBlobReadChannel.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcBlobReadChannel.java @@ -62,7 +62,7 @@ protected LazyReadChannel newLazyReadChannel() { ResumableMedia.gapic() .read() .byteChannel(read, retrier, resultRetryAlgorithm) - .setHasher(Hasher.defaultHasher()) + .setHasher(Hasher.readHasher()) .setAutoGzipDecompression(autoGzipDecompression); BufferHandle bufferHandle = getBufferHandle(); // because we're erasing the specific type of channel, we need to declare it here. diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java index ed97152b2584..62ca7c076b72 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java @@ -57,6 +57,27 @@ final class DefaultInstanceHolder { } } + final class ReadInstanceHolder { + private static final Logger LOGGER = Logger.getLogger(Hasher.class.getName()); + private static final String PROPERTY_NAME = "com.google.cloud.storage.Hasher.read"; + private static final String PROPERTY_VALUE = + System.getProperty(PROPERTY_NAME, DefaultInstanceHolder.PROPERTY_VALUE); + static final Hasher READ_HASHER; + + static { + LOGGER.fine(String.format(Locale.US, "-D%s=%s", PROPERTY_NAME, PROPERTY_VALUE)); + if ("disabled".equalsIgnoreCase(PROPERTY_VALUE)) { + READ_HASHER = noop(); + } else { + READ_HASHER = enabled(); + } + } + } + + static Hasher readHasher() { + return ReadInstanceHolder.READ_HASHER; + } + @Nullable default Crc32cLengthKnown hash(Supplier b) { return hash(b.get()); diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsChannel.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsChannel.java index 48f2e1582777..c8350208b519 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsChannel.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsChannel.java @@ -46,7 +46,7 @@ @BetaApi @Immutable public final class ReadAsChannel extends BaseConfig { - static final ReadAsChannel INSTANCE = new ReadAsChannel(RangeSpec.all(), Hasher.enabled()); + static final ReadAsChannel INSTANCE = new ReadAsChannel(RangeSpec.all(), Hasher.readHasher()); private final RangeSpec range; private final Hasher hasher; @@ -97,7 +97,7 @@ public ReadAsChannel withRangeSpec(RangeSpec range) { */ @BetaApi boolean getCrc32cValidationEnabled() { - return Hasher.enabled().equals(hasher); + return !Hasher.noop().equals(hasher); } /** @@ -111,7 +111,7 @@ boolean getCrc32cValidationEnabled() { */ @BetaApi ReadAsChannel withCrc32cValidationEnabled(boolean enabled) { - if (enabled && Hasher.enabled().equals(hasher)) { + if (enabled && !Hasher.noop().equals(hasher)) { return this; } else if (!enabled && Hasher.noop().equals(hasher)) { return this; diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureByteString.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureByteString.java index aa7eee536d1c..2b197b838db0 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureByteString.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureByteString.java @@ -46,7 +46,7 @@ public final class ReadAsFutureByteString extends BaseConfig, AccumulatingRead> { static final ReadAsFutureByteString INSTANCE = - new ReadAsFutureByteString(RangeSpec.all(), Hasher.enabled()); + new ReadAsFutureByteString(RangeSpec.all(), Hasher.readHasher()); private final RangeSpec range; private final Hasher hasher; @@ -97,7 +97,7 @@ public ReadAsFutureByteString withRangeSpec(RangeSpec range) { */ @BetaApi boolean getCrc32cValidationEnabled() { - return Hasher.enabled().equals(hasher); + return !Hasher.noop().equals(hasher); } /** @@ -111,7 +111,7 @@ boolean getCrc32cValidationEnabled() { */ @BetaApi ReadAsFutureByteString withCrc32cValidationEnabled(boolean enabled) { - if (enabled && Hasher.enabled().equals(hasher)) { + if (enabled && !Hasher.noop().equals(hasher)) { return this; } else if (!enabled && Hasher.noop().equals(hasher)) { return this; diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureBytes.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureBytes.java index 722b01bc2972..0ffae6163d1d 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureBytes.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsFutureBytes.java @@ -41,7 +41,7 @@ public final class ReadAsFutureBytes extends BaseConfig, AccumulatingRead> { static final ReadAsFutureBytes INSTANCE = - new ReadAsFutureBytes(RangeSpec.all(), Hasher.enabled()); + new ReadAsFutureBytes(RangeSpec.all(), Hasher.readHasher()); private final RangeSpec range; private final Hasher hasher; @@ -92,7 +92,7 @@ public ReadAsFutureBytes withRangeSpec(RangeSpec range) { */ @BetaApi boolean getCrc32cValidationEnabled() { - return Hasher.enabled().equals(hasher); + return !Hasher.noop().equals(hasher); } /** @@ -106,7 +106,7 @@ boolean getCrc32cValidationEnabled() { */ @BetaApi ReadAsFutureBytes withCrc32cValidationEnabled(boolean enabled) { - if (enabled && Hasher.enabled().equals(hasher)) { + if (enabled && !Hasher.noop().equals(hasher)) { return this; } else if (!enabled && Hasher.noop().equals(hasher)) { return this; diff --git a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsSeekableChannel.java b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsSeekableChannel.java index b0b098e7afee..61cdef81bf46 100644 --- a/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsSeekableChannel.java +++ b/java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/ReadAsSeekableChannel.java @@ -46,7 +46,8 @@ public final class ReadAsSeekableChannel extends ReadProjectionConfig { static final ReadAsSeekableChannel INSTANCE = - new ReadAsSeekableChannel(Hasher.enabled(), LinearExponentialRangeSpecFunction.INSTANCE); + new ReadAsSeekableChannel( + Hasher.readHasher(), LinearExponentialRangeSpecFunction.INSTANCE); private final Hasher hasher; private final RangeSpecFunction rangeSpecFunction; @@ -94,7 +95,7 @@ public ReadAsSeekableChannel withRangeSpecFunction(RangeSpecFunction rangeSpecFu */ @BetaApi boolean getCrc32cValidationEnabled() { - return Hasher.enabled().equals(hasher); + return !Hasher.noop().equals(hasher); } /** @@ -108,7 +109,7 @@ boolean getCrc32cValidationEnabled() { */ @BetaApi ReadAsSeekableChannel withCrc32cValidationEnabled(boolean enabled) { - if (enabled && Hasher.enabled().equals(hasher)) { + if (enabled && !Hasher.noop().equals(hasher)) { return this; } else if (!enabled && Hasher.noop().equals(hasher)) { return this;