This is an automated email from the ASF dual-hosted git repository. reschke pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push: new b07f74861f OAK-11793: remove usage of Guava common.hash (#2378) b07f74861f is described below commit b07f74861fe206833d65f0459340d90244bd787e Author: Julian Reschke <resc...@apache.org> AuthorDate: Fri Jul 11 10:56:30 2025 +0200 OAK-11793: remove usage of Guava common.hash (#2378) --- .../oak/plugins/memory/AbstractBlob.java | 63 +++++++--------------- .../oak/plugins/memory/AbstractBlobTest.java | 27 ++++++++++ 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlob.java b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlob.java index f0bca90bf9..32723973b1 100644 --- a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlob.java +++ b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlob.java @@ -19,15 +19,15 @@ package org.apache.jackrabbit.oak.plugins.memory; import java.io.IOException; -import java.io.InputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import org.apache.commons.io.IOUtils; -import org.apache.jackrabbit.guava.common.hash.HashCode; -import org.apache.jackrabbit.guava.common.hash.Hashing; import org.apache.jackrabbit.oak.api.Blob; import org.apache.jackrabbit.oak.commons.properties.SystemPropertySupplier; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +66,7 @@ public abstract class AbstractBlob implements Blob { //Check for identity first. If they are same then its //definitely same blob. If not we need to check further. - if (ai != null && bi != null && ai.equals(bi)){ + if (ai != null && ai.equals(bi)){ return true; } @@ -81,34 +81,9 @@ public abstract class AbstractBlob implements Blob { } } - public static HashCode calculateSha256(final Blob blob) { - AbstractBlob ab; - if (blob instanceof AbstractBlob) { - ab = ((AbstractBlob) blob); - } else { - ab = new AbstractBlob() { - @Override - public long length() { - return blob.length(); - } - - @Override public boolean isInlined() { - return blob.isInlined(); - } - - @NotNull - @Override - public InputStream getNewStream() { - return blob.getNewStream(); - } - }; - } - return ab.getSha256(); - } + private ByteBuffer hashCode; // synchronized access - private HashCode hashCode; // synchronized access - - protected AbstractBlob(HashCode hashCode) { + protected AbstractBlob(ByteBuffer hashCode) { this.hashCode = hashCode; } @@ -116,26 +91,21 @@ public abstract class AbstractBlob implements Blob { this(null); } - private synchronized HashCode getSha256() { + private synchronized ByteBuffer getSha256() { // Blobs are immutable so we can safely cache the hash if (hashCode == null) { try { - hashCode = Hashing.sha256().hashBytes(this.getNewStream().readAllBytes()); + MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); + hashCode = ByteBuffer.wrap(sha256.digest(this.getNewStream().readAllBytes())); } catch (IOException e) { throw new IllegalStateException("Hash calculation failed", e); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); } } return hashCode; } - /** - * This hash code implementation returns the hash code of the underlying stream - * @return a byte array of the hash - */ - protected byte[] sha256() { - return getSha256().asBytes(); - } - //--------------------------------------------------------------< Blob >-- @Override @Nullable @@ -152,7 +122,7 @@ public abstract class AbstractBlob implements Blob { /** * To {@code Blob} instances are considered equal iff they have the - * same SHA-256 hash code are equal. + * same SHA-256 hash code or are equal. * @param other */ @Override @@ -186,7 +156,10 @@ public abstract class AbstractBlob implements Blob { @Override public String toString() { - return getSha256().toString(); + // https://www.baeldung.com/java-byte-arrays-hex-strings#using-thebiginteger-class + // could use Java 17 HexFormat in the future + byte[] bytes = getSha256().array(); + BigInteger bigInteger = new BigInteger(1, bytes); + return String.format("%0" + (bytes.length << 1) + "x", bigInteger); } - } diff --git a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlobTest.java b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlobTest.java index fac92f2666..7dd8008ac1 100644 --- a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlobTest.java +++ b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/plugins/memory/AbstractBlobTest.java @@ -27,7 +27,9 @@ import org.apache.jackrabbit.oak.commons.conditions.Validate; import org.jetbrains.annotations.NotNull; import org.junit.Test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; public class AbstractBlobTest { @@ -54,6 +56,31 @@ public class AbstractBlobTest { assertFalse("Blob comparison should not fallback on content if lengths not same", AbstractBlob.equal(a, b)); } + @Test + public void blobArrayBasedToString() { + byte[] bytes = bytes(100); + Blob a = new ArrayBasedBlob(bytes); + Blob b = new ArrayBasedBlob(bytes); + Blob c = new ArrayBasedBlob(bytes(50)); + assertEquals(a.toString(), b.toString()); + assertNotEquals(b.toString(), c.toString()); + } + + @Test + public void blobArrayBasedEquality() { + byte[] bytes = bytes(100); + Blob a = new ArrayBasedBlob(bytes); + Blob b = new ArrayBasedBlob(bytes); + Blob c = new ArrayBasedBlob(bytes(50)); + + assertEquals(a, b); + assertNotEquals(a, c); + + // same length bypass comparison shortcut + Blob d = new ArrayBasedBlob(bytes(100)); + assertNotEquals(a, d); + } + private byte[] bytes(int size) { byte[] data = new byte[size]; rnd.nextBytes(data);