Skip to content

Commit 109008a

Browse files
committed
Use HashingOutputStream instead of custom Crc32cHashingOutputStream
1 parent b610455 commit 109008a

1 file changed

Lines changed: 11 additions & 54 deletions

File tree

java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageRpcHasherHelper.java

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,19 @@
1818

1919
import com.google.api.client.http.HttpResponse;
2020
import com.google.api.core.InternalApi;
21+
import com.google.common.hash.Hashing;
22+
import com.google.common.hash.HashingOutputStream;
2123
import com.google.common.io.BaseEncoding;
2224
import com.google.common.primitives.Ints;
2325
import java.io.IOException;
2426
import java.io.OutputStream;
2527
import java.nio.ByteBuffer;
26-
import java.util.List;
2728
import java.util.Map;
2829
import java.util.function.Supplier;
2930

3031
/**
3132
* Internal utility class to perform client-side CRC32C checksum validation on downloaded data
3233
* specifically for the {@code HttpStorageRpc} transport layer.
33-
*
34-
* <p>Since this class resides in the {@code com.google.cloud.storage} package, it has full,
35-
* package-private compile-time access to internal components (like {@link Hasher} and {@link
36-
* Crc32cValue}) without leaking GCS internal types into public client API surfaces.
3734
*/
3835
@InternalApi
3936
public final class HttpStorageRpcHasherHelper {
@@ -50,10 +47,11 @@ private HttpStorageRpcHasherHelper() {
5047
* Returns a wrapping output stream that hashes the written content if validation is enabled, or
5148
* the original output stream otherwise.
5249
*/
50+
@SuppressWarnings("UnstableApiUsage")
5351
public OutputStream wrap(OutputStream out, boolean isChecksumValidationEnabled) {
5452
boolean isHasherEnabled = !(hasher instanceof Hasher.NoOpHasher);
5553
return (isChecksumValidationEnabled && isHasherEnabled)
56-
? new Crc32cHashingOutputStream(out)
54+
? new HashingOutputStream(Hashing.crc32c(), out)
5755
: out;
5856
}
5957

@@ -63,7 +61,7 @@ public OutputStream wrap(OutputStream out, boolean isChecksumValidationEnabled)
6361
* @throws IOException if the checksums do not match.
6462
*/
6563
public void validate(HttpResponse response, byte[] content) throws IOException {
66-
Map<String, String> hashes = extractHashesFromHeader(response);
64+
Map<String, String> hashes = ChecksumResponseParser.extractHashesFromHeader(response);
6765
String expectedCrc32cBase64 = hashes.get("crc32c");
6866
if (expectedCrc32cBase64 != null) {
6967
validateCrc32c(expectedCrc32cBase64, content);
@@ -76,13 +74,15 @@ public void validate(HttpResponse response, byte[] content) throws IOException {
7674
*
7775
* @throws IOException if the checksums do not match.
7876
*/
77+
@SuppressWarnings("UnstableApiUsage")
7978
public void validate(HttpResponse response, OutputStream activeStream) throws IOException {
80-
if (activeStream instanceof Crc32cHashingOutputStream) {
81-
Crc32cHashingOutputStream targetStream = (Crc32cHashingOutputStream) activeStream;
82-
Map<String, String> hashes = extractHashesFromHeader(response);
79+
if (activeStream instanceof HashingOutputStream) {
80+
HashingOutputStream targetStream = (HashingOutputStream) activeStream;
81+
82+
Map<String, String> hashes = ChecksumResponseParser.extractHashesFromHeader(response);
8383
String expectedCrc32cBase64 = hashes.get("crc32c");
8484
if (expectedCrc32cBase64 != null) {
85-
validateCrc32c(expectedCrc32cBase64, targetStream.hash());
85+
validateCrc32c(expectedCrc32cBase64, targetStream.hash().asInt());
8686
}
8787
}
8888
}
@@ -127,47 +127,4 @@ public ByteBuffer get() {
127127
}
128128
});
129129
}
130-
131-
@SuppressWarnings("UnstableApiUsage")
132-
private static class Crc32cHashingOutputStream extends java.io.FilterOutputStream {
133-
private final com.google.common.hash.Hasher hasher;
134-
135-
Crc32cHashingOutputStream(OutputStream out) {
136-
super(out);
137-
this.hasher = com.google.common.hash.Hashing.crc32c().newHasher();
138-
}
139-
140-
@Override
141-
public void write(int b) throws IOException {
142-
out.write(b);
143-
hasher.putByte((byte) b);
144-
}
145-
146-
@Override
147-
public void write(byte[] b, int off, int len) throws IOException {
148-
out.write(b, off, len);
149-
hasher.putBytes(b, off, len);
150-
}
151-
152-
int hash() {
153-
return hasher.hash().asInt();
154-
}
155-
}
156-
157-
private static Map<String, String> extractHashesFromHeader(HttpResponse response) {
158-
List<String> hashHeaders = response.getHeaders().getHeaderStringValues("x-goog-hash");
159-
if (hashHeaders == null || hashHeaders.isEmpty()) {
160-
return java.util.Collections.emptyMap();
161-
}
162-
163-
return hashHeaders.stream()
164-
.flatMap(h -> java.util.Arrays.stream(h.split(",")))
165-
.map(String::trim)
166-
.filter(s -> !s.isEmpty())
167-
.map(s -> s.split("=", 2))
168-
.filter(a -> a.length == 2)
169-
.filter(a -> "crc32c".equalsIgnoreCase(a[0]) || "md5".equalsIgnoreCase(a[0]))
170-
.collect(
171-
java.util.stream.Collectors.toMap(a -> a[0].toLowerCase(), a -> a[1], (v1, v2) -> v1));
172-
}
173130
}

0 commit comments

Comments
 (0)