From d85bdb3313bdefd9e5b29bc7305df6f2d1afb3f2 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 10:33:51 -0300 Subject: [PATCH 01/40] Remove deprecated methods related to name-based UUID --- .../com/github/f4b6a3/uuid/UuidCreator.java | 144 ------------------ .../java/com/github/f4b6a3/uuid/alt/GUID.java | 53 ++----- .../com/github/f4b6a3/uuid/alt/GUIDTest.java | 31 ---- 3 files changed, 11 insertions(+), 217 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index d4b0f757..69abebb8 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -664,20 +664,6 @@ public static UUID getNameBasedMd5(byte[] name) { return NameBasedMd5Holder.INSTANCE.create(name); } - /** - * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param name a UUID - * @return a UUIDv3 - * @see NameBasedMd5Factory - */ - @Deprecated - public static UUID getNameBasedMd5(UUID name) { - return NameBasedMd5Holder.INSTANCE.create(name); - } - /** * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). *

@@ -706,22 +692,6 @@ public static UUID getNameBasedMd5(UUID namespace, byte[] name) { return NameBasedMd5Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a custom name space UUID - * @param name a UUID - * @return a UUIDv3 - * @see UuidNamespace - * @see NameBasedMd5Factory - */ - @Deprecated - public static UUID getNameBasedMd5(UUID namespace, UUID name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); - } - /** * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). *

@@ -752,23 +722,6 @@ public static UUID getNameBasedMd5(String namespace, byte[] name) { return NameBasedMd5Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a custom name space UUID in string format - * @param name a UUID - * @return a UUIDv3 - * @throws InvalidUuidException if namespace is invalid - * @see UuidNamespace - * @see NameBasedMd5Factory - */ - @Deprecated - public static UUID getNameBasedMd5(String namespace, UUID name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); - } - /** * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). *

@@ -813,31 +766,6 @@ public static UUID getNameBasedMd5(UuidNamespace namespace, byte[] name) { return NameBasedMd5Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses MD5 hashing (UUIDv3). - * - * @deprecated This method will be removed when the new RFC is published. - *

- * Name spaces predefined by RFC-4122 (Appendix C): - *

- * - * @param namespace a predefined name space enumeration - * @param name a UUID - * @return a UUIDv3 - * @see UuidNamespace - * @see NameBasedMd5Factory - */ - @Deprecated - public static UUID getNameBasedMd5(UuidNamespace namespace, UUID name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); - } - /** * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). *

@@ -862,20 +790,6 @@ public static UUID getNameBasedSha1(byte[] name) { return NameBasedSha1Holder.INSTANCE.create(name); } - /** - * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param name a UUID - * @return a UUIDv5 - * @see NameBasedSha1Factory - */ - @Deprecated - public static UUID getNameBasedSha1(UUID name) { - return NameBasedSha1Holder.INSTANCE.create(name); - } - /** * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). *

@@ -904,22 +818,6 @@ public static UUID getNameBasedSha1(UUID namespace, byte[] name) { return NameBasedSha1Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a custom name space UUID - * @param name a UUID - * @return a UUIDv5 - * @see UuidNamespace - * @see NameBasedSha1Factory - */ - @Deprecated - public static UUID getNameBasedSha1(UUID namespace, UUID name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); - } - /** * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). *

@@ -950,23 +848,6 @@ public static UUID getNameBasedSha1(String namespace, byte[] name) { return NameBasedSha1Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a custom name space UUID in string format - * @param name a UUID - * @return a UUIDv5 - * @throws InvalidUuidException if namespace is invalid - * @see UuidNamespace - * @see NameBasedSha1Factory - */ - @Deprecated - public static UUID getNameBasedSha1(String namespace, UUID name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); - } - /** * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). *

@@ -1011,31 +892,6 @@ public static UUID getNameBasedSha1(UuidNamespace namespace, byte[] name) { return NameBasedSha1Holder.INSTANCE.create(namespace, name); } - /** - * Returns a name-based unique identifier that uses SHA-1 hashing (UUIDv5). - * - * @deprecated This method will be removed when the new RFC is published. - *

- * Name spaces predefined by RFC-4122 (Appendix C): - *

- * - * @param namespace a predefined name space enumeration - * @param name a UUID - * @return a UUIDv5 - * @see UuidNamespace - * @see NameBasedSha1Factory - */ - @Deprecated - public static UUID getNameBasedSha1(UuidNamespace namespace, UUID name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); - } - /** * Returns a DCE Security unique identifier (UUIDv2). * diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 94b76d07..45772a5b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -122,7 +122,6 @@ public final class GUID implements Serializable, Comparable { private static final long MASK_32 = 0x0000_0000_ffff_ffffL; private static final long MULTICAST = 0x0000_0100_0000_0000L; - private static final GUID HASHSPACE_SHA2_256 = new GUID(0x3fb32780953c4464L, 0x9cfde85dbbe9843dL); /** * Creates a new GUID. @@ -243,12 +242,13 @@ public static GUID v2(byte localDomain, int localIdentifier) { * GUID guid = GUID.v3(Uuid.NAMESPACE_DNS, "www.example.com"); * } * - * @param namespace a GUID + * @param namespace a GUID (optional) * @param name a string * @return a GUID + * @throws IllegalArgumentException if the name is null */ public static GUID v3(GUID namespace, String name) { - return hash(3, "MD5", null, namespace, name); + return hash(3, "MD5", namespace, name); } /** @@ -284,12 +284,13 @@ public static GUID v4() { * GUID guid = GUID.v5(Uuid.NAMESPACE_DNS, "www.example.com"); * } * - * @param namespace a GUID + * @param namespace a GUID (optional) * @param name a string * @return a GUID + * @throws IllegalArgumentException if the name is null */ public static GUID v5(GUID namespace, String name) { - return hash(5, "SHA-1", null, namespace, name); + return hash(5, "SHA-1", namespace, name); } /** @@ -332,35 +333,6 @@ public static GUID v7() { return version(msb, lsb, 7); } - /** - * Returns a name-based unique identifier that uses SHA-256 hashing (UUIDv8). - *

- * Usage: - * - *

{@code
-	 * GUID guid = GUID.v8(Uuid.NAMESPACE_DNS, "www.example.com");
-	 * }
- * - * @deprecated This method is no longer supported due to recent sudden changes - * in the UUIDv8 discussions. It will be removed when the new RFC is - * finally published. - *

- * See the latest discussions about UUIDv8: - *

- * - * @param namespace a GUID - * @param name a string - * @return a GUID - */ - @Deprecated - public static GUID v8(GUID namespace, String name) { - return hash(8, "SHA-256", HASHSPACE_SHA2_256, namespace, name); - } - /** * Checks if the GUID string is valid. * @@ -503,7 +475,11 @@ private static long gregorian() { return time; } - private static GUID hash(int version, String algorithm, GUID hashspace, GUID namespace, String name) { + private static GUID hash(int version, String algorithm, GUID namespace, String name) { + + if (name == null) { + throw new IllegalArgumentException("Null name"); + } MessageDigest hasher = null; try { @@ -512,13 +488,6 @@ private static GUID hash(int version, String algorithm, GUID hashspace, GUID nam throw new IllegalArgumentException(String.format("%s not supported", algorithm)); } - if (hashspace != null) { - ByteBuffer ns = ByteBuffer.allocate(16); - ns.putLong(hashspace.msb); - ns.putLong(hashspace.lsb); - hasher.update(ns.array()); - } - if (namespace != null) { ByteBuffer ns = ByteBuffer.allocate(16); ns.putLong(namespace.msb); diff --git a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java index ec35a44c..61b23365 100644 --- a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java @@ -155,7 +155,6 @@ public void testV3() { assertNotEquals(GUID.v3(null, name), GUID.v3(namespace, name)); assertNotEquals(GUID.v3(GUID.NIL, name), GUID.v3(namespace, name)); assertNotEquals(GUID.v3(namespace, name), GUID.v5(namespace, name)); // v5 - assertNotEquals(GUID.v3(namespace, name), GUID.v8(namespace, name)); // v8 assertEquals(GUID.v3(null, name), GUID.v3(null, name)); assertEquals(GUID.v3(GUID.NIL, name), GUID.v3(GUID.NIL, name)); assertEquals(GUID.v3(namespace, name), GUID.v3(namespace, name)); @@ -199,7 +198,6 @@ public void testV5() { assertNotEquals(GUID.v5(null, name), GUID.v5(namespace, name)); assertNotEquals(GUID.v5(GUID.NIL, name), GUID.v5(namespace, name)); assertNotEquals(GUID.v5(namespace, name), GUID.v3(namespace, name)); // v3 - assertNotEquals(GUID.v5(namespace, name), GUID.v8(namespace, name)); // v8 assertEquals(GUID.v5(null, name), GUID.v5(null, name)); assertEquals(GUID.v5(GUID.NIL, name), GUID.v5(GUID.NIL, name)); assertEquals(GUID.v5(namespace, name), GUID.v5(namespace, name)); @@ -250,35 +248,6 @@ public void testV7() { } } - @Test - public void testV8() { - GUID prev = GUID.v8(GUID.NIL, ""); - for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - GUID namespace = new GUID(UUID.randomUUID()); - String name = UUID.randomUUID().toString(); - GUID guid = GUID.v8(namespace, name); - assertNotNull(guid); - assertNotEquals(prev, guid); - assertEquals(8, guid.version()); - assertNotEquals(GUID.NIL, guid); - assertNotEquals(GUID.MAX, guid); - assertNotEquals(GUID.v8(null, name), GUID.v8(namespace, name)); - assertNotEquals(GUID.v8(GUID.NIL, name), GUID.v8(namespace, name)); - assertNotEquals(GUID.v8(namespace, name), GUID.v3(namespace, name)); // v3 - assertNotEquals(GUID.v8(namespace, name), GUID.v5(namespace, name)); // v5 - assertEquals(GUID.v8(null, name), GUID.v8(null, name)); - assertEquals(GUID.v8(GUID.NIL, name), GUID.v8(GUID.NIL, name)); - assertEquals(GUID.v8(namespace, name), GUID.v8(namespace, name)); - prev = guid; - } - { - // Example of a UUIDv8 Value - // draft-ietf-uuidrev-rfc4122bis-03 - GUID guid = GUID.v8(GUID.NAMESPACE_DNS, "www.example.com"); - assertEquals("401835fd-a627-870a-873f-ed73f2bc5b2c", guid.toString()); - } - } - @Test public void testToUUID() { Random random = new Random(); From 02d45620264a4b88247d94e5aacdc72ce90dc2d5 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 11:12:44 -0300 Subject: [PATCH 02/40] Make all factories inherit from the abstract class UuidFactory --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 11 +- .../uuid/factory/AbstNameBasedFactory.java | 156 +++--------- .../uuid/factory/AbstRandomBasedFactory.java | 8 +- .../uuid/factory/AbstTimeBasedFactory.java | 7 +- .../f4b6a3/uuid/factory/NoArgsFactory.java | 39 --- .../f4b6a3/uuid/factory/UuidFactory.java | 238 ++++++++++++++++++ .../factory/rfc4122/NameBasedMd5Factory.java | 6 +- .../factory/rfc4122/NameBasedSha1Factory.java | 6 +- .../f4b6a3/uuid/factory/UuidFactoryTest.java | 4 +- 9 files changed, 297 insertions(+), 178 deletions(-) delete mode 100644 src/main/java/com/github/f4b6a3/uuid/factory/NoArgsFactory.java diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 45772a5b..57b96fc5 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -31,6 +31,7 @@ import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.Arrays; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @@ -245,7 +246,7 @@ public static GUID v2(byte localDomain, int localIdentifier) { * @param namespace a GUID (optional) * @param name a string * @return a GUID - * @throws IllegalArgumentException if the name is null + * @throws NullPointerException if the name is null */ public static GUID v3(GUID namespace, String name) { return hash(3, "MD5", namespace, name); @@ -287,7 +288,7 @@ public static GUID v4() { * @param namespace a GUID (optional) * @param name a string * @return a GUID - * @throws IllegalArgumentException if the name is null + * @throws NullPointerException if the name is null */ public static GUID v5(GUID namespace, String name) { return hash(5, "SHA-1", namespace, name); @@ -477,15 +478,13 @@ private static long gregorian() { private static GUID hash(int version, String algorithm, GUID namespace, String name) { - if (name == null) { - throw new IllegalArgumentException("Null name"); - } + Objects.requireNonNull(name, "Null name"); MessageDigest hasher = null; try { hasher = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(String.format("%s not supported", algorithm)); + throw new IllegalArgumentException(e.getMessage()); } if (namespace != null) { diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java index 2a28661d..eab2cda2 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java @@ -24,13 +24,11 @@ package com.github.f4b6a3.uuid.factory; -import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Objects; import java.util.UUID; -import com.github.f4b6a3.uuid.codec.BinaryCodec; -import com.github.f4b6a3.uuid.codec.StringCodec; import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.enums.UuidVersion; import com.github.f4b6a3.uuid.exception.InvalidUuidException; @@ -43,6 +41,9 @@ * Abstract factory for creating name-based unique identifiers (UUIDv3 and * UUIDv5). * + * The name space is optional for compatibility with the JDK's UUID method for + * generating UUIDv3, which is {@link UUID#nameUUIDFromBytes(byte[])}. + * * @see UuidNamespace * @see RFC-4122 - * 4.3. Algorithm for Creating a Name-Based UUID @@ -50,9 +51,9 @@ public abstract class AbstNameBasedFactory extends UuidFactory { /** - * The namespace. + * The namespace (optional). */ - protected byte[] namespace = null; + protected byte[] namespace; // can be null /** * The hash algorithm. */ @@ -88,15 +89,12 @@ protected AbstNameBasedFactory(UuidVersion version, String algorithm, byte[] nam throw new IllegalArgumentException("Invalid message digest algorithm"); } - if (namespace == null) { - // null is accepted - this.namespace = null; - } else { + if (namespace != null) { if (namespace.length == 16) { // must be 16 bytes length this.namespace = namespace; } else { - throw new IllegalArgumentException("Invalid namespace length"); + throw new IllegalArgumentException("Invalid namespace"); } } } @@ -106,9 +104,10 @@ protected AbstNameBasedFactory(UuidVersion version, String algorithm, byte[] nam * * @param name a byte array * @return a name-based UUID + * @throws NullPointerException if name is null */ public UUID create(final byte[] name) { - return create(this.namespace, name); + return create(this.namespace, nameBytes(name)); } /** @@ -118,23 +117,10 @@ public UUID create(final byte[] name) { * * @param name a string * @return a name-based UUID + * @throws NullPointerException if name is null */ public UUID create(final String name) { - final byte[] n = name.getBytes(StandardCharsets.UTF_8); - return create(this.namespace, n); - } - - /** - * Returns a name-based UUID. - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param name a UUID - * @return a name-based UUID - */ - @Deprecated - public UUID create(final UUID name) { - return create(this.namespace, bytes(name)); + return create(this.namespace, nameBytes(name)); } /** @@ -143,10 +129,10 @@ public UUID create(final UUID name) { * @param namespace a name space UUID * @param name a byte array * @return a name-based UUID + * @throws IllegalArgumentException if name is null */ public UUID create(final UUID namespace, final byte[] name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - return create(ns, name); + return create(namespaceBytes(namespace), nameBytes(name)); } /** @@ -157,27 +143,10 @@ public UUID create(final UUID namespace, final byte[] name) { * @param namespace a name space UUID * @param name a string * @return a name-based UUID + * @throws NullPointerException if name is null */ public UUID create(final UUID namespace, final String name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = name.getBytes(StandardCharsets.UTF_8); - return create(ns, n); - } - - /** - * Returns a name-based UUID. - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a name space UUID - * @param name a UUID - * @return a name-based UUID - */ - @Deprecated - public UUID create(final UUID namespace, final UUID name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = bytes(name); - return create(ns, n); + return create(namespaceBytes(namespace), nameBytes(name)); } /** @@ -186,12 +155,12 @@ public UUID create(final UUID namespace, final UUID name) { * @param namespace a name space string * @param name a byte array * @return a name-based UUID + * @throws NullPointerException if name is null * @throws InvalidUuidException if the name space is invalid * @see InvalidUuidException */ public UUID create(final String namespace, final byte[] name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - return create(ns, name); + return create(namespaceBytes(namespace), nameBytes(name)); } /** @@ -202,31 +171,12 @@ public UUID create(final String namespace, final byte[] name) { * @param namespace a name space string * @param name a string * @return a name-based UUID + * @throws NullPointerException if name is null * @throws InvalidUuidException if the name space is invalid * @see InvalidUuidException */ public UUID create(final String namespace, final String name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = name.getBytes(StandardCharsets.UTF_8); - return create(ns, n); - } - - /** - * Returns a name-based UUID. - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a name space string - * @param name a UUID - * @return a name-based UUID - * @throws InvalidUuidException if the name space is invalid - * @see InvalidUuidException - */ - @Deprecated - public UUID create(final String namespace, final UUID name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = bytes(name); - return create(ns, n); + return create(namespaceBytes(namespace), nameBytes(name)); } /** @@ -235,11 +185,10 @@ public UUID create(final String namespace, final UUID name) { * @param namespace a name space enumeration * @param name a byte array * @return a name-based UUID - * @see UuidNamespace + * @throws NullPointerException if name is null */ public UUID create(final UuidNamespace namespace, final byte[] name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - return create(ns, name); + return create(namespaceBytes(namespace), nameBytes(name)); } /** @@ -250,71 +199,32 @@ public UUID create(final UuidNamespace namespace, final byte[] name) { * @param namespace a name space enumeration * @param name a string * @return a name-based UUID - * @see UuidNamespace + * @throws NullPointerException if name is null */ public UUID create(final UuidNamespace namespace, final String name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = name.getBytes(StandardCharsets.UTF_8); - return create(ns, n); - } - - /** - * Returns a name-based UUID. - * - * @deprecated This method will be removed when the new RFC is published. - * - * @param namespace a name space enumeration - * @param name a UUID - * @return a name-based UUID - * @see UuidNamespace - */ - @Deprecated - public UUID create(final UuidNamespace namespace, final UUID name) { - final byte[] ns = namespace == null ? null : bytes(namespace); - final byte[] n = bytes(name); - return create(ns, n); - } - - /** - * Converts a name space enumeration into a byte array. - * - * @param namespace a name space enumeration - * @return a byte array - */ - protected static byte[] bytes(UuidNamespace namespace) { - return bytes(namespace.getValue()); + return create(namespaceBytes(namespace), nameBytes(name)); } - /** - * Converts a name space UUID into a byte array. - * - * @param namespace a name space UUID - * @return a byte array - */ - protected static byte[] bytes(UUID namespace) { - return BinaryCodec.INSTANCE.encode(namespace); + @Override + public UUID create() { + return create(Parameters.builder().build()); } - /** - * Converts a name space string into a byte array. - * - * @param namespace a name space string - * @return a byte array - * @throws InvalidUuidException if the name space is invalid - * @see InvalidUuidException - */ - protected static byte[] bytes(String namespace) { - return BinaryCodec.INSTANCE.encode(StringCodec.INSTANCE.decode(namespace)); + @Override + public UUID create(Parameters parameters) { + return create(parameters.getNamespace(), parameters.getName()); } private UUID create(final byte[] namespace, final byte[] name) { + Objects.requireNonNull(name, "Null name"); + MessageDigest hasher; try { hasher = MessageDigest.getInstance(this.algorithm); } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Message digest algorithm not available: " + this.algorithm, e); + throw new IllegalArgumentException(e.getMessage()); } if (namespace != null) { diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java index 7d38b5c0..cf7435c9 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java @@ -26,6 +26,7 @@ import java.security.SecureRandom; import java.util.Random; +import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.ReentrantLock; import java.util.function.IntFunction; @@ -41,7 +42,7 @@ * * @see RandomFunction */ -public abstract class AbstRandomBasedFactory extends UuidFactory implements NoArgsFactory { +public abstract class AbstRandomBasedFactory extends UuidFactory { /** * The random generator. @@ -69,6 +70,11 @@ protected AbstRandomBasedFactory(UuidVersion version, Builder builder) { this.random = builder.getRandom(); } + @Override + public UUID create(Parameters parameters) { + return create(); // ignore parameters + } + /** * Abstract builder for creating a random-based factory. * diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java index 87223abf..7800d663 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java @@ -98,7 +98,7 @@ * @see RFC-4122 - * 4.2. Algorithms for Creating a Time-Based UUID */ -public abstract class AbstTimeBasedFactory extends UuidFactory implements NoArgsFactory { +public abstract class AbstTimeBasedFactory extends UuidFactory { /** * The time function. @@ -169,6 +169,11 @@ public UUID create() { } } + @Override + public UUID create(Parameters parameters) { + return create(); // ignore arguments + } + /** * Returns the most significant bits of the UUID. *

diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/NoArgsFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/NoArgsFactory.java deleted file mode 100644 index 17c9ef7d..00000000 --- a/src/main/java/com/github/f4b6a3/uuid/factory/NoArgsFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2018-2022 Fabio Lima - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.github.f4b6a3.uuid.factory; - -import java.util.UUID; - -/** - * Interface for create methods without arguments. - */ -public interface NoArgsFactory { - /** - * Returns a new UUID. - * - * @return a UUID - */ - public UUID create(); -} diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java index e062f87c..367b5969 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java @@ -24,9 +24,16 @@ package com.github.f4b6a3.uuid.factory; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; import java.util.UUID; +import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StringCodec; +import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.enums.UuidVersion; +import com.github.f4b6a3.uuid.exception.InvalidUuidException; /** * Abstract factory that is base for all UUID factories. @@ -43,6 +50,16 @@ public abstract class UuidFactory { */ protected final long versionMask; + /** + * Default Constructor. + * + * The version used is {@link UuidVersion#VERSION_UNKNOWN}. + */ + public UuidFactory() { + this.version = UuidVersion.VERSION_UNKNOWN; + this.versionMask = (long) version.getValue() << 12; + } + /** * Constructor with a version number. * @@ -62,6 +79,227 @@ public UuidVersion getVersion() { return this.version; } + /** + * Create a UUID + * + * @return a UUID + */ + public abstract UUID create(); + + /** + * Creates a UUID using parameters. + * + * @param parameters parameters object + * @return a UUID + */ + public abstract UUID create(Parameters parameters); + + /** + * Parameters object to be used with a {@link UuidFactory#create(Parameters)}. + */ + public static class Parameters { + + /** + * Name space byte array. + */ + private byte[] namespace; + + /** + * Name byte array. + */ + private byte[] name; + + /** + * Constructor using a builder. + * + * @param builder a builder + */ + public Parameters(Builder builder) { + if (builder != null) { + this.namespace = builder.namespace; + this.name = builder.name; + } + } + + /** + * Get the name space bytes + * + * @return a byte array + */ + public byte[] getNamespace() { + return this.namespace; + } + + /** + * Get the name bytes + * + * @return a byte array + */ + public byte[] getName() { + return this.name; + } + + /** + * Returns a new builder. + * + * @return a builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Parameters builder. + */ + public static class Builder { + + /** + * Name space byte array. + */ + private byte[] namespace = null; + + /** + * Name byte array. + */ + private byte[] name = null; + + private Builder() { + } + + /** + * Use the name space UUID. + * + * @param namespace a name space + * @return the builder + */ + public Builder withNamespace(UUID namespace) { + this.namespace = namespaceBytes(namespace); + return this; + } + + /** + * Use the name space string. + * + * @param namespace a name space + * @return the builder + */ + public Builder withNamespace(String namespace) { + this.namespace = namespaceBytes(namespace); + return this; + } + + /** + * Use the name space enum. + * + * @param namespace a name space + * @return the builder + */ + public Builder withNamespace(UuidNamespace namespace) { + this.namespace = namespaceBytes(namespace); + return this; + } + + /** + * Use the name byte array. + * + * It makes a copy of the input byte array. + * + * @param name a name + * @return the builder + */ + public Builder withName(byte[] name) { + this.name = nameBytes(name); + return this; + } + + /** + * Use the name string. + * + * The string is encoded into UTF-8 byte array. + * + * @param name a name + * @return the builder + */ + public Builder withName(String name) { + this.name = nameBytes(name); + return this; + } + + /** + * Finishes the parameters build. + * + * @return the build parameters. + */ + public Parameters build() { + return new Parameters(this); + } + } + } + + /** + * Returns a copy of the input byte array. + * + * @param name a name string + * @return a byte array + * @throws IllegalArgumentException if the input is null + */ + protected static byte[] nameBytes(byte[] name) { + Objects.requireNonNull(name, "Null name"); + return Arrays.copyOf(name, name.length); + } + + /** + * Converts a name string into a byte array. + * + * @param name a name string + * @return a byte array + * @throws IllegalArgumentException if the input is null + */ + protected static byte[] nameBytes(String name) { + Objects.requireNonNull(name, "Null name"); + return name.getBytes(StandardCharsets.UTF_8); + } + + /** + * Converts a name space enumeration into a byte array. + * + * @param namespace a name space enumeration + * @return a byte array + */ + protected static byte[] namespaceBytes(UuidNamespace namespace) { + if (namespace != null) { + return namespaceBytes(namespace.getValue()); + } + return null; // the name space can be null + } + + /** + * Converts a name space UUID into a byte array. + * + * @param namespace a name space UUID + * @return a byte array + */ + protected static byte[] namespaceBytes(UUID namespace) { + if (namespace != null) { + return BinaryCodec.INSTANCE.encode(namespace); + } + return null; // the name space can be null + } + + /** + * Converts a name space string into a byte array. + * + * @param namespace a name space string + * @return a byte array + * @throws InvalidUuidException if the name space is invalid + */ + protected static byte[] namespaceBytes(String namespace) { + if (namespace != null) { + return BinaryCodec.INSTANCE.encode(StringCodec.INSTANCE.decode(namespace)); + } + return null; // the name space can be null + } + /** * Creates a UUID from a pair of numbers. *

diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java index 73074c3e..8036942a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java @@ -51,7 +51,7 @@ public NameBasedMd5Factory() { * @param namespace a namespace */ public NameBasedMd5Factory(UUID namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } /** @@ -60,7 +60,7 @@ public NameBasedMd5Factory(UUID namespace) { * @param namespace a namespace */ public NameBasedMd5Factory(String namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } /** @@ -69,7 +69,7 @@ public NameBasedMd5Factory(String namespace) { * @param namespace a namespace */ public NameBasedMd5Factory(UuidNamespace namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } private NameBasedMd5Factory(byte[] namespace) { diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java index 433e7fbc..22f8aef8 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java @@ -51,7 +51,7 @@ public NameBasedSha1Factory() { * @param namespace a namespace */ public NameBasedSha1Factory(UUID namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } /** @@ -60,7 +60,7 @@ public NameBasedSha1Factory(UUID namespace) { * @param namespace a namespace */ public NameBasedSha1Factory(String namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } /** @@ -69,7 +69,7 @@ public NameBasedSha1Factory(String namespace) { * @param namespace a namespace */ public NameBasedSha1Factory(UuidNamespace namespace) { - this(bytes(namespace)); + this(namespaceBytes(namespace)); } private NameBasedSha1Factory(byte[] namespace) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java index 85333fef..f3b2bb43 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java @@ -115,10 +115,10 @@ protected void testGetAbstractTimeBased(AbstTimeBasedFactory factory, boolean mu public static class TestThread extends Thread { public static Set hashSet = new HashSet<>(); - private NoArgsFactory factory; + private UuidFactory factory; private int loopLimit; - public TestThread(NoArgsFactory factory, int loopLimit) { + public TestThread(UuidFactory factory, int loopLimit) { this.factory = factory; this.loopLimit = loopLimit; } From 9b5b145c97a8ded2b1e1c71c18251535750cb3f2 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 11:13:06 -0300 Subject: [PATCH 03/40] Update benchmark/run.sh --- benchmark/run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmark/run.sh b/benchmark/run.sh index c48822e0..6a74b00c 100755 --- a/benchmark/run.sh +++ b/benchmark/run.sh @@ -9,7 +9,7 @@ SCRIPT_DIR=$(dirname "$0") cd "${SCRIPT_DIR}/.." # compile the parent project -mvn --batch-mode --quiet --fail-fast clean install -DskipTests +./mvnw --batch-mode --quiet --fail-fast clean install -DskipTests # create a copy with the expected name cp "${PWD}/target/${ARTIFACT_ID}"-*-SNAPSHOT.jar "${PWD}/target/${ARTIFACT_ID}"-0.0.1-BENCHMARK.jar @@ -18,8 +18,8 @@ cp "${PWD}/target/${ARTIFACT_ID}"-*-SNAPSHOT.jar "${PWD}/target/${ARTIFACT_ID}"- cd benchmark # compile the benchmark project -mvn --batch-mode --quiet --fail-fast validate -mvn --batch-mode --quiet --fail-fast clean install +../mvnw --batch-mode --quiet --fail-fast validate +../mvnw --batch-mode --quiet --fail-fast clean install # run the benchmark java -jar target/benchmarks.jar From 356a5e40ef92671067509caae2929e1d6307f740 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 11:38:57 -0300 Subject: [PATCH 04/40] Add parameters to UuidFactory for DCE Security UUIDs --- .../f4b6a3/uuid/factory/UuidFactory.java | 85 +++++++++++++++++-- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java index 367b5969..10a056ec 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java @@ -31,6 +31,7 @@ import com.github.f4b6a3.uuid.codec.BinaryCodec; import com.github.f4b6a3.uuid.codec.StringCodec; +import com.github.f4b6a3.uuid.enums.UuidLocalDomain; import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.enums.UuidVersion; import com.github.f4b6a3.uuid.exception.InvalidUuidException; @@ -102,12 +103,22 @@ public static class Parameters { /** * Name space byte array. */ - private byte[] namespace; + private final byte[] namespace; /** * Name byte array. */ - private byte[] name; + private final byte[] name; + + /** + * Local domain byte. + */ + private final byte localDomain; + + /** + * Local identifier number. + */ + private final int localIdentifier; /** * Constructor using a builder. @@ -115,10 +126,11 @@ public static class Parameters { * @param builder a builder */ public Parameters(Builder builder) { - if (builder != null) { - this.namespace = builder.namespace; - this.name = builder.name; - } + Objects.requireNonNull(builder); + this.namespace = builder.namespace; + this.name = builder.name; + this.localDomain = builder.localDomain; + this.localIdentifier = builder.localIdentifier; } /** @@ -139,6 +151,24 @@ public byte[] getName() { return this.name; } + /** + * Get the local domain. + * + * @return the local domain + */ + public byte getLocalDomain() { + return this.localDomain; + } + + /** + * Get the local identifier. + * + * @return the local identifier + */ + public int getLocalIdentifier() { + return this.localIdentifier; + } + /** * Returns a new builder. * @@ -163,6 +193,16 @@ public static class Builder { */ private byte[] name = null; + /** + * Local domain byte. + */ + private byte localDomain; + + /** + * Local identifier number. + */ + private int localIdentifier; + private Builder() { } @@ -225,6 +265,39 @@ public Builder withName(String name) { return this; } + /** + * Use the local domain. + * + * @param localDomain the local domain + * @return the builder + */ + public Builder withLocalDomain(UuidLocalDomain localDomain) { + this.localDomain = localDomain.getValue(); + return this; + } + + /** + * Use the local domain. + * + * @param localDomain the local domain + * @return the builder + */ + public Builder withLocalDomain(byte localDomain) { + this.localDomain = localDomain; + return this; + } + + /** + * Use the local identifier. + * + * @param localIdentifier the local identifier + * @return the builder + */ + public Builder withLocalIdentifier(int localIdentifier) { + this.localIdentifier = localIdentifier; + return this; + } + /** * Finishes the parameters build. * From 1faa06bddd854bf6e0cf8177c6338bee452bb9d0 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 12:21:38 -0300 Subject: [PATCH 05/40] Refactor UuidCreator to use Proxy pattern as lazy initialization --- .../com/github/f4b6a3/uuid/UuidCreator.java | 313 +++++++++--------- 1 file changed, 156 insertions(+), 157 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index 69abebb8..5be98edb 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -26,14 +26,19 @@ import java.security.SecureRandom; import java.time.Instant; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Supplier; import com.github.f4b6a3.uuid.codec.BinaryCodec; import com.github.f4b6a3.uuid.codec.StringCodec; import com.github.f4b6a3.uuid.enums.UuidLocalDomain; import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.exception.InvalidUuidException; +import com.github.f4b6a3.uuid.factory.UuidFactory; +import com.github.f4b6a3.uuid.factory.UuidFactory.Parameters; import com.github.f4b6a3.uuid.factory.nonstandard.PrefixCombFactory; import com.github.f4b6a3.uuid.factory.nonstandard.ShortPrefixCombFactory; import com.github.f4b6a3.uuid.factory.nonstandard.ShortSuffixCombFactory; @@ -189,7 +194,7 @@ public static UUID getMax() { * @see RandomBasedFactory */ public static UUID getRandomBased() { - return RandomBasedHolder.INSTANCE.create(); + return UUID4.create(); } /** @@ -207,7 +212,7 @@ public static UUID getRandomBased() { * @since 5.2.0 */ public static UUID getRandomBasedFast() { - return RandomBasedFastHolder.INSTANCE.create(); + return UUID4_FAST.create(); } /** @@ -223,7 +228,7 @@ public static UUID getRandomBasedFast() { * @see TimeBasedFactory */ public static UUID getTimeBased() { - return TimeBasedHolder.INSTANCE.create(); + return UUID1.create(); } /** @@ -235,7 +240,7 @@ public static UUID getTimeBased() { * @see TimeBasedFactory */ public static UUID getTimeBasedWithMac() { - return TimeBasedWithMacHolder.INSTANCE.create(); + return UUID1_MAC.create(); } /** @@ -250,7 +255,7 @@ public static UUID getTimeBasedWithMac() { * @see MachineId */ public static UUID getTimeBasedWithHash() { - return TimeBasedWithHashHolder.INSTANCE.create(); + return UUID1_HASH.create(); } /** @@ -263,7 +268,7 @@ public static UUID getTimeBasedWithHash() { * @see TimeBasedFactory */ public static UUID getTimeBasedWithRandom() { - return TimeBasedWithRandomHolder.INSTANCE.create(); + return UUID1_RANDOM.create(); } /** @@ -319,9 +324,7 @@ public static UUID getTimeBased(Instant instant, Integer clockseq, Long nodeid) * @return a UUIDv1 */ public static UUID getTimeBasedMin(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); TimeBasedFactory.Builder builder = TimeBasedFactory.builder(); return builder.withInstant(instant).withClockSeq(0x0000L).withNodeId(0x000000000000L).build().create(); } @@ -343,9 +346,7 @@ public static UUID getTimeBasedMin(Instant instant) { * @return a UUIDv1 */ public static UUID getTimeBasedMax(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); TimeBasedFactory.Builder builder = TimeBasedFactory.builder(); return builder.withInstant(instant).withClockSeq(0xffffL).withNodeId(0xffffffffffffL).build().create(); } @@ -366,7 +367,7 @@ public static UUID getTimeBasedMax(Instant instant) { * UUID Formats */ public static UUID getTimeOrdered() { - return TimeOrderedHolder.INSTANCE.create(); + return UUID6.create(); } /** @@ -381,7 +382,7 @@ public static UUID getTimeOrdered() { * UUID Formats */ public static UUID getTimeOrderedWithMac() { - return TimeOrderedWithMacHolder.INSTANCE.create(); + return UUID6_MAC.create(); } /** @@ -399,7 +400,7 @@ public static UUID getTimeOrderedWithMac() { * UUID Formats */ public static UUID getTimeOrderedWithHash() { - return TimeOrderedWithHashHolder.INSTANCE.create(); + return UUID6_HASH.create(); } /** @@ -415,7 +416,7 @@ public static UUID getTimeOrderedWithHash() { * UUID Formats */ public static UUID getTimeOrderedWithRandom() { - return TimeOrderedWithRandomHolder.INSTANCE.create(); + return UUID6_RANDOM.create(); } /** @@ -474,9 +475,7 @@ public static UUID getTimeOrdered(Instant instant, Integer clockseq, Long nodeid * @return a UUIDv6 */ public static UUID getTimeOrderedMin(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); TimeOrderedFactory.Builder builder = TimeOrderedFactory.builder(); return builder.withInstant(instant).withClockSeq(0x0000L).withNodeId(0x000000000000L).build().create(); } @@ -498,13 +497,11 @@ public static UUID getTimeOrderedMin(Instant instant) { * @return a UUIDv6 */ public static UUID getTimeOrderedMax(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); TimeOrderedFactory.Builder builder = TimeOrderedFactory.builder(); return builder.withInstant(instant).withClockSeq(0xffffL).withNodeId(0xffffffffffffL).build().create(); } - + /** * Returns a time-ordered unique identifier that uses Unix Epoch (UUIDv7). *

@@ -522,7 +519,7 @@ public static UUID getTimeOrderedMax(Instant instant) { * UUID Formats */ public static UUID getTimeOrderedEpoch() { - return TimeOrderedEpochHolder.INSTANCE.create(); + return UUID7.create(); } /** @@ -540,7 +537,7 @@ public static UUID getTimeOrderedEpoch() { * UUID Formats */ public static UUID getTimeOrderedEpochPlus1() { - return TimeOrderedEpochPlus1Holder.INSTANCE.create(); + return UUID7_PLUS_1.create(); } /** @@ -559,7 +556,7 @@ public static UUID getTimeOrderedEpochPlus1() { * UUID Formats */ public static UUID getTimeOrderedEpochPlusN() { - return TimeOrderedEpochPlusNHolder.INSTANCE.create(); + return UUID7_PLUS_N.create(); } /** @@ -582,9 +579,7 @@ public static UUID getTimeOrderedEpochPlusN() { * @since 5.3.3 */ public static UUID getTimeOrderedEpoch(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); SecureRandom random = new SecureRandom(); final long msb = (time << 16) | (random.nextLong() & 0x0fffL) | 0x7000L; @@ -609,9 +604,7 @@ public static UUID getTimeOrderedEpoch(Instant instant) { * @return a UUIDv7 */ public static UUID getTimeOrderedEpochMin(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID((time << 16) | 0x7000L, 0x8000000000000000L); } @@ -633,9 +626,7 @@ public static UUID getTimeOrderedEpochMin(Instant instant) { * @return a UUIDv7 */ public static UUID getTimeOrderedEpochMax(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID((time << 16) | 0x7fffL, 0xbfffffffffffffffL); } @@ -650,7 +641,7 @@ public static UUID getTimeOrderedEpochMax(Instant instant) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(String name) { - return NameBasedMd5Holder.INSTANCE.create(name); + return UUID3.create(Parameters.builder().withName(name).build()); } /** @@ -661,7 +652,7 @@ public static UUID getNameBasedMd5(String name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(byte[] name) { - return NameBasedMd5Holder.INSTANCE.create(name); + return UUID3.create(Parameters.builder().withName(name).build()); } /** @@ -676,7 +667,7 @@ public static UUID getNameBasedMd5(byte[] name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(UUID namespace, String name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -689,7 +680,7 @@ public static UUID getNameBasedMd5(UUID namespace, String name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(UUID namespace, byte[] name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -705,7 +696,7 @@ public static UUID getNameBasedMd5(UUID namespace, byte[] name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(String namespace, String name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -719,7 +710,7 @@ public static UUID getNameBasedMd5(String namespace, String name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(String namespace, byte[] name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -742,7 +733,7 @@ public static UUID getNameBasedMd5(String namespace, byte[] name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(UuidNamespace namespace, String name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -763,7 +754,7 @@ public static UUID getNameBasedMd5(UuidNamespace namespace, String name) { * @see NameBasedMd5Factory */ public static UUID getNameBasedMd5(UuidNamespace namespace, byte[] name) { - return NameBasedMd5Holder.INSTANCE.create(namespace, name); + return UUID3.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -776,7 +767,7 @@ public static UUID getNameBasedMd5(UuidNamespace namespace, byte[] name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(String name) { - return NameBasedSha1Holder.INSTANCE.create(name); + return UUID5.create(Parameters.builder().withName(name).build()); } /** @@ -787,7 +778,7 @@ public static UUID getNameBasedSha1(String name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(byte[] name) { - return NameBasedSha1Holder.INSTANCE.create(name); + return UUID5.create(Parameters.builder().withName(name).build()); } /** @@ -802,7 +793,7 @@ public static UUID getNameBasedSha1(byte[] name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(UUID namespace, String name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -815,7 +806,7 @@ public static UUID getNameBasedSha1(UUID namespace, String name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(UUID namespace, byte[] name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -831,7 +822,7 @@ public static UUID getNameBasedSha1(UUID namespace, byte[] name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(String namespace, String name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -845,7 +836,7 @@ public static UUID getNameBasedSha1(String namespace, String name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(String namespace, byte[] name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -868,7 +859,7 @@ public static UUID getNameBasedSha1(String namespace, byte[] name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(UuidNamespace namespace, String name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -889,7 +880,7 @@ public static UUID getNameBasedSha1(UuidNamespace namespace, String name) { * @see NameBasedSha1Factory */ public static UUID getNameBasedSha1(UuidNamespace namespace, byte[] name) { - return NameBasedSha1Holder.INSTANCE.create(namespace, name); + return UUID5.create(Parameters.builder().withNamespace(namespace).withName(name).build()); } /** @@ -902,7 +893,8 @@ public static UUID getNameBasedSha1(UuidNamespace namespace, byte[] name) { * @see DceSecurityFactory */ public static UUID getDceSecurity(byte localDomain, int localIdentifier) { - return DceSecurityHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2 + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -915,7 +907,8 @@ public static UUID getDceSecurity(byte localDomain, int localIdentifier) { * @see DceSecurityFactory */ public static UUID getDceSecurityWithMac(byte localDomain, int localIdentifier) { - return DceSecurityWithMacHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_MAC + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -928,7 +921,8 @@ public static UUID getDceSecurityWithMac(byte localDomain, int localIdentifier) * @see DceSecurityFactory */ public static UUID getDceSecurityWithHash(byte localDomain, int localIdentifier) { - return DceSecurityWithHashHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_HASH + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -941,7 +935,8 @@ public static UUID getDceSecurityWithHash(byte localDomain, int localIdentifier) * @see DceSecurityFactory */ public static UUID getDceSecurityWithRandom(byte localDomain, int localIdentifier) { - return DceSecurityWithRandomHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_RANDOM + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -962,7 +957,8 @@ public static UUID getDceSecurityWithRandom(byte localDomain, int localIdentifie * @see DceSecurityFactory */ public static UUID getDceSecurity(UuidLocalDomain localDomain, int localIdentifier) { - return DceSecurityHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2 + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -983,7 +979,8 @@ public static UUID getDceSecurity(UuidLocalDomain localDomain, int localIdentifi * @see DceSecurityFactory */ public static UUID getDceSecurityWithMac(UuidLocalDomain localDomain, int localIdentifier) { - return DceSecurityWithMacHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_MAC + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -1004,7 +1001,8 @@ public static UUID getDceSecurityWithMac(UuidLocalDomain localDomain, int localI * @see DceSecurityFactory */ public static UUID getDceSecurityWithHash(UuidLocalDomain localDomain, int localIdentifier) { - return DceSecurityWithHashHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_HASH + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -1025,7 +1023,8 @@ public static UUID getDceSecurityWithHash(UuidLocalDomain localDomain, int local * @see DceSecurityFactory */ public static UUID getDceSecurityWithRandom(UuidLocalDomain localDomain, int localIdentifier) { - return DceSecurityWithRandomHolder.INSTANCE.create(localDomain, localIdentifier); + return UUID2_RANDOM + .create(Parameters.builder().withLocalDomain(localDomain).withLocalIdentifier(localIdentifier).build()); } /** @@ -1039,7 +1038,7 @@ public static UUID getDceSecurityWithRandom(UuidLocalDomain localDomain, int loc * of GUIDs as Primary Keys */ public static UUID getPrefixComb() { - return PrefixCombHolder.INSTANCE.create(); + return COMB_PREFIX.create(); } /** @@ -1059,9 +1058,7 @@ public static UUID getPrefixComb() { * @return a GUID */ public static UUID getPrefixCombMin(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID((time << 16) | 0x4000L, 0x8000000000000000L); } @@ -1083,9 +1080,7 @@ public static UUID getPrefixCombMin(Instant instant) { * @return a GUID */ public static UUID getPrefixCombMax(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID((time << 16) | 0x4fffL, 0xbfffffffffffffffL); } @@ -1102,7 +1097,7 @@ public static UUID getPrefixCombMax(Instant instant) { * of GUIDs as Primary Keys */ public static UUID getSuffixComb() { - return SuffixCombHolder.INSTANCE.create(); + return COMB_SUFFIX.create(); } /** @@ -1122,9 +1117,7 @@ public static UUID getSuffixComb() { * @return a GUID */ public static UUID getSuffixCombMin(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID(0x0000000000004000L, 0x8000000000000000L | (time & 0x0000ffffffffffffL)); } @@ -1146,9 +1139,7 @@ public static UUID getSuffixCombMin(Instant instant) { * @return a GUID */ public static UUID getSuffixCombMax(Instant instant) { - if (instant == null) { - throw new IllegalArgumentException("Null instant"); - } + Objects.requireNonNull(instant, "Null instant"); final long time = instant.toEpochMilli(); return new UUID(0xffffffffffff4fffL, 0xbfff000000000000L | (time & 0x0000ffffffffffffL)); } @@ -1167,7 +1158,7 @@ public static UUID getSuffixCombMax(Instant instant) { * UUID Generators */ public static UUID getShortPrefixComb() { - return ShortPrefixCombHolder.INSTANCE.create(); + return COMB_SHORT_PREFIX.create(); } /** @@ -1184,102 +1175,110 @@ public static UUID getShortPrefixComb() { * UUID Generators */ public static UUID getShortSuffixComb() { - return ShortSuffixCombHolder.INSTANCE.create(); + return COMB_SHORT_SUFFIX.create(); } // *************************************** // Lazy holders // *************************************** - private static class RandomBasedHolder { - static final RandomBasedFactory INSTANCE = new RandomBasedFactory(); - } - - private static class RandomBasedFastHolder { - static final RandomBasedFactory INSTANCE = RandomBasedFactory.builder().withFastRandom().build(); - } - - private static class TimeBasedHolder { - static final TimeBasedFactory INSTANCE = new TimeBasedFactory(); - } - - private static class TimeBasedWithMacHolder { - static final TimeBasedFactory INSTANCE = TimeBasedFactory.builder().withMacNodeId().build(); - } - - private static class TimeBasedWithHashHolder { - static final TimeBasedFactory INSTANCE = TimeBasedFactory.builder().withHashNodeId().build(); - } - - private static class TimeBasedWithRandomHolder { - static final TimeBasedFactory INSTANCE = TimeBasedFactory.builder().withRandomNodeId().build(); - } - - private static class TimeOrderedHolder { - static final TimeOrderedFactory INSTANCE = new TimeOrderedFactory(); - } - - private static class TimeOrderedWithMacHolder { - static final TimeOrderedFactory INSTANCE = TimeOrderedFactory.builder().withMacNodeId().build(); - } - - private static class TimeOrderedWithHashHolder { - static final TimeOrderedFactory INSTANCE = TimeOrderedFactory.builder().withHashNodeId().build(); - } - - private static class TimeOrderedWithRandomHolder { - static final TimeOrderedFactory INSTANCE = TimeOrderedFactory.builder().withRandomNodeId().build(); - } - - private static class TimeOrderedEpochHolder { - static final TimeOrderedEpochFactory INSTANCE = new TimeOrderedEpochFactory(); - } - - private static class TimeOrderedEpochPlus1Holder { - static final TimeOrderedEpochFactory INSTANCE = TimeOrderedEpochFactory.builder().withIncrementPlus1().build(); - } - - private static class TimeOrderedEpochPlusNHolder { - static final TimeOrderedEpochFactory INSTANCE = TimeOrderedEpochFactory.builder().withIncrementPlusN().build(); - } - - private static class NameBasedMd5Holder { - static final NameBasedMd5Factory INSTANCE = new NameBasedMd5Factory(); - } - - private static class NameBasedSha1Holder { - static final NameBasedSha1Factory INSTANCE = new NameBasedSha1Factory(); - } + private static final Proxy UUID1 = new Proxy(Suppliers.UUID1); + private static final Proxy UUID1_MAC = new Proxy(Suppliers.UUID1_MAC); + private static final Proxy UUID1_HASH = new Proxy(Suppliers.UUID1_HASH); + private static final Proxy UUID1_RANDOM = new Proxy(Suppliers.UUID1_RANDOM); + private static final Proxy UUID2 = new Proxy(Suppliers.UUID2); + private static final Proxy UUID2_MAC = new Proxy(Suppliers.UUID2_MAC); + private static final Proxy UUID2_HASH = new Proxy(Suppliers.UUID2_HASH); + private static final Proxy UUID2_RANDOM = new Proxy(Suppliers.UUID2_RANDOM); + private static final Proxy UUID3 = new Proxy(Suppliers.UUID3); + private static final Proxy UUID4 = new Proxy(Suppliers.UUID4); + private static final Proxy UUID4_FAST = new Proxy(Suppliers.UUID4_FAST); + private static final Proxy UUID5 = new Proxy(Suppliers.UUID5); + private static final Proxy UUID6 = new Proxy(Suppliers.UUID6); + private static final Proxy UUID6_MAC = new Proxy(Suppliers.UUID6_MAC); + private static final Proxy UUID6_HASH = new Proxy(Suppliers.UUID6_HASH); + private static final Proxy UUID6_RANDOM = new Proxy(Suppliers.UUID6_RANDOM); + private static final Proxy UUID7 = new Proxy(Suppliers.UUID7); + private static final Proxy UUID7_PLUS_1 = new Proxy(Suppliers.UUID7_PLUS_1); + private static final Proxy UUID7_PLUS_N = new Proxy(Suppliers.UUID7_PLUS_N); + private static final Proxy COMB_PREFIX = new Proxy(Suppliers.COMB_PREFIX); + private static final Proxy COMB_SUFFIX = new Proxy(Suppliers.COMB_SUFFIX); + private static final Proxy COMB_SHORT_PREFIX = new Proxy(Suppliers.COMB_SHORT_PREFIX); + private static final Proxy COMB_SHORT_SUFFIX = new Proxy(Suppliers.COMB_SHORT_SUFFIX); + + private static enum Suppliers { + + UUID1(TimeBasedFactory::new), // + UUID1_MAC(() -> TimeBasedFactory.builder().withMacNodeId().build()), // + UUID1_HASH(() -> TimeBasedFactory.builder().withHashNodeId().build()), // + UUID1_RANDOM(() -> TimeBasedFactory.builder().withRandomNodeId().build()), // + UUID2(DceSecurityFactory::new), // + UUID2_MAC(() -> DceSecurityFactory.builder().withMacNodeId().build()), // + UUID2_HASH(() -> DceSecurityFactory.builder().withHashNodeId().build()), // + UUID2_RANDOM(() -> DceSecurityFactory.builder().withRandomNodeId().build()), // + UUID3(NameBasedMd5Factory::new), // + UUID4(RandomBasedFactory::new), // + UUID4_FAST(() -> RandomBasedFactory.builder().withFastRandom().build()), // + UUID5(NameBasedSha1Factory::new), // + UUID6(TimeOrderedFactory::new), // + UUID6_MAC(() -> TimeOrderedFactory.builder().withMacNodeId().build()), // + UUID6_HASH(() -> TimeOrderedFactory.builder().withHashNodeId().build()), // + UUID6_RANDOM(() -> TimeOrderedFactory.builder().withRandomNodeId().build()), // + UUID7(TimeOrderedEpochFactory::new), // + UUID7_PLUS_1(() -> TimeOrderedEpochFactory.builder().withIncrementPlus1().build()), // + UUID7_PLUS_N(() -> TimeOrderedEpochFactory.builder().withIncrementPlusN().build()), // + COMB_PREFIX(PrefixCombFactory::new), // + COMB_SUFFIX(SuffixCombFactory::new), // + COMB_SHORT_PREFIX(ShortPrefixCombFactory::new), // + COMB_SHORT_SUFFIX(ShortSuffixCombFactory::new), // + ; + + private final Supplier supplier; + + Suppliers(Supplier supplier) { + this.supplier = supplier; + } - private static class DceSecurityHolder { - static final DceSecurityFactory INSTANCE = new DceSecurityFactory(); + public Supplier getValue() { + return this.supplier; + } } - private static class DceSecurityWithMacHolder { - static final DceSecurityFactory INSTANCE = DceSecurityFactory.builder().withMacNodeId().build(); - } + private static class Proxy extends UuidFactory { - private static class DceSecurityWithHashHolder { - static final DceSecurityFactory INSTANCE = DceSecurityFactory.builder().withHashNodeId().build(); - } + private UuidFactory factory = null; + private Supplier supplier; + private static final ReentrantLock lock = new ReentrantLock(); - private static class DceSecurityWithRandomHolder { - static final DceSecurityFactory INSTANCE = DceSecurityFactory.builder().withRandomNodeId().build(); - } - - private static class SuffixCombHolder { - static final SuffixCombFactory INSTANCE = new SuffixCombFactory(); - } + public Proxy(Suppliers supplier) { + this.supplier = (Supplier) supplier.getValue(); + } - private static class PrefixCombHolder { - static final PrefixCombFactory INSTANCE = new PrefixCombFactory(); - } + private UuidFactory get() { + + if (factory != null) { + return factory; + } + + lock.lock(); + try { + if (factory == null) { + this.factory = supplier.get(); + } + return this.factory; + } finally { + lock.unlock(); + } + } - private static class ShortPrefixCombHolder { - static final ShortPrefixCombFactory INSTANCE = new ShortPrefixCombFactory(); - } + @Override + public UUID create() { + return get().create(); + } - private static class ShortSuffixCombHolder { - static final ShortSuffixCombFactory INSTANCE = new ShortSuffixCombFactory(); + @Override + public UUID create(Parameters parameters) { + return get().create(parameters); + } } } From 53378dc893ff305ecdafb86d188f69777e081dcc Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 12:28:31 -0300 Subject: [PATCH 06/40] Add fast version of UUID v7 #100 Add a fast (i.e. non-cryptographic) version of UUID v7. --- .../com/github/f4b6a3/uuid/UuidCreator.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index 5be98edb..bdd382ff 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -501,7 +501,7 @@ public static UUID getTimeOrderedMax(Instant instant) { TimeOrderedFactory.Builder builder = TimeOrderedFactory.builder(); return builder.withInstant(instant).withClockSeq(0xffffL).withNodeId(0xffffffffffffL).build().create(); } - + /** * Returns a time-ordered unique identifier that uses Unix Epoch (UUIDv7). *

@@ -522,6 +522,32 @@ public static UUID getTimeOrderedEpoch() { return UUID7.create(); } + /** + * Returns a fast time-ordered unique identifier that uses Unix Epoch (UUIDv7). + *

+ * This method produces identifiers with 3 parts: time, counter and random. + *

+ * The counter bits are incremented by 1 when the time repeats. + *

+ * The random bits are generated with each method invocation. + * + * It employs {@link ThreadLocalRandom} which works very well, although not + * cryptographically strong. It can be useful, for example, for logging. + *

+ * Security-sensitive applications that require a cryptographically secure + * pseudo-random generator should use {@link UuidCreator#getTimeOrderedEpoch()}. + * + * @return a UUIDv7 + * @since 6.0.0 + * @see TimeOrderedEpochFactory + * @see New + * UUID Formats + */ + public static UUID getTimeOrderedEpochFast() { + return UUID7_FAST.create(); + } + /** * Returns a time-ordered unique identifier that uses Unix Epoch (UUIDv7). *

@@ -1199,6 +1225,7 @@ public static UUID getShortSuffixComb() { private static final Proxy UUID6_HASH = new Proxy(Suppliers.UUID6_HASH); private static final Proxy UUID6_RANDOM = new Proxy(Suppliers.UUID6_RANDOM); private static final Proxy UUID7 = new Proxy(Suppliers.UUID7); + private static final Proxy UUID7_FAST = new Proxy(Suppliers.UUID7_FAST); private static final Proxy UUID7_PLUS_1 = new Proxy(Suppliers.UUID7_PLUS_1); private static final Proxy UUID7_PLUS_N = new Proxy(Suppliers.UUID7_PLUS_N); private static final Proxy COMB_PREFIX = new Proxy(Suppliers.COMB_PREFIX); @@ -1225,6 +1252,7 @@ private static enum Suppliers { UUID6_HASH(() -> TimeOrderedFactory.builder().withHashNodeId().build()), // UUID6_RANDOM(() -> TimeOrderedFactory.builder().withRandomNodeId().build()), // UUID7(TimeOrderedEpochFactory::new), // + UUID7_FAST(() -> TimeOrderedEpochFactory.builder().withFastRandom().build()), // UUID7_PLUS_1(() -> TimeOrderedEpochFactory.builder().withIncrementPlus1().build()), // UUID7_PLUS_N(() -> TimeOrderedEpochFactory.builder().withIncrementPlusN().build()), // COMB_PREFIX(PrefixCombFactory::new), // From 48050603eae715961ccdabdecf28500877ec27cb Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 12:38:47 -0300 Subject: [PATCH 07/40] Add create method with parameters object in DCE Security factory --- .../f4b6a3/uuid/factory/AbstTimeBasedFactory.java | 5 +++++ .../uuid/factory/rfc4122/DceSecurityFactory.java | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java index 7800d663..e767d3fd 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java @@ -169,6 +169,11 @@ public UUID create() { } } + /** + * Returns a time-based UUID. + * + * @return a time-based UUID + */ @Override public UUID create(Parameters parameters) { return create(); // ignore arguments diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java index 14863c63..5c896611 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java @@ -177,6 +177,16 @@ public UUID create() { throw new UnsupportedOperationException("Unsuported operation for DCE Security UUID factory"); } + /** + * Returns a DCE Security unique identifier (UUIDv2). + * + * @return a UUIDv2 + */ + @Override + public UUID create(Parameters parameters) { + return create(parameters.getLocalDomain(), parameters.getLocalIdentifier()); + } + /** * Embeds the local identifier in into the most significant bits. * From ecee68fbffbb4fedbe7c440923c19a7ef9b661d6 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 25 Feb 2024 13:11:08 -0300 Subject: [PATCH 08/40] fix doc --- .../com/github/f4b6a3/uuid/UuidCreator.java | 66 +++++++++---------- .../f4b6a3/uuid/factory/UuidFactory.java | 6 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index bdd382ff..dea1e592 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -95,6 +95,38 @@ public final class UuidCreator { private UuidCreator() { } + /** + * Returns a Nil UUID. + *

+ * Nil UUID is a special UUID that has all 128 bits set to ZERO. + *

+ * The canonical string of Nil UUID is + * 00000000-0000-0000-0000-000000000000. + * + * @return a Nil UUID + */ + public static UUID getNil() { + return UUID_NIL; + } + + /** + * Returns a Max UUID. + *

+ * Max UUID is a special UUID that has all 128 bits set to ONE. + *

+ * The canonical string of Max UUID is + * FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF. + * + * @return a Max UUID + * @since 5.0.0 + * @see New + * UUID Formats + */ + public static UUID getMax() { + return UUID_MAX; + } + /** * Returns an array of bytes from a UUID. * @@ -155,38 +187,6 @@ public static UUID fromString(String uuid) { return StringCodec.INSTANCE.decode(uuid); } - /** - * Returns a Nil UUID. - *

- * Nil UUID is a special UUID that has all 128 bits set to ZERO. - *

- * The canonical string of Nil UUID is - * 00000000-0000-0000-0000-000000000000. - * - * @return a Nil UUID - */ - public static UUID getNil() { - return UUID_NIL; - } - - /** - * Returns a Max UUID. - *

- * Max UUID is a special UUID that has all 128 bits set to ONE. - *

- * The canonical string of Max UUID is - * FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF. - * - * @return a Max UUID - * @since 5.0.0 - * @see New - * UUID Formats - */ - public static UUID getMax() { - return UUID_MAX; - } - /** * Returns a random-based unique identifier (UUIDv4). * @@ -530,7 +530,7 @@ public static UUID getTimeOrderedEpoch() { * The counter bits are incremented by 1 when the time repeats. *

* The random bits are generated with each method invocation. - * + *

* It employs {@link ThreadLocalRandom} which works very well, although not * cryptographically strong. It can be useful, for example, for logging. *

diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java index 10a056ec..b405b117 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java @@ -53,7 +53,7 @@ public abstract class UuidFactory { /** * Default Constructor. - * + *

* The version used is {@link UuidVersion#VERSION_UNKNOWN}. */ public UuidFactory() { @@ -134,7 +134,7 @@ public Parameters(Builder builder) { } /** - * Get the name space bytes + * Get the name space bytes. * * @return a byte array */ @@ -143,7 +143,7 @@ public byte[] getNamespace() { } /** - * Get the name bytes + * Get the name bytes. * * @return a byte array */ From 0bdb3371bb70f406f9821cce46e5f436c9b6c152 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 15:57:52 -0300 Subject: [PATCH 09/40] Move Parser to GUID GUID must be independent of the rest of the library. Additionally, Parser code is only used by GUID. Although some consider nested classes to be a smell, this is not true in all cases. If you think that's the case, I hope you can forgive this one. --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 117 +++++++++++++++++ .../com/github/f4b6a3/uuid/alt/Parser.java | 121 ------------------ .../com/github/f4b6a3/uuid/alt/GUIDTest.java | 6 +- 3 files changed, 120 insertions(+), 124 deletions(-) delete mode 100644 src/main/java/com/github/f4b6a3/uuid/alt/Parser.java diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index c765704a..7d5bd10d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -520,4 +520,121 @@ long getMostSignificantBits() { long getLeastSignificantBits() { return this.lsb; } + + static final class Parser { + + private static final byte[] VALUES = new byte[256]; + static { + Arrays.fill(VALUES, (byte) -1); + VALUES['0'] = 0; + VALUES['1'] = 1; + VALUES['2'] = 2; + VALUES['3'] = 3; + VALUES['4'] = 4; + VALUES['5'] = 5; + VALUES['6'] = 6; + VALUES['7'] = 7; + VALUES['8'] = 8; + VALUES['9'] = 9; + VALUES['A'] = 10; + VALUES['B'] = 11; + VALUES['C'] = 12; + VALUES['D'] = 13; + VALUES['E'] = 14; + VALUES['F'] = 15; + VALUES['a'] = 10; + VALUES['b'] = 11; + VALUES['c'] = 12; + VALUES['d'] = 13; + VALUES['e'] = 14; + VALUES['f'] = 15; + } + + public static GUID parse(final String string) { + + if (!valid(string)) { + throw new IllegalArgumentException("Invalid GUID string: " + string); + } + + long msb = 0; + long lsb = 0; + + // UUID string WITH hyphen + msb |= (long) VALUES[string.charAt(0x00)] << 60; + msb |= (long) VALUES[string.charAt(0x01)] << 56; + msb |= (long) VALUES[string.charAt(0x02)] << 52; + msb |= (long) VALUES[string.charAt(0x03)] << 48; + msb |= (long) VALUES[string.charAt(0x04)] << 44; + msb |= (long) VALUES[string.charAt(0x05)] << 40; + msb |= (long) VALUES[string.charAt(0x06)] << 36; + msb |= (long) VALUES[string.charAt(0x07)] << 32; + // input[8] = '-' + msb |= (long) VALUES[string.charAt(0x09)] << 28; + msb |= (long) VALUES[string.charAt(0x0a)] << 24; + msb |= (long) VALUES[string.charAt(0x0b)] << 20; + msb |= (long) VALUES[string.charAt(0x0c)] << 16; + // input[13] = '-' + msb |= (long) VALUES[string.charAt(0x0e)] << 12; + msb |= (long) VALUES[string.charAt(0x0f)] << 8; + msb |= (long) VALUES[string.charAt(0x10)] << 4; + msb |= (long) VALUES[string.charAt(0x11)]; + // input[18] = '-' + lsb |= (long) VALUES[string.charAt(0x13)] << 60; + lsb |= (long) VALUES[string.charAt(0x14)] << 56; + lsb |= (long) VALUES[string.charAt(0x15)] << 52; + lsb |= (long) VALUES[string.charAt(0x16)] << 48; + // input[23] = '-' + lsb |= (long) VALUES[string.charAt(0x18)] << 44; + lsb |= (long) VALUES[string.charAt(0x19)] << 40; + lsb |= (long) VALUES[string.charAt(0x1a)] << 36; + lsb |= (long) VALUES[string.charAt(0x1b)] << 32; + lsb |= (long) VALUES[string.charAt(0x1c)] << 28; + lsb |= (long) VALUES[string.charAt(0x1d)] << 24; + lsb |= (long) VALUES[string.charAt(0x1e)] << 20; + lsb |= (long) VALUES[string.charAt(0x1f)] << 16; + lsb |= (long) VALUES[string.charAt(0x20)] << 12; + lsb |= (long) VALUES[string.charAt(0x21)] << 8; + lsb |= (long) VALUES[string.charAt(0x22)] << 4; + lsb |= (long) VALUES[string.charAt(0x23)]; + + return new GUID(msb, lsb); + } + + private static final int[] DASH_POSITIONS = { 8, 13, 18, 23 }; + private static final int DASH_REQUIRED_COUNT = 4; + + private static boolean isCharValid(char chr) { + return chr >= 0 && chr < VALUES.length && VALUES[chr] >= 0; + } + + private static boolean isDashPosition(int index) { + for (int dashPosition : DASH_POSITIONS) { + if (index == dashPosition) { + return true; + } + } + return false; + } + + public static boolean valid(final String guid) { + if (guid == null || guid.length() != GUID_CHARS) { + return false; // null or wrong length + } + + int dashesCount = 0; + for (int i = 0; i < GUID_CHARS; i++) { + char chr = guid.charAt(i); + if (isCharValid(chr)) { + continue; // character is valid + } + if (isDashPosition(i) && chr == '-') { + dashesCount++; + continue; + } + return false; // invalid character + } + + return dashesCount == DASH_REQUIRED_COUNT; + } + } } diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/Parser.java b/src/main/java/com/github/f4b6a3/uuid/alt/Parser.java deleted file mode 100644 index ac76d6e8..00000000 --- a/src/main/java/com/github/f4b6a3/uuid/alt/Parser.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.github.f4b6a3.uuid.alt; - -import java.util.Arrays; - -import static com.github.f4b6a3.uuid.alt.GUID.GUID_CHARS; - -public final class Parser { - - private static final byte[] VALUES = new byte[256]; - static { - Arrays.fill(VALUES, (byte) -1); - VALUES['0'] = 0; - VALUES['1'] = 1; - VALUES['2'] = 2; - VALUES['3'] = 3; - VALUES['4'] = 4; - VALUES['5'] = 5; - VALUES['6'] = 6; - VALUES['7'] = 7; - VALUES['8'] = 8; - VALUES['9'] = 9; - VALUES['A'] = 10; - VALUES['B'] = 11; - VALUES['C'] = 12; - VALUES['D'] = 13; - VALUES['E'] = 14; - VALUES['F'] = 15; - VALUES['a'] = 10; - VALUES['b'] = 11; - VALUES['c'] = 12; - VALUES['d'] = 13; - VALUES['e'] = 14; - VALUES['f'] = 15; - } - - public static GUID parse(final String string) { - - if (!valid(string)) { - throw new IllegalArgumentException("Invalid GUID string: " + string); - } - - long msb = 0; - long lsb = 0; - - // UUID string WITH hyphen - msb |= (long) VALUES[string.charAt(0x00)] << 60; - msb |= (long) VALUES[string.charAt(0x01)] << 56; - msb |= (long) VALUES[string.charAt(0x02)] << 52; - msb |= (long) VALUES[string.charAt(0x03)] << 48; - msb |= (long) VALUES[string.charAt(0x04)] << 44; - msb |= (long) VALUES[string.charAt(0x05)] << 40; - msb |= (long) VALUES[string.charAt(0x06)] << 36; - msb |= (long) VALUES[string.charAt(0x07)] << 32; - // input[8] = '-' - msb |= (long) VALUES[string.charAt(0x09)] << 28; - msb |= (long) VALUES[string.charAt(0x0a)] << 24; - msb |= (long) VALUES[string.charAt(0x0b)] << 20; - msb |= (long) VALUES[string.charAt(0x0c)] << 16; - // input[13] = '-' - msb |= (long) VALUES[string.charAt(0x0e)] << 12; - msb |= (long) VALUES[string.charAt(0x0f)] << 8; - msb |= (long) VALUES[string.charAt(0x10)] << 4; - msb |= (long) VALUES[string.charAt(0x11)]; - // input[18] = '-' - lsb |= (long) VALUES[string.charAt(0x13)] << 60; - lsb |= (long) VALUES[string.charAt(0x14)] << 56; - lsb |= (long) VALUES[string.charAt(0x15)] << 52; - lsb |= (long) VALUES[string.charAt(0x16)] << 48; - // input[23] = '-' - lsb |= (long) VALUES[string.charAt(0x18)] << 44; - lsb |= (long) VALUES[string.charAt(0x19)] << 40; - lsb |= (long) VALUES[string.charAt(0x1a)] << 36; - lsb |= (long) VALUES[string.charAt(0x1b)] << 32; - lsb |= (long) VALUES[string.charAt(0x1c)] << 28; - lsb |= (long) VALUES[string.charAt(0x1d)] << 24; - lsb |= (long) VALUES[string.charAt(0x1e)] << 20; - lsb |= (long) VALUES[string.charAt(0x1f)] << 16; - lsb |= (long) VALUES[string.charAt(0x20)] << 12; - lsb |= (long) VALUES[string.charAt(0x21)] << 8; - lsb |= (long) VALUES[string.charAt(0x22)] << 4; - lsb |= (long) VALUES[string.charAt(0x23)]; - - return new GUID(msb, lsb); - } - - private static final int[] DASH_POSITIONS = {8, 13, 18, 23}; - private static final int DASH_REQUIRED_COUNT = 4; - - private static boolean isCharValid(char chr) { - return chr >= 0 && chr < VALUES.length && VALUES[chr] >= 0; - } - private static boolean isDashPosition(int index) { - for (int dashPosition : DASH_POSITIONS) { - if (index == dashPosition) { - return true; - } - } - return false; - } - - public static boolean valid(final String guid) { - if (guid == null || guid.length() != GUID_CHARS) { - return false; // null or wrong length - } - - int dashesCount = 0; - for (int i = 0; i < GUID_CHARS; i++) { - char chr = guid.charAt(i); - if (isCharValid(chr)) { - continue; // character is valid - } - if (isDashPosition(i) && chr == '-') { - dashesCount++; - continue; - } - return false; // invalid character - } - - return dashesCount == DASH_REQUIRED_COUNT; - } -} \ No newline at end of file diff --git a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java index 9e94b43e..0d855fd7 100644 --- a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java @@ -422,13 +422,13 @@ public void testParser() { // canonical format with 36 characters for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { String string = UUID.randomUUID().toString(); - GUID guid = Parser.parse(string); + GUID guid = GUID.Parser.parse(string); assertEquals(string, guid.toString()); } testValidator((String string) -> { try { - return Parser.parse(string) != null; + return GUID.Parser.parse(string) != null; } catch (IllegalArgumentException e) { return false; } @@ -437,7 +437,7 @@ public void testParser() { // compare with regular expression testValidator((String string) -> { boolean expected = (string != null && PATTERN.matcher(string).matches()); - boolean result = Parser.valid(string); + boolean result = GUID.Parser.valid(string); assertEquals(expected, result); return expected && result; }); From 7524c6df1c17df8d6486554e61b8683aa9180099 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 16:12:34 -0300 Subject: [PATCH 10/40] chore --- src/main/java/com/github/f4b6a3/uuid/UuidCreator.java | 2 +- src/main/java/com/github/f4b6a3/uuid/alt/GUID.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/UuidCodec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base16Codec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base32Codec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base58BtcCodec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base62Codec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base64Codec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/base/Base64UrlCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base16Decoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base16Encoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base32Decoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base32Encoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base64Decoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/Base64Encoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java | 2 +- .../github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java | 2 +- .../f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java | 2 +- .../f4b6a3/uuid/codec/base/function/BaseNRemainderEncoder.java | 2 +- .../com/github/f4b6a3/uuid/codec/other/DotNetGuid1Codec.java | 2 +- .../com/github/f4b6a3/uuid/codec/other/DotNetGuid4Codec.java | 2 +- .../java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/codec/other/SlugCodec.java | 2 +- .../com/github/f4b6a3/uuid/codec/other/TimeOrderedCodec.java | 2 +- src/main/java/com/github/f4b6a3/uuid/enums/UuidLocalDomain.java | 2 +- src/main/java/com/github/f4b6a3/uuid/enums/UuidNamespace.java | 2 +- src/main/java/com/github/f4b6a3/uuid/enums/UuidVariant.java | 2 +- src/main/java/com/github/f4b6a3/uuid/enums/UuidVersion.java | 2 +- .../com/github/f4b6a3/uuid/exception/InvalidUuidException.java | 2 +- .../java/com/github/f4b6a3/uuid/factory/AbstCombFactory.java | 2 +- .../com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java | 2 +- .../com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java | 2 +- .../com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java | 2 +- src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java | 2 +- .../github/f4b6a3/uuid/factory/function/ClockSeqFunction.java | 2 +- .../com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java | 2 +- .../com/github/f4b6a3/uuid/factory/function/RandomFunction.java | 2 +- .../com/github/f4b6a3/uuid/factory/function/TimeFunction.java | 2 +- .../uuid/factory/function/impl/DefaultClockSeqFunction.java | 2 +- .../uuid/factory/function/impl/DefaultNodeIdFunction.java | 2 +- .../uuid/factory/function/impl/DefaultRandomFunction.java | 2 +- .../f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java | 2 +- .../f4b6a3/uuid/factory/function/impl/HashNodeIdFunction.java | 2 +- .../f4b6a3/uuid/factory/function/impl/MacNodeIdFunction.java | 2 +- .../f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java | 2 +- .../f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java | 2 +- .../f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java | 2 +- .../f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java | 2 +- .../f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java | 2 +- .../f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java | 2 +- .../github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java | 2 +- .../github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java | 2 +- .../f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java | 2 +- .../github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java | 2 +- .../github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactory.java | 2 +- .../f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java | 2 +- .../github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactory.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/CombUtil.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/MachineId.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/UuidComparator.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/UuidTime.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/UuidUtil.java | 2 +- src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java | 2 +- .../java/com/github/f4b6a3/uuid/util/immutable/CharArray.java | 2 +- .../java/com/github/f4b6a3/uuid/util/immutable/LongArray.java | 2 +- .../java/com/github/f4b6a3/uuid/util/internal/ByteUtil.java | 2 +- .../com/github/f4b6a3/uuid/util/internal/JavaVersionUtil.java | 2 +- .../java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java | 2 +- .../java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java | 2 +- .../java/com/github/f4b6a3/uuid/util/internal/SettingsUtil.java | 2 +- 76 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index dea1e592..2e158864 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2023 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 7d5bd10d..2f04ab50 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2023 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java index 86c010ff..1614804d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java index 401e2f2a..abd13e05 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java index d5ec135a..0fa4e37f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java index 568ddf83..49a1b0bf 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/UuidCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/UuidCodec.java index 6dcfdadf..892c6544 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/UuidCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/UuidCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base16Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base16Codec.java index 709b40f6..f29baeb3 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base16Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base16Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base32Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base32Codec.java index 94c207a9..5040d8a3 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base32Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base32Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base58BtcCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base58BtcCodec.java index 6439195c..f11243e4 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base58BtcCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base58BtcCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base62Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base62Codec.java index 145d7c68..8826ef6e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base62Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base62Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64Codec.java index 8203999f..bb05b737 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64UrlCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64UrlCodec.java index 04e73d0b..f0decb1c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64UrlCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/Base64UrlCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java index 7d3e0dd0..7c7cc282 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java index b15aa3b0..99047362 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java index 92f41e8f..ab89b6ac 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java index ee939398..6da687ea 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java index 9d5eb512..682d5e24 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java index 3993da8a..abe50289 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java index 5c8cd04f..a8932192 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java index e95cc89b..0c145968 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java index ae7f82b1..7dfdfc8a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java index 36f53772..3768d0ab 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java index 3f9cfa7a..0cae81f7 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoder.java index 24370269..bdefdca3 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid1Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid1Codec.java index 153000e2..29f05c9a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid1Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid1Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid4Codec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid4Codec.java index 6c759e5f..91e6e005 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid4Codec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/DotNetGuid4Codec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java index de3f9341..34f48ae6 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/SlugCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/SlugCodec.java index 629b74b1..b9c9646b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/SlugCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/SlugCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/TimeOrderedCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/TimeOrderedCodec.java index d775b516..7694215f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/TimeOrderedCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/TimeOrderedCodec.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/enums/UuidLocalDomain.java b/src/main/java/com/github/f4b6a3/uuid/enums/UuidLocalDomain.java index 8e96f956..7cb22572 100644 --- a/src/main/java/com/github/f4b6a3/uuid/enums/UuidLocalDomain.java +++ b/src/main/java/com/github/f4b6a3/uuid/enums/UuidLocalDomain.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/enums/UuidNamespace.java b/src/main/java/com/github/f4b6a3/uuid/enums/UuidNamespace.java index 218d280d..20458048 100644 --- a/src/main/java/com/github/f4b6a3/uuid/enums/UuidNamespace.java +++ b/src/main/java/com/github/f4b6a3/uuid/enums/UuidNamespace.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/enums/UuidVariant.java b/src/main/java/com/github/f4b6a3/uuid/enums/UuidVariant.java index e29c56f5..cf40ed88 100644 --- a/src/main/java/com/github/f4b6a3/uuid/enums/UuidVariant.java +++ b/src/main/java/com/github/f4b6a3/uuid/enums/UuidVariant.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/enums/UuidVersion.java b/src/main/java/com/github/f4b6a3/uuid/enums/UuidVersion.java index 39c20b35..e3bc7d3a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/enums/UuidVersion.java +++ b/src/main/java/com/github/f4b6a3/uuid/enums/UuidVersion.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/exception/InvalidUuidException.java b/src/main/java/com/github/f4b6a3/uuid/exception/InvalidUuidException.java index 0058e909..896cb130 100644 --- a/src/main/java/com/github/f4b6a3/uuid/exception/InvalidUuidException.java +++ b/src/main/java/com/github/f4b6a3/uuid/exception/InvalidUuidException.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstCombFactory.java index a699b070..0ced282e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstCombFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java index eab2cda2..3340809f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstNameBasedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java index cf7435c9..2ad2005e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java index e767d3fd..717e1a4a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java index b405b117..dcf7a09c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java index 61887a12..ead195bc 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java index f7259fbe..33f5fc4c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/RandomFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/RandomFunction.java index 698163d8..60b93201 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/RandomFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/RandomFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/TimeFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/TimeFunction.java index 5f615c3c..412b3aa1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/TimeFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/TimeFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java index ace58742..f43a39d6 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultNodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultNodeIdFunction.java index e988e22d..456bffed 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultNodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultNodeIdFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java index 51ea6bea..ab78460e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java index f3ffdcdd..706ad242 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/HashNodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/HashNodeIdFunction.java index 33c7fa5f..58180acf 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/HashNodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/HashNodeIdFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/MacNodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/MacNodeIdFunction.java index 986f2645..5a9d7878 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/MacNodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/MacNodeIdFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java index ba13ec53..d1fca8e1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java index 8a6b6395..d138b48d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java index 1317e4d3..14ccad10 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java index f59f0e2f..da20a835 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java index 13e763cc..fb9fd98d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java index f3d9cbc9..b6fd2a48 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java index 5c896611..b24ec651 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/DceSecurityFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java index 8036942a..0314ee2d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedMd5Factory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java index 22f8aef8..687ad77f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/NameBasedSha1Factory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java index aceda3b3..d0a0846c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactory.java index 45b502ce..8a3ac9b0 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java index 8752f0eb..5387a064 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactory.java index 12994ae9..4b583e7d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactory.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/CombUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/CombUtil.java index 09cf4c0d..ab2d127e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/CombUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/CombUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java index cabb1e2b..2613fd0e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidComparator.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidComparator.java index 410fb98a..6707d20a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/UuidComparator.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidComparator.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidTime.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidTime.java index 94d29b2d..de4dca60 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/UuidTime.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidTime.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidUtil.java index 1cb71a4b..5455c139 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/UuidUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java index 470bba14..1dc7e4d1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/immutable/CharArray.java b/src/main/java/com/github/f4b6a3/uuid/util/immutable/CharArray.java index 9c583b38..8dcdbd2b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/immutable/CharArray.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/immutable/CharArray.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java b/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java index a1e30c74..f6c03134 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/ByteUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/ByteUtil.java index 0f706f2e..0249b478 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/ByteUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/ByteUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/JavaVersionUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/JavaVersionUtil.java index 41985b06..3e08bb0e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/JavaVersionUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/JavaVersionUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java index 01ce8684..024db8e1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java index e610952b..362f5bb1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/SettingsUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/SettingsUtil.java index 3c0b3d42..f55af67f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/SettingsUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/SettingsUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2018-2022 Fabio Lima + * Copyright (c) 2018-2024 Fabio Lima * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 09cfdc4acdbac3d10acbfc0a696ce5c4ba342b41 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 16:50:27 -0300 Subject: [PATCH 11/40] chore --- pom.xml | 12 ------------ src/main/java/com/github/f4b6a3/uuid/alt/GUID.java | 2 +- .../f4b6a3/uuid/util/internal/NetworkUtil.java | 14 +++++--------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index b352432a..94979418 100644 --- a/pom.xml +++ b/pom.xml @@ -44,18 +44,6 @@ 3.4.0 test - - org.junit.jupiter - junit-jupiter - 5.8.1 - test - - - org.junit.jupiter - junit-jupiter-api - 5.10.2 - test - diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 2f04ab50..7841d9f1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -627,7 +627,7 @@ public static boolean valid(final String guid) { if (isCharValid(chr)) { continue; // character is valid } - if (isDashPosition(i) && chr == '-') { + if (chr == '-' && isDashPosition(i)) { dashesCount++; continue; } diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java index 024db8e1..855d377c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/NetworkUtil.java @@ -188,28 +188,24 @@ public static synchronized String getMachineString() { */ public static synchronized NetworkInterface nic() { - NetworkInterface nic; - try { InetAddress ip = null; - NetworkInterface ni = null; + NetworkInterface nic = null; Enumeration enu = null; // try to find the network interface for the host name ip = InetAddress.getByName(hostname()); - ni = NetworkInterface.getByInetAddress(ip); - if (acceptable(ni)) { - nic = ni; + nic = NetworkInterface.getByInetAddress(ip); + if (acceptable(nic)) { return nic; } // try to find the first network interface enu = NetworkInterface.getNetworkInterfaces(); while (enu.hasMoreElements()) { - ni = enu.nextElement(); - if (acceptable(ni)) { - nic = ni; + nic = enu.nextElement(); + if (acceptable(nic)) { return nic; } } From af95b5e37342ed9a891514939baedd461e37c8e0 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 19:58:35 -0300 Subject: [PATCH 12/40] Add UuidBuilder --- .../github/f4b6a3/uuid/util/UuidBuilder.java | 178 +++++++++++++++ .../com/github/f4b6a3/uuid/TestSuite.java | 4 + .../f4b6a3/uuid/util/UuidBuilderTest.java | 209 ++++++++++++++++++ 3 files changed, 391 insertions(+) create mode 100644 src/main/java/com/github/f4b6a3/uuid/util/UuidBuilder.java create mode 100644 src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidBuilder.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidBuilder.java new file mode 100644 index 00000000..0e6b343c --- /dev/null +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidBuilder.java @@ -0,0 +1,178 @@ +/* + * MIT License + * + * Copyright (c) 2018-2024 Fabio Lima + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.github.f4b6a3.uuid.util; + +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * A UUID builder. + *

+ * Usage: + * + *

{@code
+ * SecureRandom random = new SecureRandom();
+ * UUID uuid = new UuidBuilder(4) // sets version 4 (random-based)
+ * 		.put(random.nextLong()) // put the most significant 64 bits
+ * 		.put(random.nextLong()) // put the least significant 64 bits
+ * 		.build(); // return the built UUID
+ * }
+ */ +public class UuidBuilder { + + private Integer version; + + // newly-created byte buffers are always BIG_ENDIAN + private ByteBuffer buffer = ByteBuffer.allocate(16); + + /** + * Instantiates a new builder without a version number. + * + */ + public UuidBuilder() { + this.version = null; + } + + /** + * Instantiates a new builder with a version number. + * + * @param version a value between 0 and 15 + */ + public UuidBuilder(int version) { + if (version < 0x00L || version > 0xfL) { + throw new IllegalArgumentException("Invalid version number"); + } + this.version = version; + } + + /** + * Puts 8 bytes containing the given long. + * + * @param value a long value + * + * @return This buffer + * + * @throws BufferOverflowException If there are fewer than 8 bytes remaining + */ + public synchronized UuidBuilder put(long value) { + buffer.putLong(value); + return this; + } + + /** + * Puts 4 bytes containing the given int. + * + * @param value an int value + * + * @return This buffer + * + * @throws BufferOverflowException If there are fewer than 4 bytes remaining + */ + public synchronized UuidBuilder put(int value) { + buffer.putInt(value); + return this; + } + + /** + * Puts 2 bytes containing the given short. + * + * @param value a short value + * + * @return This buffer + * + * @throws BufferOverflowException If there are fewer than 2 bytes remaining + */ + public synchronized UuidBuilder put(short value) { + buffer.putShort(value); + return this; + } + + /** + * Puts the given byte. + * + * @param value a byte value + * + * @return This buffer + * + * @throws BufferOverflowException If there are fewer than 1 bytes remaining + */ + public synchronized UuidBuilder put(byte value) { + buffer.put(value); + return this; + } + + /** + * Puts the given byte array. + * + * @param value a byte array + * + * @return This buffer + * + * @throws BufferOverflowException If there are fewer bytes remaining than the + * array length + */ + public synchronized UuidBuilder put(byte[] array) { + buffer.put(array); + return this; + } + + /** + * Builds a UUID after all 16 bytes are filled. + *

+ * This method ends the use of a builder. + *

+ * Successive calls will always return the same UUID value. + *

+ * Note: this method overrides bits 48 through 51 (version field) and bits 52 + * through 63 (variant field), 6 bits total, to comply the UUID specification. + * + * @throws BufferUnderflowException If there are bytes remaining to be filled + */ + public synchronized UUID build() { + + validate(); + buffer.rewind(); + + if (this.version != null) { + // set the 4 most significant bits of the 7th byte (version field) + final long msb = (buffer.getLong() & 0xffff_ffff_ffff_0fffL) | (version & 0xfL) << 12; + // set the 2 most significant bits of the 9th byte to 1 and 0 (variant field) + final long lsb = (buffer.getLong() & 0x3fff_ffff_ffff_ffffL) | 0x8000_0000_0000_0000L; + return new UUID(msb, lsb); + } + + final long msb = buffer.getLong(); + final long lsb = buffer.getLong(); + return new UUID(msb, lsb); + } + + private synchronized void validate() { + if (buffer.hasRemaining()) { + throw new BufferUnderflowException(); + } + } +} diff --git a/src/test/java/com/github/f4b6a3/uuid/TestSuite.java b/src/test/java/com/github/f4b6a3/uuid/TestSuite.java index 0d76121f..127387bf 100644 --- a/src/test/java/com/github/f4b6a3/uuid/TestSuite.java +++ b/src/test/java/com/github/f4b6a3/uuid/TestSuite.java @@ -40,6 +40,8 @@ import com.github.f4b6a3.uuid.util.internal.ByteUtilTest; import com.github.f4b6a3.uuid.util.internal.SettingsUtilTest; import com.github.f4b6a3.uuid.util.CombUtilTest; +import com.github.f4b6a3.uuid.util.MachineIdTest; +import com.github.f4b6a3.uuid.util.UuidBuilderTest; import com.github.f4b6a3.uuid.util.UuidComparatorTest; import com.github.f4b6a3.uuid.util.UuidTimeTest; import com.github.f4b6a3.uuid.util.UuidUtilTest; @@ -65,6 +67,7 @@ DotNetGuid1CodecTest.class, DotNetGuid4CodecTest.class, GUIDTest.class, + MachineIdTest.class, NameBasedMd5FactoryTest.class, NameBasedSha1FactoryTest.class, NcnameCodecTest.class, @@ -80,6 +83,7 @@ TimeOrderedCodecTest.class, TimeOrderedEpochFactoryTest.class, TimeOrderedFactoryTest.class, + UuidBuilderTest.class, UriCodecTest.class, UrnCodecTest.class, UuidComparatorTest.class, diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java new file mode 100644 index 00000000..6587570e --- /dev/null +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java @@ -0,0 +1,209 @@ +package com.github.f4b6a3.uuid.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; +import java.util.Random; +import java.util.UUID; + +import org.junit.Test; + +import com.github.f4b6a3.uuid.util.internal.ByteUtil; + +public class UuidBuilderTest { + + private static final int DEFAULT_LOOP_MAX = 1_000; + private static final Random seeder = new Random(1L); + + @Test + public void testVersionNumber() { + + assertEquals(0x0L, new UuidBuilder().put((long) 0L).put((long) 0L).build().version()); + assertEquals(0xfL, new UuidBuilder().put((long) -1L).put((long) -1L).build().version()); + + for (int i = 0; i < 15; i++) { + Random random = new Random(seeder.nextLong()); + assertEquals(i, new UuidBuilder(i).put(random.nextLong()).put(random.nextLong()).build().version()); + } + } + + @Test + public void testPutTwoLongsWithoutVersionNumber() { + + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { + + Random random = new Random(seeder.nextLong()); + long msb = random.nextLong(); + long lsb = random.nextLong(); + + UUID expected = new UUID(msb, lsb); + UUID actual = new UuidBuilder().put(msb).put(lsb).build(); + + assertEquals(expected, actual); + } + } + + @Test + public void testPutTwoLongsWithVersion4() { + + int version = 4; + + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { + + Random random = new Random(seeder.nextLong()); + + long msb = random.nextLong(); + long lsb = random.nextLong(); + + UUID expected = new UUID(version(msb, version), variant(lsb)); + UUID actual = new UuidBuilder(version).put(msb).put(lsb).build(); + + assertEquals(expected, actual); + } + } + + @Test + public void testPutFourIntsWithVersion4() { + + int version = 4; + + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { + + Random random = new Random(seeder.nextLong()); + + int part1 = random.nextInt(); + int part2 = random.nextInt(); + int part3 = random.nextInt(); + int part4 = random.nextInt(); + + long msb = (((long) part1) << 32) | (long) (part2 & 0xffffffffL); + long lsb = (((long) part3) << 32) | (long) (part4 & 0xffffffffL); + + UUID expected = new UUID(version(msb, version), variant(lsb)); + UUID actual = new UuidBuilder(version).put(part1).put(part2).put(part3).put(part4).build(); + + assertEquals(expected, actual); + } + } + + @Test + public void testPutSixteenBytesWithVersion4() { + + int version = 4; + + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { + + Random random = new Random(seeder.nextLong()); + + byte[] bytes1 = new byte[8]; + random.nextBytes(bytes1); + + byte[] bytes2 = new byte[8]; + random.nextBytes(bytes2); + + long msb = ByteUtil.toNumber(bytes1); + long lsb = ByteUtil.toNumber(bytes2); + UUID expected = new UUID(version(msb, version), variant(lsb)); + UUID actual = new UuidBuilder(version).put(bytes1).put(bytes2).build(); + + assertEquals(expected, actual); + } + } + + @Test + public void testPutTwoIntsFourShortsWithVersion8() { + + int version = 8; + + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { + + Random random = new Random(seeder.nextLong()); + + int p1 = random.nextInt(); + short p2 = (short) random.nextInt(); + short p3 = (short) random.nextInt(); + int p4 = random.nextInt(); + short p5 = (short) random.nextInt(); + short p6 = (short) random.nextInt(); + + long msb = ((long) p1) << 32 | ((long) p2 & 0xffffL) << 16 | (long) (p3 & 0xffffL); + long lsb = ((long) p4) << 32 | ((long) p5 & 0xffffL) << 16 | (long) (p6 & 0xffffL); + + UUID expected = new UUID(version(msb, version), variant(lsb)); + UUID actual = new UuidBuilder(version).put(p1).put(p2).put(p3).put(p4).put(p5).put(p6).build(); + + assertEquals(expected, actual); + } + } + + @Test + public void testIllegalArgumentException() { + + try { + new UuidBuilder(-1); + fail("Should throw illegal argument exception"); + } catch (IllegalArgumentException e) { + // success + } + + try { + new UuidBuilder(16); + fail("Should throw illegal argument exception"); + } catch (IllegalArgumentException e) { + // success + } + } + + @Test + public void testBufferUnderflowException() { + + try { + new UuidBuilder().build(); + fail("Should throw buffer underflow exception"); + } catch (BufferUnderflowException e) { + // success + } + + try { + new UuidBuilder().put((long) 0).put((int) 0).build(); + fail("Should throw buffer underflow exception"); + } catch (BufferUnderflowException e) { + // success + } + + try { + new UuidBuilder().put((long) 0).put((int) 0).put((short) 0L).build(); + fail("Should throw buffer underflow exception"); + } catch (BufferUnderflowException e) { + // success + } + } + + @Test + public void testBufferOverflowException() { + + try { + new UuidBuilder().put((byte) 0).put((long) 0).put((long) 0).build(); + fail("Should throw buffer overflow exception"); + } catch (BufferOverflowException e) { + // success + } + + try { + new UuidBuilder().put((byte) 0).put((long) 0).put((int) 0).put((short) 0L).put((short) 0L).build(); + fail("Should throw buffer overflow exception"); + } catch (BufferOverflowException e) { + // success + } + } + + private static long version(long msb, int version) { + return (msb & 0xffff_ffff_ffff_0fffL) | (version & 0xf) << 12; + } + + private static long variant(long lsb) { + return (lsb & 0x3fff_ffff_ffff_ffffL) | 0x8000_0000_0000_0000L; + } +} \ No newline at end of file From 5927390ff273e78d62b6c726e4263ccb5eb8df7a Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 20:00:17 -0300 Subject: [PATCH 13/40] Remove Mockito dependency Static mocking is not working. --- pom.xml | 6 -- .../f4b6a3/uuid/util/MachineIdTest.java | 72 ++++++++----------- 2 files changed, 30 insertions(+), 48 deletions(-) diff --git a/pom.xml b/pom.xml index 94979418..5bb93d1a 100644 --- a/pom.xml +++ b/pom.xml @@ -38,12 +38,6 @@ 4.13.1 test - - org.mockito - mockito-inline - 3.4.0 - test - diff --git a/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java b/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java index 6747967c..a72e97b5 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java @@ -2,52 +2,40 @@ import static org.junit.Assert.*; -import com.github.f4b6a3.uuid.util.internal.NetworkUtil; import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; import java.util.UUID; public class MachineIdTest { - @Test(expected = AssertionError.class) - public void testGetMachineString() { - MockedStatic mockedNetworkUtil = Mockito.mockStatic(NetworkUtil.class); - mockedNetworkUtil.when(NetworkUtil::getMachineString).thenReturn("mockedHostname 11-22-33-44-55-66 127.0.0.1"); - String machineString = MachineId.getMachineString(); - assertEquals("mockedHostname 11-22-33-44-55-66 127.0.0.1", machineString, "The machine string should match the mocked value"); - } - - @Test(expected = AssertionError.class) - public void testGetMachineId() { - long machineId1 = MachineId.getMachineId(); - long machineId2 = MachineId.getMachineId(); - assertEquals("Machine ID should be consistent", machineId1, machineId2); - assertTrue("Machine ID should be greater than or equal to 0", machineId1 >= 0); - } - - @Test - public void testGetMachineUuid() { - UUID machineUuid1 = MachineId.getMachineUuid(); - UUID machineUuid2 = MachineId.getMachineUuid(); - assertEquals("Machine UUID should be consistent", machineUuid1, machineUuid2); - assertEquals("Version should be 4 (random)", 4, machineUuid1.version()); - } - - @Test - public void testGetMachineHexa() { - String machineHexa1 = MachineId.getMachineHexa(); - String machineHexa2 = MachineId.getMachineHexa(); - assertEquals("Machine hexadecimal should be consistent", machineHexa1, machineHexa2); - assertEquals("Machine hexadecimal length should be 64", 64, machineHexa1.length()); - } - - @Test - public void testGetMachineHash() { - byte[] machineHash1 = MachineId.getMachineHash(); - byte[] machineHash2 = MachineId.getMachineHash(); - assertArrayEquals("Machine hash should be consistent", machineHash1, machineHash2); - assertEquals("Machine hash length should be 32 bytes", 32, machineHash1.length); - } + @Test + public void testGetMachineId() { + long machineId1 = MachineId.getMachineId(); + long machineId2 = MachineId.getMachineId(); + assertEquals("Machine ID should be consistent", machineId1, machineId2); + } + + @Test + public void testGetMachineUuid() { + UUID machineUuid1 = MachineId.getMachineUuid(); + UUID machineUuid2 = MachineId.getMachineUuid(); + assertEquals("Machine UUID should be consistent", machineUuid1, machineUuid2); + assertEquals("Version should be 4 (random)", 4, machineUuid1.version()); + } + + @Test + public void testGetMachineHexa() { + String machineHexa1 = MachineId.getMachineHexa(); + String machineHexa2 = MachineId.getMachineHexa(); + assertEquals("Machine hexadecimal should be consistent", machineHexa1, machineHexa2); + assertEquals("Machine hexadecimal length should be 64", 64, machineHexa1.length()); + } + + @Test + public void testGetMachineHash() { + byte[] machineHash1 = MachineId.getMachineHash(); + byte[] machineHash2 = MachineId.getMachineHash(); + assertArrayEquals("Machine hash should be consistent", machineHash1, machineHash2); + assertEquals("Machine hash length should be 32 bytes", 32, machineHash1.length); + } } From cb9c7275b8c20a4b0ad041308e093fdc3c9200b3 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 20:18:20 -0300 Subject: [PATCH 14/40] Update doc --- src/main/java/com/github/f4b6a3/uuid/util/MachineId.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java index 2613fd0e..d4bea90b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java @@ -62,6 +62,8 @@ private MachineId() { *

* It uses the first 8 bytes of the machine hash. * + * Note that the return value can be negative. + * * @return a number */ public static long getMachineId() { From 04ca89178a10ca0ca6fb0c8cc9736b6d04d843be Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Apr 2024 21:12:38 -0300 Subject: [PATCH 15/40] Update MachineIdTest.java Add tests for static methods in MachineId.java. --- .../github/f4b6a3/uuid/util/MachineId.java | 45 +++++++++++-------- .../f4b6a3/uuid/util/MachineIdTest.java | 35 +++++++++++++++ 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java index d4bea90b..182e504e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/MachineId.java @@ -68,12 +68,15 @@ private MachineId() { */ public static long getMachineId() { if (id == null) { - final byte[] bytes = getMachineHash(); - id = toNumber(bytes, 0, 8); + id = getMachineId(getMachineHash()); } return id; } + static long getMachineId(byte[] hash) { + return toNumber(hash, 0, 8); + } + /** * Returns a UUID generated from the machine hash. *

@@ -85,14 +88,17 @@ public static long getMachineId() { */ public static UUID getMachineUuid() { if (uuid == null) { - final byte[] bytes = getMachineHash(); - final long mostSigBits = toNumber(bytes, 0, 8); - final long leastSigBits = toNumber(bytes, 8, 16); - uuid = setVersion(new UUID(mostSigBits, leastSigBits), 4); + uuid = getMachineUuid(getMachineHash()); } return uuid; } + static UUID getMachineUuid(byte[] hash) { + final long mostSigBits = toNumber(hash, 0, 8); + final long leastSigBits = toNumber(hash, 8, 16); + return setVersion(new UUID(mostSigBits, leastSigBits), 4); + } + /** * Returns the machine hash in hexadecimal format. *

@@ -102,12 +108,15 @@ public static UUID getMachineUuid() { */ public static String getMachineHexa() { if (hexa == null) { - final byte[] bytes = getMachineHash(); - hexa = toHexadecimal(bytes); + hexa = getMachineHexa(getMachineHash()); } return hexa; } + static String getMachineHexa(byte[] hash) { + return toHexadecimal(hash); + } + /** * Returns the machine hash in a byte array. *

@@ -117,30 +126,30 @@ public static String getMachineHexa() { */ public static byte[] getMachineHash() { if (hash == null) { - try { - final String string = getMachineString(); - hash = MessageDigest.getInstance("SHA-256").digest(string.getBytes(StandardCharsets.UTF_8)); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("Message digest algorithm not supported.", e); - } - + hash = getMachineHash(getMachineString()); } return Arrays.copyOf(hash, hash.length); } + static byte[] getMachineHash(String string) { + try { + return MessageDigest.getInstance("SHA-256").digest(string.getBytes(StandardCharsets.UTF_8)); + } catch (NoSuchAlgorithmException e) { + throw new InternalError("Message digest algorithm not supported.", e); + } + } + /** * Returns a string containing host name, MAC and IP. *

- * Output format: "hostname 11-11-11-11-11-11 222.222.222.222" + * Output format: "hostname 11-11-11-11-11-11 222.222.222.222". * * @return a string */ public static String getMachineString() { - if (string == null) { string = NetworkUtil.getMachineString(); } - return string; } } diff --git a/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java b/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java index a72e97b5..97542d00 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/MachineIdTest.java @@ -8,34 +8,69 @@ public class MachineIdTest { + // echo -n "hostname 11-11-11-11-11-11 222.222.222.222" | sha256sum + // 1fe0fc1ba619e998770438b4568fb652e84bf20939f0b08c73843ba98ebddde9 + private static final String string = "hostname 11-11-11-11-11-11 222.222.222.222"; + private static final byte[] hash = MachineId.getMachineHash(string); + private static final long id = 0x1fe0fc1ba619e998L; + private static final UUID uuid = UUID.fromString("1fe0fc1b-a619-4998-b704-38b4568fb652"); + private static final String hexa = "1fe0fc1ba619e998770438b4568fb652e84bf20939f0b08c73843ba98ebddde9"; + @Test public void testGetMachineId() { + long machineId1 = MachineId.getMachineId(); long machineId2 = MachineId.getMachineId(); assertEquals("Machine ID should be consistent", machineId1, machineId2); + + machineId1 = MachineId.getMachineId(hash); + machineId2 = MachineId.getMachineId(hash); + assertEquals(id, MachineId.getMachineId(hash)); + assertEquals("Machine ID should be consistent", machineId1, machineId2); } @Test public void testGetMachineUuid() { + UUID machineUuid1 = MachineId.getMachineUuid(); UUID machineUuid2 = MachineId.getMachineUuid(); assertEquals("Machine UUID should be consistent", machineUuid1, machineUuid2); assertEquals("Version should be 4 (random)", 4, machineUuid1.version()); + + machineUuid1 = MachineId.getMachineUuid(hash); + machineUuid2 = MachineId.getMachineUuid(hash); + assertEquals(uuid, MachineId.getMachineUuid(hash)); + assertEquals("Machine UUID should be consistent", machineUuid1, machineUuid2); + assertEquals("Version should be 4 (random)", 4, machineUuid1.version()); } @Test public void testGetMachineHexa() { + String machineHexa1 = MachineId.getMachineHexa(); String machineHexa2 = MachineId.getMachineHexa(); assertEquals("Machine hexadecimal should be consistent", machineHexa1, machineHexa2); assertEquals("Machine hexadecimal length should be 64", 64, machineHexa1.length()); + + machineHexa1 = MachineId.getMachineHexa(hash); + machineHexa2 = MachineId.getMachineHexa(hash); + assertEquals(hexa, MachineId.getMachineHexa(hash)); + assertEquals("Machine hexadecimal should be consistent", machineHexa1, machineHexa2); + assertEquals("Machine hexadecimal length should be 64", 64, machineHexa1.length()); } @Test public void testGetMachineHash() { + byte[] machineHash1 = MachineId.getMachineHash(); byte[] machineHash2 = MachineId.getMachineHash(); assertArrayEquals("Machine hash should be consistent", machineHash1, machineHash2); assertEquals("Machine hash length should be 32 bytes", 32, machineHash1.length); + + machineHash1 = MachineId.getMachineHash(string); + machineHash2 = MachineId.getMachineHash(string); + assertArrayEquals(hash, MachineId.getMachineHash(string)); + assertArrayEquals("Machine hash should be consistent", machineHash1, machineHash2); + assertEquals("Machine hash length should be 32 bytes", 32, machineHash1.length); } } From 6531d6a6cc4f78e2d55678f397547055d5d00839 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 7 Apr 2024 06:29:30 -0300 Subject: [PATCH 16/40] Optimize parsing --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 169 ++++++++--------- .../github/f4b6a3/uuid/codec/StringCodec.java | 174 ++++++++---------- .../f4b6a3/uuid/codec/StringCodecTest.java | 11 +- 3 files changed, 149 insertions(+), 205 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 7841d9f1..f09c489b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -523,118 +523,93 @@ long getLeastSignificantBits() { static final class Parser { - private static final byte[] VALUES = new byte[256]; + private static final byte[] VALUES; static { - Arrays.fill(VALUES, (byte) -1); - VALUES['0'] = 0; - VALUES['1'] = 1; - VALUES['2'] = 2; - VALUES['3'] = 3; - VALUES['4'] = 4; - VALUES['5'] = 5; - VALUES['6'] = 6; - VALUES['7'] = 7; - VALUES['8'] = 8; - VALUES['9'] = 9; - VALUES['A'] = 10; - VALUES['B'] = 11; - VALUES['C'] = 12; - VALUES['D'] = 13; - VALUES['E'] = 14; - VALUES['F'] = 15; - VALUES['a'] = 10; - VALUES['b'] = 11; - VALUES['c'] = 12; - VALUES['d'] = 13; - VALUES['e'] = 14; - VALUES['f'] = 15; + byte[] temp = new byte[256]; + Arrays.fill(temp, (byte) -1); + temp['0'] = 0; + temp['1'] = 1; + temp['2'] = 2; + temp['3'] = 3; + temp['4'] = 4; + temp['5'] = 5; + temp['6'] = 6; + temp['7'] = 7; + temp['8'] = 8; + temp['9'] = 9; + temp['A'] = 10; + temp['B'] = 11; + temp['C'] = 12; + temp['D'] = 13; + temp['E'] = 14; + temp['F'] = 15; + temp['a'] = 10; + temp['b'] = 11; + temp['c'] = 12; + temp['d'] = 13; + temp['e'] = 14; + temp['f'] = 15; + VALUES = temp; } - public static GUID parse(final String string) { + private static final int DASH_POSITION_1 = 8; + private static final int DASH_POSITION_2 = 13; + private static final int DASH_POSITION_3 = 18; + private static final int DASH_POSITION_4 = 23; - if (!valid(string)) { - throw new IllegalArgumentException("Invalid GUID string: " + string); + public static GUID parse(final String str) { + + if (str == null || str.length() != 36) { + throw newIllegalArgumentException(str); } - long msb = 0; - long lsb = 0; - - // UUID string WITH hyphen - msb |= (long) VALUES[string.charAt(0x00)] << 60; - msb |= (long) VALUES[string.charAt(0x01)] << 56; - msb |= (long) VALUES[string.charAt(0x02)] << 52; - msb |= (long) VALUES[string.charAt(0x03)] << 48; - msb |= (long) VALUES[string.charAt(0x04)] << 44; - msb |= (long) VALUES[string.charAt(0x05)] << 40; - msb |= (long) VALUES[string.charAt(0x06)] << 36; - msb |= (long) VALUES[string.charAt(0x07)] << 32; - // input[8] = '-' - msb |= (long) VALUES[string.charAt(0x09)] << 28; - msb |= (long) VALUES[string.charAt(0x0a)] << 24; - msb |= (long) VALUES[string.charAt(0x0b)] << 20; - msb |= (long) VALUES[string.charAt(0x0c)] << 16; - // input[13] = '-' - msb |= (long) VALUES[string.charAt(0x0e)] << 12; - msb |= (long) VALUES[string.charAt(0x0f)] << 8; - msb |= (long) VALUES[string.charAt(0x10)] << 4; - msb |= (long) VALUES[string.charAt(0x11)]; - // input[18] = '-' - lsb |= (long) VALUES[string.charAt(0x13)] << 60; - lsb |= (long) VALUES[string.charAt(0x14)] << 56; - lsb |= (long) VALUES[string.charAt(0x15)] << 52; - lsb |= (long) VALUES[string.charAt(0x16)] << 48; - // input[23] = '-' - lsb |= (long) VALUES[string.charAt(0x18)] << 44; - lsb |= (long) VALUES[string.charAt(0x19)] << 40; - lsb |= (long) VALUES[string.charAt(0x1a)] << 36; - lsb |= (long) VALUES[string.charAt(0x1b)] << 32; - lsb |= (long) VALUES[string.charAt(0x1c)] << 28; - lsb |= (long) VALUES[string.charAt(0x1d)] << 24; - lsb |= (long) VALUES[string.charAt(0x1e)] << 20; - lsb |= (long) VALUES[string.charAt(0x1f)] << 16; - lsb |= (long) VALUES[string.charAt(0x20)] << 12; - lsb |= (long) VALUES[string.charAt(0x21)] << 8; - lsb |= (long) VALUES[string.charAt(0x22)] << 4; - lsb |= (long) VALUES[string.charAt(0x23)]; - - return new GUID(msb, lsb); - } + if (str.charAt(DASH_POSITION_1) != '-' || str.charAt(DASH_POSITION_2) != '-' + || str.charAt(DASH_POSITION_3) != '-' || str.charAt(DASH_POSITION_4) != '-') { + throw newIllegalArgumentException(str); + } - private static final int[] DASH_POSITIONS = { 8, 13, 18, 23 }; - private static final int DASH_REQUIRED_COUNT = 4; + final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); + final long hi2 = parseShort(str, 0x09, 0x0a, 0x0b, 0x0c) << 16 | parseShort(str, 0x0e, 0x0f, 0x10, 0x11); + final long lo1 = parseShort(str, 0x13, 0x14, 0x15, 0x16) << 16 | parseShort(str, 0x18, 0x19, 0x1a, 0x1b); + final long lo2 = parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f) << 16 | parseShort(str, 0x20, 0x21, 0x22, 0x23); - private static boolean isCharValid(char chr) { - return chr >= 0 && chr < VALUES.length && VALUES[chr] >= 0; + return new GUID(hi1 << 32 | hi2, lo1 << 32 | lo2); } - private static boolean isDashPosition(int index) { - for (int dashPosition : DASH_POSITIONS) { - if (index == dashPosition) { - return true; - } - } - return false; - } + private static long parseShort(final String str, final int i1, final int i2, final int i3, final int i4) { - public static boolean valid(final String guid) { - if (guid == null || guid.length() != GUID_CHARS) { - return false; // null or wrong length + final char chr1 = str.charAt(i1); + final char chr2 = str.charAt(i2); + final char chr3 = str.charAt(i3); + final char chr4 = str.charAt(i4); + + if (chr1 > 0xff || chr2 > 0xff || chr3 > 0xff || chr4 > 0xff) { + throw newIllegalArgumentException(str); } - int dashesCount = 0; - for (int i = 0; i < GUID_CHARS; i++) { - char chr = guid.charAt(i); - if (isCharValid(chr)) { - continue; // character is valid - } - if (chr == '-' && isDashPosition(i)) { - dashesCount++; - continue; - } - return false; // invalid character + final int val1 = VALUES[chr1]; + final int val2 = VALUES[chr2]; + final int val3 = VALUES[chr3]; + final int val4 = VALUES[chr4]; + + if (val1 == -1 || val2 == -1 || val3 == -1 || val4 == -1) { + throw newIllegalArgumentException(str); } - return dashesCount == DASH_REQUIRED_COUNT; + return (long) (val1 << 12 | val2 << 8 | val3 << 4 | val4); + } + + private static RuntimeException newIllegalArgumentException(final String str) { + return new IllegalArgumentException("Invalid UUID: " + str); + } + + public static boolean valid(final String guid) { + try { + parse(guid); + return true; + } catch (IllegalArgumentException e) { + return false; + } } } } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java index abd13e05..a168b5bf 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java @@ -69,6 +69,16 @@ public class StringCodec implements UuidCodec { private static final String URN_PREFIX = "urn:uuid:"; private static final boolean JAVA_VERSION_GREATER_THAN_8 = JavaVersionUtil.getJavaVersion() > 8; + private static final int WITH_DASH_UUID_LENGTH = 36; + private static final int WITHOUT_DASH_UUID_LENGTH = 32; + private static final int URN_PREFIX_UUID_LENGTH = 45; + private static final int CURLY_BRACES_UUID_LENGTH = 38; + + private static final int DASH_POSITION_1 = 8; + private static final int DASH_POSITION_2 = 13; + private static final int DASH_POSITION_3 = 18; + private static final int DASH_POSITION_4 = 23; + /** * Get a string from a UUID. *

@@ -151,124 +161,86 @@ public String encode(UUID uuid) { * @throws InvalidUuidException if the argument is invalid */ @Override - public UUID decode(String string) { - - char[] chars = toCharArray(string); - UuidValidator.validate(chars); - - long msb = 0; - long lsb = 0; - - if (chars.length == 32) { - // UUID string WITHOUT hyphen - msb |= MAP.get(chars[0x00]) << 60; - msb |= MAP.get(chars[0x01]) << 56; - msb |= MAP.get(chars[0x02]) << 52; - msb |= MAP.get(chars[0x03]) << 48; - msb |= MAP.get(chars[0x04]) << 44; - msb |= MAP.get(chars[0x05]) << 40; - msb |= MAP.get(chars[0x06]) << 36; - msb |= MAP.get(chars[0x07]) << 32; - msb |= MAP.get(chars[0x08]) << 28; - msb |= MAP.get(chars[0x09]) << 24; - msb |= MAP.get(chars[0x0a]) << 20; - msb |= MAP.get(chars[0x0b]) << 16; - msb |= MAP.get(chars[0x0c]) << 12; - msb |= MAP.get(chars[0x0d]) << 8; - msb |= MAP.get(chars[0x0e]) << 4; - msb |= MAP.get(chars[0x0f]); - - lsb |= MAP.get(chars[0x10]) << 60; - lsb |= MAP.get(chars[0x11]) << 56; - lsb |= MAP.get(chars[0x12]) << 52; - lsb |= MAP.get(chars[0x13]) << 48; - lsb |= MAP.get(chars[0x14]) << 44; - lsb |= MAP.get(chars[0x15]) << 40; - lsb |= MAP.get(chars[0x16]) << 36; - lsb |= MAP.get(chars[0x17]) << 32; - lsb |= MAP.get(chars[0x18]) << 28; - lsb |= MAP.get(chars[0x19]) << 24; - lsb |= MAP.get(chars[0x1a]) << 20; - lsb |= MAP.get(chars[0x1b]) << 16; - lsb |= MAP.get(chars[0x1c]) << 12; - lsb |= MAP.get(chars[0x1d]) << 8; - lsb |= MAP.get(chars[0x1e]) << 4; - lsb |= MAP.get(chars[0x1f]); - } else { - // UUID string WITH hyphen - msb |= MAP.get(chars[0x00]) << 60; - msb |= MAP.get(chars[0x01]) << 56; - msb |= MAP.get(chars[0x02]) << 52; - msb |= MAP.get(chars[0x03]) << 48; - msb |= MAP.get(chars[0x04]) << 44; - msb |= MAP.get(chars[0x05]) << 40; - msb |= MAP.get(chars[0x06]) << 36; - msb |= MAP.get(chars[0x07]) << 32; - // input[8] = '-' - msb |= MAP.get(chars[0x09]) << 28; - msb |= MAP.get(chars[0x0a]) << 24; - msb |= MAP.get(chars[0x0b]) << 20; - msb |= MAP.get(chars[0x0c]) << 16; - // input[13] = '-' - msb |= MAP.get(chars[0x0e]) << 12; - msb |= MAP.get(chars[0x0f]) << 8; - msb |= MAP.get(chars[0x10]) << 4; - msb |= MAP.get(chars[0x11]); - // input[18] = '-' - lsb |= MAP.get(chars[0x13]) << 60; - lsb |= MAP.get(chars[0x14]) << 56; - lsb |= MAP.get(chars[0x15]) << 52; - lsb |= MAP.get(chars[0x16]) << 48; - // input[23] = '-' - lsb |= MAP.get(chars[0x18]) << 44; - lsb |= MAP.get(chars[0x19]) << 40; - lsb |= MAP.get(chars[0x1a]) << 36; - lsb |= MAP.get(chars[0x1b]) << 32; - lsb |= MAP.get(chars[0x1c]) << 28; - lsb |= MAP.get(chars[0x1d]) << 24; - lsb |= MAP.get(chars[0x1e]) << 20; - lsb |= MAP.get(chars[0x1f]) << 16; - lsb |= MAP.get(chars[0x20]) << 12; - lsb |= MAP.get(chars[0x21]) << 8; - lsb |= MAP.get(chars[0x22]) << 4; - lsb |= MAP.get(chars[0x23]); + public UUID decode(final String string) { + + if (string == null) { + throw newInvalidUuidException(string); + } + + final String str = modifyString(string); + + if (str.length() == WITH_DASH_UUID_LENGTH) { + if (str.charAt(DASH_POSITION_1) != '-' || str.charAt(DASH_POSITION_2) != '-' + || str.charAt(DASH_POSITION_3) != '-' || str.charAt(DASH_POSITION_4) != '-') { + throw newInvalidUuidException(str); + } + final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); + final long hi2 = parseShort(str, 0x09, 0x0a, 0x0b, 0x0c) << 16 | parseShort(str, 0x0e, 0x0f, 0x10, 0x11); + final long lo1 = parseShort(str, 0x13, 0x14, 0x15, 0x16) << 16 | parseShort(str, 0x18, 0x19, 0x1a, 0x1b); + final long lo2 = parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f) << 16 | parseShort(str, 0x20, 0x21, 0x22, 0x23); + return new UUID(hi1 << 32 | hi2, lo1 << 32 | lo2); } - return new UUID(msb, lsb); + if (str.length() == WITHOUT_DASH_UUID_LENGTH) { + final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); + final long hi2 = parseShort(str, 0x08, 0x09, 0x0a, 0x0b) << 16 | parseShort(str, 0x0c, 0x0d, 0x0e, 0x0f); + final long lo1 = parseShort(str, 0x10, 0x11, 0x12, 0x13) << 16 | parseShort(str, 0x14, 0x15, 0x16, 0x17); + final long lo2 = parseShort(str, 0x18, 0x19, 0x1a, 0x1b) << 16 | parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f); + return new UUID(hi1 << 32 | hi2, lo1 << 32 | lo2); + } + + throw newInvalidUuidException(str); + } + + private static long parseShort(final String str, final int i1, final int i2, final int i3, final int i4) { + + final char chr1 = str.charAt(i1); + final char chr2 = str.charAt(i2); + final char chr3 = str.charAt(i3); + final char chr4 = str.charAt(i4); + + if (chr1 > 0xff || chr2 > 0xff || chr3 > 0xff || chr4 > 0xff) { + throw newInvalidUuidException(str); + } + + final long val1 = MAP.get(chr1); + final long val2 = MAP.get(chr2); + final long val3 = MAP.get(chr3); + final long val4 = MAP.get(chr4); + + if (val1 == -1 || val2 == -1 || val3 == -1 || val4 == -1) { + throw newInvalidUuidException(str); + } + + return (long) (val1 << 12 | val2 << 8 | val3 << 4 | val4); + } + + private static RuntimeException newInvalidUuidException(final String str) { + return new InvalidUuidException("Invalid UUID: " + str); } /** - * Returns a char array of a string. + * Returns a modified string without URN prefix and curly braces. *

- * It removes URN prefix and curly braces from the string. + * It removes URN prefix and curly braces from the original string. * * @param string a string * @return a substring */ - protected static char[] toCharArray(String string) { - - if (string == null) { - throw new InvalidUuidException("Invalid UUID: null"); - } - - char[] chars = string.toCharArray(); + protected static String modifyString(String string) { // UUID URN format: "urn:uuid:00000000-0000-0000-0000-000000000000" - if (chars.length == 45 && string.startsWith(URN_PREFIX)) { - // Remove the UUID URN prefix: "urn:uuid:" - char[] substring = new char[chars.length - 9]; - System.arraycopy(chars, 9, substring, 0, substring.length); - return substring; + if (string.length() == URN_PREFIX_UUID_LENGTH && string.startsWith(URN_PREFIX)) { + // Remove the URN prefix: "urn:uuid:" + return string.substring(URN_PREFIX.length()); } // Curly braces format: "{00000000-0000-0000-0000-000000000000}" - if (chars.length == 38 && chars[0] == '{' && chars[chars.length - 1] == '}') { + if (string.length() == CURLY_BRACES_UUID_LENGTH && string.startsWith("{") && string.endsWith("}")) { // Remove curly braces: '{' and '}' - char[] substring = new char[chars.length - 2]; - System.arraycopy(chars, 1, substring, 0, substring.length); - return substring; + return string.substring(1, string.length() - 1); } - return chars; + return string; } } diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java index e343684c..611fa008 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java @@ -227,27 +227,24 @@ public void testDecodeInvalidUuidException() { } @Test - public void testToCharArray() { + public void testModifyString() { { // 00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - char[] chars = StringCodec.toCharArray(string); - assertEquals(string, String.valueOf(chars)); + assertEquals(string, StringCodec.modifyString(string)); } { // urn:uuid:00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - char[] chars = StringCodec.toCharArray(URN_PREFIX + string); - assertEquals(string, String.valueOf(chars)); + assertEquals(string, StringCodec.modifyString(URN_PREFIX + string)); } { // {00000000-0000-0000-0000-000000000000} String string = UUID.randomUUID().toString(); - char[] chars = StringCodec.toCharArray("{" + string + "}"); - assertEquals(string, String.valueOf(chars)); + assertEquals(string, StringCodec.modifyString("{" + string + "}")); } } From 9b7331bc2c76555b840ff794cfd0c4558230529e Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 7 Apr 2024 16:49:23 -0300 Subject: [PATCH 17/40] Optimize base-n codecs --- .../github/f4b6a3/uuid/codec/StringCodec.java | 12 ++-- .../github/f4b6a3/uuid/codec/base/BaseN.java | 31 ++++---- .../codec/base/function/Base16Decoder.java | 70 +++++++++---------- .../codec/base/function/Base32Decoder.java | 61 ++++++++-------- .../codec/base/function/Base64Decoder.java | 53 +++++++------- .../codec/base/function/BaseNDecoder.java | 4 +- .../f4b6a3/uuid/codec/other/NcnameCodec.java | 15 ++-- .../f4b6a3/uuid/util/UuidValidator.java | 4 +- .../{LongArray.java => ByteArray.java} | 30 ++++---- 9 files changed, 140 insertions(+), 140 deletions(-) rename src/main/java/com/github/f4b6a3/uuid/util/immutable/{LongArray.java => ByteArray.java} (80%) diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java index a168b5bf..8505a108 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java @@ -29,8 +29,8 @@ import com.github.f4b6a3.uuid.codec.base.Base16Codec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; import com.github.f4b6a3.uuid.util.UuidValidator; +import com.github.f4b6a3.uuid.util.immutable.ByteArray; import com.github.f4b6a3.uuid.util.immutable.CharArray; -import com.github.f4b6a3.uuid.util.immutable.LongArray; import com.github.f4b6a3.uuid.util.internal.JavaVersionUtil; /** @@ -63,7 +63,7 @@ public class StringCodec implements UuidCodec { */ public static final StringCodec INSTANCE = new StringCodec(); - private static final LongArray MAP = Base16Codec.INSTANCE.getBase().getMap(); + private static final ByteArray MAP = Base16Codec.INSTANCE.getBase().getMap(); private static final CharArray ALPHABET = Base16Codec.INSTANCE.getBase().getAlphabet(); private static final String URN_PREFIX = "urn:uuid:"; @@ -203,10 +203,10 @@ private static long parseShort(final String str, final int i1, final int i2, fin throw newInvalidUuidException(str); } - final long val1 = MAP.get(chr1); - final long val2 = MAP.get(chr2); - final long val3 = MAP.get(chr3); - final long val4 = MAP.get(chr4); + final int val1 = MAP.get(chr1); + final int val2 = MAP.get(chr2); + final int val3 = MAP.get(chr3); + final int val4 = MAP.get(chr4); if (val1 == -1 || val2 == -1 || val3 == -1 || val4 == -1) { throw newInvalidUuidException(str); diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java index 7c7cc282..8e942ea6 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseN.java @@ -24,9 +24,11 @@ package com.github.f4b6a3.uuid.codec.base; +import java.util.Arrays; + import com.github.f4b6a3.uuid.exception.InvalidUuidException; +import com.github.f4b6a3.uuid.util.immutable.ByteArray; import com.github.f4b6a3.uuid.util.immutable.CharArray; -import com.github.f4b6a3.uuid.util.immutable.LongArray; /** * Class that represents the base-n encodings. @@ -39,7 +41,7 @@ public final class BaseN { private final boolean sensitive; private final CharArray alphabet; - private final LongArray map; + private final ByteArray map; /** * The minimum radix: 2. @@ -59,7 +61,7 @@ public final class BaseN { */ protected static final String ALPHABET_64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; - private static final int BIT_LENGTH = 128; + private static final int UUID_BITS = 128; /** * Public constructor for the base-n object. @@ -145,7 +147,7 @@ public BaseN(String alphabet) { this.radix = charset.length(); // set the length field - this.length = (int) Math.ceil(BIT_LENGTH / (Math.log(this.radix) / Math.log(2))); + this.length = (int) Math.ceil(UUID_BITS / (Math.log(this.radix) / Math.log(2))); // set the padding field this.padding = charset.charAt(0); @@ -210,7 +212,7 @@ public CharArray getAlphabet() { * * @return a map */ - public LongArray getMap() { + public ByteArray getMap() { return this.map; } @@ -250,22 +252,23 @@ private static boolean sensitive(String charset) { return !(charset.equals(lowercase) || charset.equals(uppercase)); } - private static LongArray map(String alphabet, boolean sensitive) { + private static ByteArray map(String alphabet, boolean sensitive) { + // initialize the map with -1 - final long[] mapping = new long[128]; - for (int i = 0; i < mapping.length; i++) { - mapping[i] = -1; - } + byte[] mapping = new byte[256]; + Arrays.fill(mapping, (byte) -1); + // map the alphabets chars to values for (int i = 0; i < alphabet.length(); i++) { if (sensitive) { - mapping[alphabet.charAt(i)] = i; + mapping[alphabet.charAt(i)] = (byte) i; } else { - mapping[alphabet.toLowerCase().charAt(i)] = i; - mapping[alphabet.toUpperCase().charAt(i)] = i; + mapping[alphabet.toLowerCase().charAt(i)] = (byte) i; + mapping[alphabet.toUpperCase().charAt(i)] = (byte) i; } } - return LongArray.from(mapping); + + return ByteArray.from(mapping); } private static String expand(int radix) { diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java index ab89b6ac..a9a78ad3 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java @@ -45,48 +45,46 @@ public final class Base16Decoder extends BaseNDecoder { public Base16Decoder(BaseN base) { super(base); } - + @Override public UUID apply(String string) { - - char[] chars = string.toCharArray(); - + long msb = 0; long lsb = 0; - msb |= map.get(chars[0x00]) << 60; - msb |= map.get(chars[0x01]) << 56; - msb |= map.get(chars[0x02]) << 52; - msb |= map.get(chars[0x03]) << 48; - msb |= map.get(chars[0x04]) << 44; - msb |= map.get(chars[0x05]) << 40; - msb |= map.get(chars[0x06]) << 36; - msb |= map.get(chars[0x07]) << 32; - msb |= map.get(chars[0x08]) << 28; - msb |= map.get(chars[0x09]) << 24; - msb |= map.get(chars[0x0a]) << 20; - msb |= map.get(chars[0x0b]) << 16; - msb |= map.get(chars[0x0c]) << 12; - msb |= map.get(chars[0x0d]) << 8; - msb |= map.get(chars[0x0e]) << 4; - msb |= map.get(chars[0x0f]); + msb = (msb << 4) | (map.get(string.charAt(0x00)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x01)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x02)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x03)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x04)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x05)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x06)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x07)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x08)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x09)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0a)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0b)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0c)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0d)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0e)) & 0xffL); + msb = (msb << 4) | (map.get(string.charAt(0x0f)) & 0xffL); - lsb |= map.get(chars[0x10]) << 60; - lsb |= map.get(chars[0x11]) << 56; - lsb |= map.get(chars[0x12]) << 52; - lsb |= map.get(chars[0x13]) << 48; - lsb |= map.get(chars[0x14]) << 44; - lsb |= map.get(chars[0x15]) << 40; - lsb |= map.get(chars[0x16]) << 36; - lsb |= map.get(chars[0x17]) << 32; - lsb |= map.get(chars[0x18]) << 28; - lsb |= map.get(chars[0x19]) << 24; - lsb |= map.get(chars[0x1a]) << 20; - lsb |= map.get(chars[0x1b]) << 16; - lsb |= map.get(chars[0x1c]) << 12; - lsb |= map.get(chars[0x1d]) << 8; - lsb |= map.get(chars[0x1e]) << 4; - lsb |= map.get(chars[0x1f]); + lsb = (lsb << 4) | (map.get(string.charAt(0x10)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x11)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x12)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x13)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x14)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x15)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x16)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x17)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x18)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x19)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1a)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1b)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1c)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1d)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1e)) & 0xffL); + lsb = (lsb << 4) | (map.get(string.charAt(0x1f)) & 0xffL); return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java index 682d5e24..197f724f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java @@ -49,40 +49,39 @@ public Base32Decoder(BaseN base) { @Override public UUID apply(String string) { - char[] chars = string.toCharArray(); - long msb = 0; long lsb = 0; - msb |= map.get(chars[0x00]) << 59; - msb |= map.get(chars[0x01]) << 54; - msb |= map.get(chars[0x02]) << 49; - msb |= map.get(chars[0x03]) << 44; - msb |= map.get(chars[0x04]) << 39; - msb |= map.get(chars[0x05]) << 34; - msb |= map.get(chars[0x06]) << 29; - msb |= map.get(chars[0x07]) << 24; - msb |= map.get(chars[0x08]) << 19; - msb |= map.get(chars[0x09]) << 14; - msb |= map.get(chars[0x0a]) << 9; - msb |= map.get(chars[0x0b]) << 4; - - msb |= map.get(chars[0x0c]) >>> 1; - lsb |= map.get(chars[0x0c]) << 63; - - lsb |= map.get(chars[0x0d]) << 58; - lsb |= map.get(chars[0x0e]) << 53; - lsb |= map.get(chars[0x0f]) << 48; - lsb |= map.get(chars[0x10]) << 43; - lsb |= map.get(chars[0x11]) << 38; - lsb |= map.get(chars[0x12]) << 33; - lsb |= map.get(chars[0x13]) << 28; - lsb |= map.get(chars[0x14]) << 23; - lsb |= map.get(chars[0x15]) << 18; - lsb |= map.get(chars[0x16]) << 13; - lsb |= map.get(chars[0x17]) << 8; - lsb |= map.get(chars[0x18]) << 3; - lsb |= map.get(chars[0x19]) >>> 2; + msb = (msb << 5) | (map.get(string.charAt(0x00)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x01)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x02)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x03)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x04)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x05)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x06)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x07)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x08)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x09)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x0a)) & 0xffL); + msb = (msb << 5) | (map.get(string.charAt(0x0b)) & 0xffL); + + msb = (msb << 4) | ((map.get(string.charAt(0x0c)) & 0xffL) >>> 1); + + lsb = (lsb << 5) | (map.get(string.charAt(0x0c)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x0d)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x0e)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x0f)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x10)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x11)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x12)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x13)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x14)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x15)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x16)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x17)) & 0xffL); + lsb = (lsb << 5) | (map.get(string.charAt(0x18)) & 0xffL); + + lsb = (lsb << 3) | ((map.get(string.charAt(0x19)) & 0xffL) >>> 2); return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java index a8932192..6fcf2dce 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java @@ -49,36 +49,35 @@ public Base64Decoder(BaseN base) { @Override public UUID apply(String string) { - char[] chars = string.toCharArray(); - long msb = 0; long lsb = 0; - msb |= map.get(chars[0x00]) << 58; - msb |= map.get(chars[0x01]) << 52; - msb |= map.get(chars[0x02]) << 46; - msb |= map.get(chars[0x03]) << 40; - msb |= map.get(chars[0x04]) << 34; - msb |= map.get(chars[0x05]) << 28; - msb |= map.get(chars[0x06]) << 22; - msb |= map.get(chars[0x07]) << 16; - msb |= map.get(chars[0x08]) << 10; - msb |= map.get(chars[0x09]) << 4; - - msb |= map.get(chars[0x0a]) >>> 2; - lsb |= map.get(chars[0x0a]) << 62; - - lsb |= map.get(chars[0x0b]) << 56; - lsb |= map.get(chars[0x0c]) << 50; - lsb |= map.get(chars[0x0d]) << 44; - lsb |= map.get(chars[0x0e]) << 38; - lsb |= map.get(chars[0x0f]) << 32; - lsb |= map.get(chars[0x10]) << 26; - lsb |= map.get(chars[0x11]) << 20; - lsb |= map.get(chars[0x12]) << 14; - lsb |= map.get(chars[0x13]) << 8; - lsb |= map.get(chars[0x14]) << 2; - lsb |= map.get(chars[0x15]) >>> 4; + msb = (msb << 6) | (map.get(string.charAt(0x00)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x01)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x02)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x03)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x04)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x05)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x06)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x07)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x08)) & 0xffL); + msb = (msb << 6) | (map.get(string.charAt(0x09)) & 0xffL); + + msb = (msb << 4) | ((map.get(string.charAt(0x0a)) & 0xffL) >>> 2); + + lsb = (lsb << 6) | (map.get(string.charAt(0x0a)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x0b)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x0c)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x0d)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x0e)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x0f)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x10)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x11)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x12)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x13)) & 0xffL); + lsb = (lsb << 6) | (map.get(string.charAt(0x14)) & 0xffL); + + lsb = (lsb << 2) | ((map.get(string.charAt(0x15)) & 0xffL) >>> 4); return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java index 7dfdfc8a..2d0aa5d5 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java @@ -28,7 +28,7 @@ import java.util.function.Function; import com.github.f4b6a3.uuid.codec.base.BaseN; -import com.github.f4b6a3.uuid.util.immutable.LongArray; +import com.github.f4b6a3.uuid.util.immutable.ByteArray; /** * Abstract function to be extended by all decoder functions of this package. @@ -45,7 +45,7 @@ public abstract class BaseNDecoder implements Function { /** * The base-n map. */ - protected final LongArray map; + protected final ByteArray map; /** * @param base an enumeration that represents the base-n encoding diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java index 34f48ae6..8126c256 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java @@ -24,6 +24,7 @@ package com.github.f4b6a3.uuid.codec.other; +import java.util.Arrays; import java.util.UUID; import com.github.f4b6a3.uuid.codec.BinaryCodec; @@ -33,8 +34,8 @@ import com.github.f4b6a3.uuid.codec.base.BaseNCodec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; import com.github.f4b6a3.uuid.util.UuidValidator; +import com.github.f4b6a3.uuid.util.immutable.ByteArray; import com.github.f4b6a3.uuid.util.immutable.CharArray; -import com.github.f4b6a3.uuid.util.immutable.LongArray; import com.github.f4b6a3.uuid.util.internal.ByteUtil; /** @@ -80,13 +81,13 @@ public final class NcnameCodec implements UuidCodec { private static final CharArray VERSION_UPPERCASE = CharArray.from("ABCDEFGHIJKLMNOP".toCharArray()); private static final CharArray VERSION_LOWERCASE = CharArray.from("abcdefghijklmnop".toCharArray()); - private static final LongArray VERSION_MAP; + private static final ByteArray VERSION_MAP; static { + // initialize the array with -1 - final long[] mapping = new long[128]; - for (int i = 0; i < mapping.length; i++) { - mapping[i] = -1; - } + byte[] mapping = new byte[256]; + Arrays.fill(mapping, (byte) -1); + // upper case for base-64 mapping['A'] = 0x0; mapping['B'] = 0x1; @@ -122,7 +123,7 @@ public final class NcnameCodec implements UuidCodec { mapping['o'] = 0xe; mapping['p'] = 0xf; - VERSION_MAP = LongArray.from(mapping); + VERSION_MAP = ByteArray.from(mapping); } /** diff --git a/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java b/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java index 1dc7e4d1..ad76faac 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/UuidValidator.java @@ -28,7 +28,7 @@ import com.github.f4b6a3.uuid.codec.base.Base16Codec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; -import com.github.f4b6a3.uuid.util.immutable.LongArray; +import com.github.f4b6a3.uuid.util.immutable.ByteArray; /** * Utility for UUID validation. @@ -49,7 +49,7 @@ */ public final class UuidValidator { - private static final LongArray MAP = Base16Codec.INSTANCE.getBase().getMap(); + private static final ByteArray MAP = Base16Codec.INSTANCE.getBase().getMap(); private UuidValidator() { } diff --git a/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java b/src/main/java/com/github/f4b6a3/uuid/util/immutable/ByteArray.java similarity index 80% rename from src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java rename to src/main/java/com/github/f4b6a3/uuid/util/immutable/ByteArray.java index f6c03134..9b3c003a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/immutable/LongArray.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/immutable/ByteArray.java @@ -27,33 +27,33 @@ import java.util.Arrays; /** - * Immutable array of longs. + * Immutable array of bytes. */ -public final class LongArray { +public final class ByteArray { - private final long[] array; + private final byte[] array; - private LongArray(long[] a) { + private ByteArray(byte[] a) { array = Arrays.copyOf(a, a.length); } /** * Creates an instance of this class. * - * @param a an array of longs + * @param a an array of bytes * @return a new instance */ - public static LongArray from(long[] a) { - return new LongArray(a); + public static ByteArray from(byte[] a) { + return new ByteArray(a); } /** - * Return the long at a position. + * Return the byte at a position. * * @param index the position - * @return a long + * @return a byte */ - public long get(int index) { + public byte get(int index) { return array[index]; } @@ -69,10 +69,10 @@ public int length() { /** * Returns copy of the array. * - * @return an array of longs + * @return an array of bytes */ - public long[] array() { - return array.clone(); + public byte[] array() { + return Arrays.copyOf(array, array.length); } @Override @@ -91,12 +91,12 @@ public boolean equals(Object obj) { return false; if (getClass() != obj.getClass()) return false; - LongArray other = (LongArray) obj; + ByteArray other = (ByteArray) obj; return Arrays.equals(array, other.array); } @Override public String toString() { - return "LongArray [array=" + Arrays.toString(array) + "]"; + return "ByteArray [array=" + Arrays.toString(array) + "]"; } } From b4a1a42bcc1d464d8ecfb6804bfeb06f728382ff Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 7 Apr 2024 18:36:14 -0300 Subject: [PATCH 18/40] Optimize base-n codecs --- .../f4b6a3/uuid/codec/base/BaseNCodec.java | 8 +++- .../codec/base/function/Base16Decoder.java | 42 ++++--------------- .../codec/base/function/Base32Decoder.java | 42 ++++++------------- .../codec/base/function/Base64Decoder.java | 38 ++++++----------- .../codec/base/function/BaseNDecoder.java | 9 ++++ .../base/function/BaseNRemainderDecoder.java | 6 +-- 6 files changed, 50 insertions(+), 95 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java index 99047362..e2e265db 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec.java @@ -274,10 +274,16 @@ public String encode(UUID uuid) { @Override public UUID decode(String string) { try { - base.validate(string); + validate(string); return decoder.apply(string); } catch (RuntimeException e) { throw new InvalidUuidException(e.getMessage(), e); } } + + protected void validate(String string) { + if (string == null || string.length() != this.base.getLength()) { + throw InvalidUuidException.newInstance(string); + } + } } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java index a9a78ad3..1bb5ea05 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Decoder.java @@ -45,46 +45,20 @@ public final class Base16Decoder extends BaseNDecoder { public Base16Decoder(BaseN base) { super(base); } - + @Override public UUID apply(String string) { - + long msb = 0; long lsb = 0; - msb = (msb << 4) | (map.get(string.charAt(0x00)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x01)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x02)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x03)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x04)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x05)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x06)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x07)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x08)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x09)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0a)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0b)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0c)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0d)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0e)) & 0xffL); - msb = (msb << 4) | (map.get(string.charAt(0x0f)) & 0xffL); + for (int i = 0; i < 16; i++) { + msb = (msb << 4) | get(string, i); + } - lsb = (lsb << 4) | (map.get(string.charAt(0x10)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x11)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x12)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x13)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x14)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x15)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x16)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x17)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x18)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x19)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1a)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1b)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1c)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1d)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1e)) & 0xffL); - lsb = (lsb << 4) | (map.get(string.charAt(0x1f)) & 0xffL); + for (int i = 16; i < 32; i++) { + lsb = (lsb << 4) | get(string, i); + } return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java index 197f724f..50771742 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Decoder.java @@ -52,36 +52,18 @@ public UUID apply(String string) { long msb = 0; long lsb = 0; - msb = (msb << 5) | (map.get(string.charAt(0x00)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x01)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x02)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x03)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x04)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x05)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x06)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x07)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x08)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x09)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x0a)) & 0xffL); - msb = (msb << 5) | (map.get(string.charAt(0x0b)) & 0xffL); - - msb = (msb << 4) | ((map.get(string.charAt(0x0c)) & 0xffL) >>> 1); - - lsb = (lsb << 5) | (map.get(string.charAt(0x0c)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x0d)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x0e)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x0f)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x10)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x11)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x12)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x13)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x14)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x15)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x16)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x17)) & 0xffL); - lsb = (lsb << 5) | (map.get(string.charAt(0x18)) & 0xffL); - - lsb = (lsb << 3) | ((map.get(string.charAt(0x19)) & 0xffL) >>> 2); + for (int i = 0; i < 12; i++) { + msb = (msb << 5) | get(string, i); + } + + msb = (msb << 4) | (get(string, 12) >>> 1); + lsb = (lsb << 5) | get(string, 12); + + for (int i = 13; i < 25; i++) { + lsb = (lsb << 5) | get(string, i); + } + + lsb = (lsb << 3) | (get(string, 25) >>> 2); return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java index 6fcf2dce..2539f4d3 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Decoder.java @@ -52,32 +52,18 @@ public UUID apply(String string) { long msb = 0; long lsb = 0; - msb = (msb << 6) | (map.get(string.charAt(0x00)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x01)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x02)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x03)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x04)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x05)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x06)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x07)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x08)) & 0xffL); - msb = (msb << 6) | (map.get(string.charAt(0x09)) & 0xffL); - - msb = (msb << 4) | ((map.get(string.charAt(0x0a)) & 0xffL) >>> 2); - - lsb = (lsb << 6) | (map.get(string.charAt(0x0a)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x0b)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x0c)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x0d)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x0e)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x0f)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x10)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x11)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x12)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x13)) & 0xffL); - lsb = (lsb << 6) | (map.get(string.charAt(0x14)) & 0xffL); - - lsb = (lsb << 2) | ((map.get(string.charAt(0x15)) & 0xffL) >>> 4); + for (int i = 0; i < 10; i++) { + msb = (msb << 6) | get(string, i); + } + + msb = (msb << 4) | (get(string, 10) >>> 2); + lsb = (lsb << 6) | get(string, 10); + + for (int i = 11; i < 21; i++) { + lsb = (lsb << 6) | get(string, i); + } + + lsb = (lsb << 2) | (get(string, 21) >>> 4); return new UUID(msb, lsb); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java index 2d0aa5d5..db28dc8e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java @@ -28,6 +28,7 @@ import java.util.function.Function; import com.github.f4b6a3.uuid.codec.base.BaseN; +import com.github.f4b6a3.uuid.exception.InvalidUuidException; import com.github.f4b6a3.uuid.util.immutable.ByteArray; /** @@ -54,4 +55,12 @@ public BaseNDecoder(BaseN base) { this.base = base; this.map = base.getMap(); } + + protected long get(String string, int i) { + final byte value = map.get(string.charAt(i)); + if (value < 0) { + throw InvalidUuidException.newInstance(string); + } + return value & 0xffL; + } } \ No newline at end of file diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java index 0cae81f7..b8217b1b 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoder.java @@ -55,16 +55,14 @@ public BaseNRemainderDecoder(BaseN base) { public UUID apply(String string) { - final char[] chars = string.toCharArray(); - long msb = 0; long lsb = 0; long rem = 0; // remainder long[] ans; // [product, overflow] - for (int i = 0; i < chars.length; i++) { - rem = (int) map.get(chars[i]); + for (int i = 0; i < base.getLength(); i++) { + rem = get(string, i); ans = multiply(lsb, multiplier, rem); lsb = ans[0]; rem = ans[1]; From 23fd52c53c45ca4e9f898076cf16ffd34509781a Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 7 Apr 2024 18:50:39 -0300 Subject: [PATCH 19/40] Optimize base-n codecs --- .../f4b6a3/uuid/codec/base/function/BaseNDecoder.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java index db28dc8e..7d8ef881 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNDecoder.java @@ -57,7 +57,13 @@ public BaseNDecoder(BaseN base) { } protected long get(String string, int i) { - final byte value = map.get(string.charAt(i)); + + final int chr = string.charAt(i); + if (chr > 255) { + throw InvalidUuidException.newInstance(string); + } + + final byte value = map.get(chr); if (value < 0) { throw InvalidUuidException.newInstance(string); } From 78b99bfaeb2d00bfee6214601dfd47db6413a661 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 7 Apr 2024 20:36:13 -0300 Subject: [PATCH 20/40] Optimize parsing --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 121 ++++++++++-------- .../github/f4b6a3/uuid/codec/StringCodec.java | 94 +++++++------- 2 files changed, 118 insertions(+), 97 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index f09c489b..7385f208 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -523,33 +523,33 @@ long getLeastSignificantBits() { static final class Parser { - private static final byte[] VALUES; + private static final byte[] MAP; static { - byte[] temp = new byte[256]; - Arrays.fill(temp, (byte) -1); - temp['0'] = 0; - temp['1'] = 1; - temp['2'] = 2; - temp['3'] = 3; - temp['4'] = 4; - temp['5'] = 5; - temp['6'] = 6; - temp['7'] = 7; - temp['8'] = 8; - temp['9'] = 9; - temp['A'] = 10; - temp['B'] = 11; - temp['C'] = 12; - temp['D'] = 13; - temp['E'] = 14; - temp['F'] = 15; - temp['a'] = 10; - temp['b'] = 11; - temp['c'] = 12; - temp['d'] = 13; - temp['e'] = 14; - temp['f'] = 15; - VALUES = temp; + byte[] mapping = new byte[256]; + Arrays.fill(mapping, (byte) -1); + mapping['0'] = 0; + mapping['1'] = 1; + mapping['2'] = 2; + mapping['3'] = 3; + mapping['4'] = 4; + mapping['5'] = 5; + mapping['6'] = 6; + mapping['7'] = 7; + mapping['8'] = 8; + mapping['9'] = 9; + mapping['A'] = 10; + mapping['B'] = 11; + mapping['C'] = 12; + mapping['D'] = 13; + mapping['E'] = 14; + mapping['F'] = 15; + mapping['a'] = 10; + mapping['b'] = 11; + mapping['c'] = 12; + mapping['d'] = 13; + mapping['e'] = 14; + mapping['f'] = 15; + MAP = mapping; } private static final int DASH_POSITION_1 = 8; @@ -557,52 +557,65 @@ static final class Parser { private static final int DASH_POSITION_3 = 18; private static final int DASH_POSITION_4 = 23; - public static GUID parse(final String str) { + public static GUID parse(final String string) { - if (str == null || str.length() != 36) { - throw newIllegalArgumentException(str); + if (string == null || string.length() != GUID.GUID_CHARS) { + throw newIllegalArgumentException(string); } - if (str.charAt(DASH_POSITION_1) != '-' || str.charAt(DASH_POSITION_2) != '-' - || str.charAt(DASH_POSITION_3) != '-' || str.charAt(DASH_POSITION_4) != '-') { - throw newIllegalArgumentException(str); - } - - final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); - final long hi2 = parseShort(str, 0x09, 0x0a, 0x0b, 0x0c) << 16 | parseShort(str, 0x0e, 0x0f, 0x10, 0x11); - final long lo1 = parseShort(str, 0x13, 0x14, 0x15, 0x16) << 16 | parseShort(str, 0x18, 0x19, 0x1a, 0x1b); - final long lo2 = parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f) << 16 | parseShort(str, 0x20, 0x21, 0x22, 0x23); + validateDashPositions(string); - return new GUID(hi1 << 32 | hi2, lo1 << 32 | lo2); - } + long msb = 0; + long lsb = 0; - private static long parseShort(final String str, final int i1, final int i2, final int i3, final int i4) { + for (int i = 0; i < 8; i++) { + msb = (msb << 4) | get(string, i); + } - final char chr1 = str.charAt(i1); - final char chr2 = str.charAt(i2); - final char chr3 = str.charAt(i3); - final char chr4 = str.charAt(i4); + for (int i = 9; i < 13; i++) { + msb = (msb << 4) | get(string, i); + } - if (chr1 > 0xff || chr2 > 0xff || chr3 > 0xff || chr4 > 0xff) { - throw newIllegalArgumentException(str); + for (int i = 14; i < 18; i++) { + msb = (msb << 4) | get(string, i); } - final int val1 = VALUES[chr1]; - final int val2 = VALUES[chr2]; - final int val3 = VALUES[chr3]; - final int val4 = VALUES[chr4]; + for (int i = 19; i < 23; i++) { + lsb = (lsb << 4) | get(string, i); + } - if (val1 == -1 || val2 == -1 || val3 == -1 || val4 == -1) { - throw newIllegalArgumentException(str); + for (int i = 24; i < 36; i++) { + lsb = (lsb << 4) | get(string, i); } - return (long) (val1 << 12 | val2 << 8 | val3 << 4 | val4); + return new GUID(msb, lsb); + } + + protected static void validateDashPositions(final String string) { + if (string.charAt(DASH_POSITION_1) != '-' || string.charAt(DASH_POSITION_2) != '-' + || string.charAt(DASH_POSITION_3) != '-' || string.charAt(DASH_POSITION_4) != '-') { + throw newIllegalArgumentException(string); + } } private static RuntimeException newIllegalArgumentException(final String str) { return new IllegalArgumentException("Invalid UUID: " + str); } + protected static long get(final String string, int i) { + + final int chr = string.charAt(i); + if (chr > 255) { + throw newIllegalArgumentException(string); + } + + final byte value = MAP[chr]; + if (value < 0) { + throw newIllegalArgumentException(string); + } + return value & 0xffL; + } + public static boolean valid(final String guid) { try { parse(guid); diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java index 8505a108..700b9e13 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java @@ -29,7 +29,6 @@ import com.github.f4b6a3.uuid.codec.base.Base16Codec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; import com.github.f4b6a3.uuid.util.UuidValidator; -import com.github.f4b6a3.uuid.util.immutable.ByteArray; import com.github.f4b6a3.uuid.util.immutable.CharArray; import com.github.f4b6a3.uuid.util.internal.JavaVersionUtil; @@ -63,7 +62,7 @@ public class StringCodec implements UuidCodec { */ public static final StringCodec INSTANCE = new StringCodec(); - private static final ByteArray MAP = Base16Codec.INSTANCE.getBase().getMap(); + private static final byte[] MAP = Base16Codec.INSTANCE.getBase().getMap().array(); private static final CharArray ALPHABET = Base16Codec.INSTANCE.getBase().getAlphabet(); private static final String URN_PREFIX = "urn:uuid:"; @@ -164,59 +163,46 @@ public String encode(UUID uuid) { public UUID decode(final String string) { if (string == null) { - throw newInvalidUuidException(string); + throw InvalidUuidException.newInstance(string); } - final String str = modifyString(string); + final String modified = modifyString(string); - if (str.length() == WITH_DASH_UUID_LENGTH) { - if (str.charAt(DASH_POSITION_1) != '-' || str.charAt(DASH_POSITION_2) != '-' - || str.charAt(DASH_POSITION_3) != '-' || str.charAt(DASH_POSITION_4) != '-') { - throw newInvalidUuidException(str); - } - final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); - final long hi2 = parseShort(str, 0x09, 0x0a, 0x0b, 0x0c) << 16 | parseShort(str, 0x0e, 0x0f, 0x10, 0x11); - final long lo1 = parseShort(str, 0x13, 0x14, 0x15, 0x16) << 16 | parseShort(str, 0x18, 0x19, 0x1a, 0x1b); - final long lo2 = parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f) << 16 | parseShort(str, 0x20, 0x21, 0x22, 0x23); - return new UUID(hi1 << 32 | hi2, lo1 << 32 | lo2); - } + if (modified.length() == WITH_DASH_UUID_LENGTH) { - if (str.length() == WITHOUT_DASH_UUID_LENGTH) { - final long hi1 = parseShort(str, 0x00, 0x01, 0x02, 0x03) << 16 | parseShort(str, 0x04, 0x05, 0x06, 0x07); - final long hi2 = parseShort(str, 0x08, 0x09, 0x0a, 0x0b) << 16 | parseShort(str, 0x0c, 0x0d, 0x0e, 0x0f); - final long lo1 = parseShort(str, 0x10, 0x11, 0x12, 0x13) << 16 | parseShort(str, 0x14, 0x15, 0x16, 0x17); - final long lo2 = parseShort(str, 0x18, 0x19, 0x1a, 0x1b) << 16 | parseShort(str, 0x1c, 0x1d, 0x1e, 0x1f); - return new UUID(hi1 << 32 | hi2, lo1 << 32 | lo2); - } + validateDashPositions(modified); - throw newInvalidUuidException(str); - } + long msb = 0; + long lsb = 0; + + for (int i = 0; i < 8; i++) { + msb = (msb << 4) | get(modified, i); + } - private static long parseShort(final String str, final int i1, final int i2, final int i3, final int i4) { + for (int i = 9; i < 13; i++) { + msb = (msb << 4) | get(modified, i); + } - final char chr1 = str.charAt(i1); - final char chr2 = str.charAt(i2); - final char chr3 = str.charAt(i3); - final char chr4 = str.charAt(i4); + for (int i = 14; i < 18; i++) { + msb = (msb << 4) | get(modified, i); + } - if (chr1 > 0xff || chr2 > 0xff || chr3 > 0xff || chr4 > 0xff) { - throw newInvalidUuidException(str); - } + for (int i = 19; i < 23; i++) { + lsb = (lsb << 4) | get(modified, i); + } - final int val1 = MAP.get(chr1); - final int val2 = MAP.get(chr2); - final int val3 = MAP.get(chr3); - final int val4 = MAP.get(chr4); + for (int i = 24; i < 36; i++) { + lsb = (lsb << 4) | get(modified, i); + } - if (val1 == -1 || val2 == -1 || val3 == -1 || val4 == -1) { - throw newInvalidUuidException(str); + return new UUID(msb, lsb); } - return (long) (val1 << 12 | val2 << 8 | val3 << 4 | val4); - } + if (modified.length() == WITHOUT_DASH_UUID_LENGTH) { + return Base16Codec.INSTANCE.decode(modified); + } - private static RuntimeException newInvalidUuidException(final String str) { - return new InvalidUuidException("Invalid UUID: " + str); + throw InvalidUuidException.newInstance(modified); } /** @@ -227,7 +213,7 @@ private static RuntimeException newInvalidUuidException(final String str) { * @param string a string * @return a substring */ - protected static String modifyString(String string) { + protected static String modifyString(final String string) { // UUID URN format: "urn:uuid:00000000-0000-0000-0000-000000000000" if (string.length() == URN_PREFIX_UUID_LENGTH && string.startsWith(URN_PREFIX)) { @@ -243,4 +229,26 @@ protected static String modifyString(String string) { return string; } + + protected static void validateDashPositions(final String string) { + if (string.charAt(DASH_POSITION_1) != '-' || string.charAt(DASH_POSITION_2) != '-' + || string.charAt(DASH_POSITION_3) != '-' || string.charAt(DASH_POSITION_4) != '-') { + throw InvalidUuidException.newInstance(string); + } + } + + protected long get(final String string, int i) { + + final int chr = string.charAt(i); + if (chr > 255) { + throw InvalidUuidException.newInstance(string); + } + + final byte value = MAP[chr]; + if (value < 0) { + throw InvalidUuidException.newInstance(string); + } + + return value & 0xffL; + } } From 67e2bf6376b56954b90416ffd8a943f54ad4eaf8 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 8 Jun 2024 21:12:07 -0300 Subject: [PATCH 21/40] Add a unique number to be XORed with the thread-local random sequence The JVM unique number tries to mitigate the fact that the thread local random is not seeded with a secure random seed by default. Their seeds are based on temporal data and predefined constants. Although the seeds are unique per JVM, they are not across JVMs. It helps to generate different sequences of numbers even if two ThreadLocalRandom are by chance instantiated with the same seed. Of course it doesn't better the output, but doesn't hurt either. --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 7385f208..0ab8dd0c 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.time.Instant; import java.util.Arrays; import java.util.Objects; @@ -208,9 +209,12 @@ public GUID(String string) { * @return a GUID */ public static GUID v1() { + final long time = gregorian(); + final long msb = (time << 32) | ((time >>> 16) & (MASK_16 << 16)) | ((time >>> 48) & MASK_12); - final long lsb = ThreadLocalRandom.current().nextLong() | MULTICAST; + final long lsb = LazyHolder.random() | MULTICAST; + return version(msb, lsb, 1); } @@ -270,9 +274,8 @@ public static GUID v3(GUID namespace, String name) { * @return a GUID */ public static GUID v4() { - ThreadLocalRandom random = ThreadLocalRandom.current(); - final long msb = random.nextLong(); - final long lsb = random.nextLong(); + final long msb = LazyHolder.random(); + final long lsb = LazyHolder.random(); return version(msb, lsb, 4); } @@ -309,9 +312,12 @@ public static GUID v5(GUID namespace, String name) { * @return a GUID */ public static GUID v6() { + final long time = gregorian(); + final long msb = ((time & ~MASK_12) << 4) | (time & MASK_12); - final long lsb = ThreadLocalRandom.current().nextLong() | MULTICAST; + final long lsb = LazyHolder.random() | MULTICAST; + return version(msb, lsb, 6); } @@ -327,10 +333,12 @@ public static GUID v6() { * @return a GUID */ public static GUID v7() { + final long time = System.currentTimeMillis(); - ThreadLocalRandom random = ThreadLocalRandom.current(); - final long msb = (time << 16) | (random.nextLong() & MASK_16); - final long lsb = random.nextLong(); + + final long msb = (time << 16) | (LazyHolder.random() & MASK_16); + final long lsb = LazyHolder.random(); + return version(msb, lsb, 7); } @@ -476,6 +484,22 @@ private static long gregorian() { return time; } + private static class LazyHolder { + + // The JVM unique number tries to mitigate the fact that the thread + // local random is not seeded with a secure random seed by default. + // Their seeds are based on temporal data and predefined constants. + // Although the seeds are unique per JVM, they are not across JVMs. + // It helps to generate different sequences of numbers even if two + // ThreadLocalRandom are by chance instantiated with the same seed. + // Of course it doesn't better the output, but doesn't hurt either. + static final long JVM_UNIQUE_NUMBER = new SecureRandom().nextLong(); + + private static long random() { + return ThreadLocalRandom.current().nextLong() ^ JVM_UNIQUE_NUMBER; + } + } + private static GUID hash(int version, String algorithm, GUID namespace, String name) { Objects.requireNonNull(name, "Null name"); From f67d3e4edd66279c19b2f83fa75e847fc4bd9054 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 8 Jun 2024 21:37:19 -0300 Subject: [PATCH 22/40] Refactor AbstRandomBasedFactory --- .../uuid/factory/AbstRandomBasedFactory.java | 68 ++++++++++++------- .../nonstandard/PrefixCombFactory.java | 2 +- .../nonstandard/ShortPrefixCombFactory.java | 2 +- .../nonstandard/ShortSuffixCombFactory.java | 2 +- .../nonstandard/SuffixCombFactory.java | 2 +- .../factory/rfc4122/RandomBasedFactory.java | 2 +- .../rfc4122/TimeOrderedEpochFactory.java | 8 +-- .../factory/AbstRandomBasedFactoryTest.java | 24 +++---- .../rfc4122/TimeOrderedEpochFactoryTest.java | 12 ---- 9 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java index 2ad2005e..5bf32dd2 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java @@ -25,6 +25,7 @@ package com.github.f4b6a3.uuid.factory; import java.security.SecureRandom; +import java.util.Objects; import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @@ -95,7 +96,7 @@ protected abstract static class Builder> { */ protected IRandom getRandom() { if (this.random == null) { - this.random = new ByteRandom(new DefaultRandomFunction()); + this.random = new SafeRandom(new DefaultRandomFunction()); } return this.random; } @@ -110,9 +111,9 @@ protected IRandom getRandom() { public B withRandom(Random random) { if (random != null) { if (random instanceof SecureRandom) { - this.random = new ByteRandom(random); + this.random = new SafeRandom(random); } else { - this.random = new LongRandom(random); + this.random = new FastRandom(random); } } return (B) this; @@ -121,11 +122,28 @@ public B withRandom(Random random) { /** * Set the random generator with a fast algorithm. * + * Use it to replace the {@link DefaultRandomFunction} with + * {@link ThreadLocalRandom}. + * * @return the generator */ @SuppressWarnings("unchecked") public B withFastRandom() { - this.random = new LongRandom(() -> ThreadLocalRandom.current().nextLong()); + this.random = new FastRandom(); + return (B) this; + } + + /** + * Set the random generator with a safe algorithm. + * + * Use it to replace the {@link DefaultRandomFunction} with + * {@link SecureRandom}. + * + * @return the generator + */ + @SuppressWarnings("unchecked") + public B withSafeRandom() { + this.random = new SafeRandom(); return (B) this; } @@ -137,7 +155,7 @@ public B withFastRandom() { */ @SuppressWarnings("unchecked") public B withRandomFunction(LongSupplier randomFunction) { - this.random = new LongRandom(randomFunction); + this.random = new FastRandom(randomFunction); return (B) this; } @@ -149,7 +167,7 @@ public B withRandomFunction(LongSupplier randomFunction) { */ @SuppressWarnings("unchecked") public B withRandomFunction(IntFunction randomFunction) { - this.random = new ByteRandom(randomFunction); + this.random = new SafeRandom(randomFunction); return (B) this; } @@ -185,15 +203,15 @@ protected static interface IRandom { /** * A long random generator. */ - protected static final class LongRandom implements IRandom { + protected static final class FastRandom implements IRandom { private final LongSupplier randomFunction; /** * Default constructor. */ - public LongRandom() { - this(newRandomFunction(null)); + public FastRandom() { + this(newFastFunction(null)); } /** @@ -201,8 +219,8 @@ public LongRandom() { * * @param random a random */ - public LongRandom(Random random) { - this(newRandomFunction(random)); + public FastRandom(Random random) { + this(newFastFunction(Objects.requireNonNull(random))); } /** @@ -210,8 +228,8 @@ public LongRandom(Random random) { * * @param randomFunction a function */ - public LongRandom(LongSupplier randomFunction) { - this.randomFunction = randomFunction != null ? randomFunction : newRandomFunction(null); + public FastRandom(LongSupplier randomFunction) { + this.randomFunction = Objects.requireNonNull(randomFunction); } @Override @@ -244,24 +262,26 @@ public byte[] nextBytes(int length) { * @param random a random * @return a function */ - protected static LongSupplier newRandomFunction(Random random) { - final Random entropy = random != null ? random : new SecureRandom(); - return entropy::nextLong; + private static LongSupplier newFastFunction(Random random) { + if (random != null) { + return () -> random.nextLong(); + } + return () -> ThreadLocalRandom.current().nextLong(); } } /** * A byte random generator. */ - protected static final class ByteRandom implements IRandom { + protected static final class SafeRandom implements IRandom { private final IntFunction randomFunction; /** * Default constructor. */ - public ByteRandom() { - this(newRandomFunction(null)); + public SafeRandom() { + this(newSafeFunction(null)); } /** @@ -269,8 +289,8 @@ public ByteRandom() { * * @param random a random */ - public ByteRandom(Random random) { - this(newRandomFunction(random)); + public SafeRandom(Random random) { + this(newSafeFunction(Objects.requireNonNull(random))); } /** @@ -278,8 +298,8 @@ public ByteRandom(Random random) { * * @param randomFunction a function */ - public ByteRandom(IntFunction randomFunction) { - this.randomFunction = randomFunction != null ? randomFunction : newRandomFunction(null); + public SafeRandom(IntFunction randomFunction) { + this.randomFunction = Objects.requireNonNull(randomFunction); } @Override @@ -299,7 +319,7 @@ public byte[] nextBytes(int length) { * @param random a random * @return a function */ - protected static IntFunction newRandomFunction(Random random) { + private static IntFunction newSafeFunction(Random random) { final Random entropy = random != null ? random : new SecureRandom(); return (final int length) -> { final byte[] bytes = new byte[length]; diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java index 14ccad10..de0d4e28 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java @@ -156,7 +156,7 @@ public UUID create() { lock.lock(); try { final long time = timeFunction.getAsLong(); - if (this.random instanceof ByteRandom) { + if (this.random instanceof SafeRandom) { final byte[] bytes = this.random.nextBytes(10); final long long1 = ByteUtil.toNumber(bytes, 0, 2); final long long2 = ByteUtil.toNumber(bytes, 2, 10); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java index da20a835..3649a73f 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java @@ -197,7 +197,7 @@ public UUID create() { lock.lock(); try { final long time = timeFunction.getAsLong() / interval; - if (this.random instanceof ByteRandom) { + if (this.random instanceof SafeRandom) { final byte[] bytes = this.random.nextBytes(14); final long long1 = ByteUtil.toNumber(bytes, 0, 6); final long long2 = ByteUtil.toNumber(bytes, 6, 14); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java index fb9fd98d..5611d2cc 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java @@ -197,7 +197,7 @@ public UUID create() { lock.lock(); try { final long time = timeFunction.getAsLong() / interval; - if (this.random instanceof ByteRandom) { + if (this.random instanceof SafeRandom) { final byte[] bytes = this.random.nextBytes(14); final long long1 = ByteUtil.toNumber(bytes, 0, 8); final long long2 = ByteUtil.toNumber(bytes, 8, 14); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java index b6fd2a48..70ad3d86 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java @@ -159,7 +159,7 @@ public UUID create() { lock.lock(); try { final long time = timeFunction.getAsLong(); - if (this.random instanceof ByteRandom) { + if (this.random instanceof SafeRandom) { final byte[] bytes = this.random.nextBytes(10); final long long1 = ByteUtil.toNumber(bytes, 0, 8); final long long2 = ByteUtil.toNumber(bytes, 8, 10); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java index d0a0846c..d74ebdb1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java @@ -117,7 +117,7 @@ public static Builder builder() { public UUID create() { lock.lock(); try { - if (this.random instanceof ByteRandom) { + if (this.random instanceof SafeRandom) { final byte[] bytes = this.random.nextBytes(16); final long msb = ByteUtil.toNumber(bytes, 0, 8); final long lsb = ByteUtil.toNumber(bytes, 8, 16); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java index 5387a064..cf22ac49 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java @@ -328,7 +328,7 @@ long time() { } void reset(final long time) { - if (random instanceof ByteRandom) { + if (random instanceof SafeRandom) { final byte[] bytes = random.nextBytes(10); this.msb = (time << 16) | (ByteUtil.toNumber(bytes, 0, 2)); this.lsb = ByteUtil.toNumber(bytes, 2, 10); @@ -358,7 +358,7 @@ void increment() { } // then randomize the lower 48 bits - if (random instanceof ByteRandom) { + if (random instanceof SafeRandom) { final byte[] bytes = random.nextBytes(6); this.lsb |= ByteUtil.toNumber(bytes); } else { @@ -409,7 +409,7 @@ void increment() { private LongSupplier customPlusNFunction(IRandom random, Long incrementMax) { if (incrementMax == INCREMENT_MAX_DEFAULT) { - if (random instanceof ByteRandom) { + if (random instanceof SafeRandom) { return () -> { // return n, where 1 <= n <= 2^32 final byte[] bytes = random.nextBytes(4); @@ -423,7 +423,7 @@ private LongSupplier customPlusNFunction(IRandom random, Long incrementMax) { } } else { final long positive = 0x7fffffffffffffffL; - if (random instanceof ByteRandom) { + if (random instanceof SafeRandom) { // the minimum number of bits and bytes for incrementMax final int bits = (int) Math.ceil(Math.log(incrementMax) / Math.log(2)); final int size = ((bits - 1) / Byte.SIZE) + 1; diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java index f17024df..a179a476 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java @@ -30,7 +30,7 @@ public void testByteRandomNextLong() { byte[] bytes = new byte[Long.BYTES]; (new Random()).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.ByteRandom((x) -> bytes); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> bytes); assertEquals(number, random.nextLong()); } @@ -44,7 +44,7 @@ public void testByteRandomNextLong() { ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.ByteRandom((x) -> { + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> { byte[] octects = new byte[x]; buffer1.get(octects); return octects; @@ -62,7 +62,7 @@ public void testByteRandomNextBytes() { for (int i = 0; i < 10; i++) { byte[] bytes = new byte[Long.BYTES]; (new Random()).nextBytes(bytes); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.ByteRandom((x) -> bytes); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> bytes); assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES))); } @@ -76,7 +76,7 @@ public void testByteRandomNextBytes() { ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.ByteRandom((x) -> { + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> { byte[] octects = new byte[x]; buffer1.get(octects); return octects; @@ -97,7 +97,7 @@ public void testLogRandomNextLong() { byte[] bytes = new byte[Long.BYTES]; (new Random()).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> number); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> number); assertEquals(number, random.nextLong()); } @@ -111,7 +111,7 @@ public void testLogRandomNextLong() { ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> buffer1.getLong()); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> buffer1.getLong()); for (int j = 0; j < ints; j++) { assertEquals(buffer2.getLong(), random.nextLong()); @@ -127,7 +127,7 @@ public void testLogRandomNextBytes() { byte[] bytes = new byte[Long.BYTES]; (new Random()).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> number); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> number); assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES))); } @@ -141,7 +141,7 @@ public void testLogRandomNextBytes() { ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> buffer1.getLong()); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> buffer1.getLong()); for (int j = 0; j < ints; j++) { byte[] octects = new byte[Long.BYTES]; @@ -156,7 +156,7 @@ public void testLongRandom() { { long nextLong = 0x1122334455667788L; - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> nextLong); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> nextLong); byte[] bytes = random.nextBytes(Long.BYTES); ByteBuffer buffer = ByteBuffer.wrap(bytes); assertEquals(nextLong, buffer.getLong()); @@ -164,7 +164,7 @@ public void testLongRandom() { { long nextLong = ThreadLocalRandom.current().nextLong(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom(() -> nextLong); + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> nextLong); byte[] bytes = random.nextBytes(Long.BYTES); ByteBuffer buffer = ByteBuffer.wrap(bytes); assertEquals(nextLong, buffer.getLong()); @@ -183,7 +183,7 @@ public void testLongRandom() { ByteBuffer buffer2 = ByteBuffer.allocate(octects); AtomicInteger x = new AtomicInteger(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom( + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom( () -> nextLong[x.getAndIncrement()]); for (int i = 0; i < nextLong.length; i++) { @@ -210,7 +210,7 @@ public void testLongRandom() { ByteBuffer buffer2 = ByteBuffer.allocate(octects); AtomicInteger x = new AtomicInteger(); - AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.LongRandom( + AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom( () -> nextLong[x.getAndIncrement()]); for (int i = 0; i < nextLong.length; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java index 6bb10741..cafbf5c5 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java @@ -88,18 +88,6 @@ public void testWithRandomNull() { assertNotNull(factory.create()); } - @Test - public void testWithRandomFunctionNull() { - { - TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory((LongSupplier) null); - assertNotNull(factory.create()); - } - { - TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory((IntFunction) null); - assertNotNull(factory.create()); - } - } - @Test public void testGetTimeOrderedEpoch() { From 9488455ddc88d1ebe36446c8fcbee10d2674c9be Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 8 Jun 2024 22:12:23 -0300 Subject: [PATCH 23/40] Refactor UuidCreator lazy holders --- .../com/github/f4b6a3/uuid/UuidCreator.java | 118 ++++++++---------- .../github/f4b6a3/uuid/util/UuidUtilTest.java | 1 + 2 files changed, 54 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index 2e158864..1292012d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -1208,69 +1208,30 @@ public static UUID getShortSuffixComb() { // Lazy holders // *************************************** - private static final Proxy UUID1 = new Proxy(Suppliers.UUID1); - private static final Proxy UUID1_MAC = new Proxy(Suppliers.UUID1_MAC); - private static final Proxy UUID1_HASH = new Proxy(Suppliers.UUID1_HASH); - private static final Proxy UUID1_RANDOM = new Proxy(Suppliers.UUID1_RANDOM); - private static final Proxy UUID2 = new Proxy(Suppliers.UUID2); - private static final Proxy UUID2_MAC = new Proxy(Suppliers.UUID2_MAC); - private static final Proxy UUID2_HASH = new Proxy(Suppliers.UUID2_HASH); - private static final Proxy UUID2_RANDOM = new Proxy(Suppliers.UUID2_RANDOM); - private static final Proxy UUID3 = new Proxy(Suppliers.UUID3); - private static final Proxy UUID4 = new Proxy(Suppliers.UUID4); - private static final Proxy UUID4_FAST = new Proxy(Suppliers.UUID4_FAST); - private static final Proxy UUID5 = new Proxy(Suppliers.UUID5); - private static final Proxy UUID6 = new Proxy(Suppliers.UUID6); - private static final Proxy UUID6_MAC = new Proxy(Suppliers.UUID6_MAC); - private static final Proxy UUID6_HASH = new Proxy(Suppliers.UUID6_HASH); - private static final Proxy UUID6_RANDOM = new Proxy(Suppliers.UUID6_RANDOM); - private static final Proxy UUID7 = new Proxy(Suppliers.UUID7); - private static final Proxy UUID7_FAST = new Proxy(Suppliers.UUID7_FAST); - private static final Proxy UUID7_PLUS_1 = new Proxy(Suppliers.UUID7_PLUS_1); - private static final Proxy UUID7_PLUS_N = new Proxy(Suppliers.UUID7_PLUS_N); - private static final Proxy COMB_PREFIX = new Proxy(Suppliers.COMB_PREFIX); - private static final Proxy COMB_SUFFIX = new Proxy(Suppliers.COMB_SUFFIX); - private static final Proxy COMB_SHORT_PREFIX = new Proxy(Suppliers.COMB_SHORT_PREFIX); - private static final Proxy COMB_SHORT_SUFFIX = new Proxy(Suppliers.COMB_SHORT_SUFFIX); - - private static enum Suppliers { - - UUID1(TimeBasedFactory::new), // - UUID1_MAC(() -> TimeBasedFactory.builder().withMacNodeId().build()), // - UUID1_HASH(() -> TimeBasedFactory.builder().withHashNodeId().build()), // - UUID1_RANDOM(() -> TimeBasedFactory.builder().withRandomNodeId().build()), // - UUID2(DceSecurityFactory::new), // - UUID2_MAC(() -> DceSecurityFactory.builder().withMacNodeId().build()), // - UUID2_HASH(() -> DceSecurityFactory.builder().withHashNodeId().build()), // - UUID2_RANDOM(() -> DceSecurityFactory.builder().withRandomNodeId().build()), // - UUID3(NameBasedMd5Factory::new), // - UUID4(RandomBasedFactory::new), // - UUID4_FAST(() -> RandomBasedFactory.builder().withFastRandom().build()), // - UUID5(NameBasedSha1Factory::new), // - UUID6(TimeOrderedFactory::new), // - UUID6_MAC(() -> TimeOrderedFactory.builder().withMacNodeId().build()), // - UUID6_HASH(() -> TimeOrderedFactory.builder().withHashNodeId().build()), // - UUID6_RANDOM(() -> TimeOrderedFactory.builder().withRandomNodeId().build()), // - UUID7(TimeOrderedEpochFactory::new), // - UUID7_FAST(() -> TimeOrderedEpochFactory.builder().withFastRandom().build()), // - UUID7_PLUS_1(() -> TimeOrderedEpochFactory.builder().withIncrementPlus1().build()), // - UUID7_PLUS_N(() -> TimeOrderedEpochFactory.builder().withIncrementPlusN().build()), // - COMB_PREFIX(PrefixCombFactory::new), // - COMB_SUFFIX(SuffixCombFactory::new), // - COMB_SHORT_PREFIX(ShortPrefixCombFactory::new), // - COMB_SHORT_SUFFIX(ShortSuffixCombFactory::new), // - ; - - private final Supplier supplier; - - Suppliers(Supplier supplier) { - this.supplier = supplier; - } - - public Supplier getValue() { - return this.supplier; - } - } + private static final Proxy UUID1 = new Proxy(Proxy.UUID1); + private static final Proxy UUID1_MAC = new Proxy(Proxy.UUID1_MAC); + private static final Proxy UUID1_HASH = new Proxy(Proxy.UUID1_HASH); + private static final Proxy UUID1_RANDOM = new Proxy(Proxy.UUID1_RANDOM); + private static final Proxy UUID2 = new Proxy(Proxy.UUID2); + private static final Proxy UUID2_MAC = new Proxy(Proxy.UUID2_MAC); + private static final Proxy UUID2_HASH = new Proxy(Proxy.UUID2_HASH); + private static final Proxy UUID2_RANDOM = new Proxy(Proxy.UUID2_RANDOM); + private static final Proxy UUID3 = new Proxy(Proxy.UUID3); + private static final Proxy UUID4 = new Proxy(Proxy.UUID4); + private static final Proxy UUID4_FAST = new Proxy(Proxy.UUID4_FAST); + private static final Proxy UUID5 = new Proxy(Proxy.UUID5); + private static final Proxy UUID6 = new Proxy(Proxy.UUID6); + private static final Proxy UUID6_MAC = new Proxy(Proxy.UUID6_MAC); + private static final Proxy UUID6_HASH = new Proxy(Proxy.UUID6_HASH); + private static final Proxy UUID6_RANDOM = new Proxy(Proxy.UUID6_RANDOM); + private static final Proxy UUID7 = new Proxy(Proxy.UUID7); + private static final Proxy UUID7_FAST = new Proxy(Proxy.UUID7_FAST); + private static final Proxy UUID7_PLUS_1 = new Proxy(Proxy.UUID7_PLUS_1); + private static final Proxy UUID7_PLUS_N = new Proxy(Proxy.UUID7_PLUS_N); + private static final Proxy COMB_PREFIX = new Proxy(Proxy.COMB_PREFIX); + private static final Proxy COMB_SUFFIX = new Proxy(Proxy.COMB_SUFFIX); + private static final Proxy COMB_SHORT_PREFIX = new Proxy(Proxy.COMB_SHORT_PREFIX); + private static final Proxy COMB_SHORT_SUFFIX = new Proxy(Proxy.COMB_SHORT_SUFFIX); private static class Proxy extends UuidFactory { @@ -1278,8 +1239,35 @@ private static class Proxy extends UuidFactory { private Supplier supplier; private static final ReentrantLock lock = new ReentrantLock(); - public Proxy(Suppliers supplier) { - this.supplier = (Supplier) supplier.getValue(); + // @formatter:off + static final Supplier UUID1 = TimeBasedFactory::new; + static final Supplier UUID1_MAC = () -> TimeBasedFactory.builder().withMacNodeId().build(); + static final Supplier UUID1_HASH = () -> TimeBasedFactory.builder().withHashNodeId().build(); + static final Supplier UUID1_RANDOM = () -> TimeBasedFactory.builder().withRandomNodeId().build(); + static final Supplier UUID2 = DceSecurityFactory::new; + static final Supplier UUID2_MAC = () -> DceSecurityFactory.builder().withMacNodeId().build(); + static final Supplier UUID2_HASH = () -> DceSecurityFactory.builder().withHashNodeId().build(); + static final Supplier UUID2_RANDOM = () -> DceSecurityFactory.builder().withRandomNodeId().build(); + static final Supplier UUID3 = NameBasedMd5Factory::new; + static final Supplier UUID4 = RandomBasedFactory::new; + static final Supplier UUID4_FAST = () -> RandomBasedFactory.builder().withFastRandom().build(); + static final Supplier UUID5 = NameBasedSha1Factory::new; + static final Supplier UUID6 = TimeOrderedFactory::new; + static final Supplier UUID6_MAC = () -> TimeOrderedFactory.builder().withMacNodeId().build(); + static final Supplier UUID6_HASH = () -> TimeOrderedFactory.builder().withHashNodeId().build(); + static final Supplier UUID6_RANDOM = () -> TimeOrderedFactory.builder().withRandomNodeId().build(); + static final Supplier UUID7 = TimeOrderedEpochFactory::new; + static final Supplier UUID7_FAST = () -> TimeOrderedEpochFactory.builder().withFastRandom().build(); + static final Supplier UUID7_PLUS_1 = () -> TimeOrderedEpochFactory.builder().withIncrementPlus1().build(); + static final Supplier UUID7_PLUS_N = () -> TimeOrderedEpochFactory.builder().withIncrementPlusN().build(); + static final Supplier COMB_PREFIX = PrefixCombFactory::new; + static final Supplier COMB_SUFFIX = SuffixCombFactory::new; + static final Supplier COMB_SHORT_PREFIX = ShortPrefixCombFactory::new; + static final Supplier COMB_SHORT_SUFFIX = ShortSuffixCombFactory::new; + // @formatter:on + + public Proxy(Supplier supplier) { + this.supplier = supplier; } private UuidFactory get() { diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java index 1c66a09c..fd3b6c47 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java @@ -89,6 +89,7 @@ public void testGetTimestamp() { UUID uuid1 = factory1.create(); long gregTimestamp1 = getTimestamp(uuid1); assertEquals(gregTimestamp, gregTimestamp1); + assertEquals(gregTimestamp, uuid1.timestamp()); TimeOrderedFactory factory2 = TimeOrderedFactory.builder().withTimeFunction(() -> unixTimestamp).build(); UUID uuid2 = factory2.create(); From 226830b1582ea6279e3c13587b717015cf345dcc Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 8 Jun 2024 23:29:59 -0300 Subject: [PATCH 24/40] Modify AbstRandomBasedFactory Remove `Builder.withRandomFunction(IntFunction`. There are too many "with" options already. --- .../uuid/factory/AbstRandomBasedFactory.java | 38 +++++++------------ .../nonstandard/PrefixCombFactory.java | 21 ---------- .../nonstandard/ShortPrefixCombFactory.java | 21 ---------- .../nonstandard/ShortSuffixCombFactory.java | 21 ---------- .../nonstandard/SuffixCombFactory.java | 21 ---------- .../factory/rfc4122/RandomBasedFactory.java | 10 ----- .../rfc4122/TimeOrderedEpochFactory.java | 21 ---------- .../nonstandard/PrefixCombFactoryTest.java | 8 +--- .../ShortPrefixCombFactoryTest.java | 8 +--- .../ShortSuffixCombFactoryTest.java | 8 +--- .../nonstandard/SuffixCombFactoryTest.java | 8 +--- .../rfc4122/RandomBasedFactoryTest.java | 8 +--- .../rfc4122/TimeOrderedEpochFactoryTest.java | 20 ++-------- 13 files changed, 26 insertions(+), 187 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java index 5bf32dd2..3c7ae502 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactory.java @@ -101,24 +101,6 @@ protected IRandom getRandom() { return this.random; } - /** - * Set the random generator. - * - * @param random a random - * @return the builder - */ - @SuppressWarnings("unchecked") - public B withRandom(Random random) { - if (random != null) { - if (random instanceof SecureRandom) { - this.random = new SafeRandom(random); - } else { - this.random = new FastRandom(random); - } - } - return (B) this; - } - /** * Set the random generator with a fast algorithm. * @@ -148,26 +130,32 @@ public B withSafeRandom() { } /** - * Set a random function which returns random numbers. + * Set the random generator. * - * @param randomFunction a function + * @param random a random * @return the builder */ @SuppressWarnings("unchecked") - public B withRandomFunction(LongSupplier randomFunction) { - this.random = new FastRandom(randomFunction); + public B withRandom(Random random) { + if (random != null) { + if (random instanceof SecureRandom) { + this.random = new SafeRandom(random); + } else { + this.random = new FastRandom(random); + } + } return (B) this; } /** - * Set a random function which returns random arrays of bytes. + * Set a random function which returns random numbers. * * @param randomFunction a function * @return the builder */ @SuppressWarnings("unchecked") - public B withRandomFunction(IntFunction randomFunction) { - this.random = new SafeRandom(randomFunction); + public B withRandomFunction(LongSupplier randomFunction) { + this.random = new FastRandom(randomFunction); return (B) this; } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java index de0d4e28..5f4db3af 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactory.java @@ -27,7 +27,6 @@ import java.time.Clock; import java.util.Random; import java.util.UUID; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -92,15 +91,6 @@ public PrefixCombFactory(LongSupplier randomFunction) { this(builder().withRandomFunction(randomFunction)); } - /** - * Constructor with a function which returns random arrays of bytes. - * - * @param randomFunction a function - */ - public PrefixCombFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - /** * Constructor with a function which a function which return random numbers and * a clock. @@ -112,17 +102,6 @@ public PrefixCombFactory(LongSupplier randomFunction, Clock clock) { this(builder().withRandomFunction(randomFunction).withClock(clock)); } - /** - * Constructor with a function which a function which returns random arrays of - * bytes and a clock. - * - * @param randomFunction a function - * @param clock a clock - */ - public PrefixCombFactory(IntFunction randomFunction, Clock clock) { - this(builder().withRandomFunction(randomFunction).withClock(clock)); - } - private PrefixCombFactory(Builder builder) { super(UuidVersion.VERSION_RANDOM_BASED, builder); } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java index 3649a73f..2dc9b9a6 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactory.java @@ -27,7 +27,6 @@ import java.time.Clock; import java.util.Random; import java.util.UUID; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -106,15 +105,6 @@ public ShortPrefixCombFactory(LongSupplier randomFunction) { this(builder().withRandomFunction(randomFunction)); } - /** - * Constructor with a function which returns random arrays of bytes. - * - * @param randomFunction a function - */ - public ShortPrefixCombFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - /** * Constructor with a function which a function which return random numbers and * a clock. @@ -126,17 +116,6 @@ public ShortPrefixCombFactory(LongSupplier randomFunction, Clock clock) { this(builder().withRandomFunction(randomFunction).withClock(clock)); } - /** - * Constructor with a function which a function which returns random arrays of - * bytes and a clock. - * - * @param randomFunction a function - * @param clock a clock - */ - public ShortPrefixCombFactory(IntFunction randomFunction, Clock clock) { - this(builder().withRandomFunction(randomFunction).withClock(clock)); - } - private ShortPrefixCombFactory(Builder builder) { super(UuidVersion.VERSION_RANDOM_BASED, builder); this.interval = builder.getInterval(); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java index 5611d2cc..7f4112c2 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactory.java @@ -27,7 +27,6 @@ import java.time.Clock; import java.util.Random; import java.util.UUID; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -106,15 +105,6 @@ public ShortSuffixCombFactory(LongSupplier randomFunction) { this(builder().withRandomFunction(randomFunction)); } - /** - * Constructor with a function which returns random arrays of bytes. - * - * @param randomFunction a function - */ - public ShortSuffixCombFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - /** * Constructor with a function which a function which return random numbers and * a clock. @@ -126,17 +116,6 @@ public ShortSuffixCombFactory(LongSupplier randomFunction, Clock clock) { this(builder().withRandomFunction(randomFunction).withClock(clock)); } - /** - * Constructor with a function which a function which returns random arrays of - * bytes and a clock. - * - * @param randomFunction a function - * @param clock a clock - */ - public ShortSuffixCombFactory(IntFunction randomFunction, Clock clock) { - this(builder().withRandomFunction(randomFunction).withClock(clock)); - } - private ShortSuffixCombFactory(Builder builder) { super(UuidVersion.VERSION_RANDOM_BASED, builder); this.interval = builder.getInterval(); diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java index 70ad3d86..2b72b23d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactory.java @@ -27,7 +27,6 @@ import java.time.Clock; import java.util.Random; import java.util.UUID; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -95,15 +94,6 @@ public SuffixCombFactory(LongSupplier randomFunction) { this(builder().withRandomFunction(randomFunction)); } - /** - * Constructor with a function which returns random arrays of bytes. - * - * @param randomFunction a function - */ - public SuffixCombFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - /** * Constructor with a function which a function which return random numbers and * a clock. @@ -115,17 +105,6 @@ public SuffixCombFactory(LongSupplier randomFunction, Clock clock) { this(builder().withRandomFunction(randomFunction).withClock(clock)); } - /** - * Constructor with a function which a function which returns random arrays of - * bytes and a clock. - * - * @param randomFunction a function - * @param clock a clock - */ - public SuffixCombFactory(IntFunction randomFunction, Clock clock) { - this(builder().withRandomFunction(randomFunction).withClock(clock)); - } - private SuffixCombFactory(Builder builder) { super(UuidVersion.VERSION_RANDOM_BASED, builder); } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java index d74ebdb1..ec95c336 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactory.java @@ -26,7 +26,6 @@ import java.util.Random; import java.util.UUID; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -63,15 +62,6 @@ public RandomBasedFactory(LongSupplier randomSupplier) { this(builder().withRandomFunction(randomSupplier)); } - /** - * Constructor with a function which returns a byte array. - * - * @param randomFunction a function - */ - public RandomBasedFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - private RandomBasedFactory(Builder builder) { super(UuidVersion.VERSION_RANDOM_BASED, builder); } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java index cf22ac49..47a86110 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactory.java @@ -28,7 +28,6 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.IntFunction; import java.util.function.LongSupplier; import java.util.function.Supplier; @@ -135,15 +134,6 @@ public TimeOrderedEpochFactory(LongSupplier randomFunction) { this(builder().withRandomFunction(randomFunction)); } - /** - * Constructor with a function which returns random arrays of bytes. - * - * @param randomFunction a function - */ - public TimeOrderedEpochFactory(IntFunction randomFunction) { - this(builder().withRandomFunction(randomFunction)); - } - /** * Constructor with a function which a function which return random numbers and * a clock. @@ -155,17 +145,6 @@ public TimeOrderedEpochFactory(LongSupplier randomFunction, Clock clock) { this(builder().withRandomFunction(randomFunction).withClock(clock)); } - /** - * Constructor with a function which a function which returns random arrays of - * bytes and a clock. - * - * @param randomFunction a function - * @param clock a clock - */ - public TimeOrderedEpochFactory(IntFunction randomFunction, Clock clock) { - this(builder().withRandomFunction(randomFunction).withClock(clock)); - } - private TimeOrderedEpochFactory(Builder builder) { super(UuidVersion.VERSION_TIME_ORDERED_EPOCH, builder); diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java index 978f71df..c9c65524 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java @@ -4,7 +4,6 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import com.github.f4b6a3.uuid.util.CombUtil; import com.github.f4b6a3.uuid.util.UuidTime; @@ -18,6 +17,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.LongSupplier; public class PrefixCombFactoryTest extends UuidFactoryTest { @@ -104,11 +104,7 @@ public void testGetPrefixCombWithRandom() { public void testGetPrefixCombWithRandomFunction() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); PrefixCombFactory factory = new PrefixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java index 0c24d9f9..db925fa1 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java @@ -4,7 +4,6 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -13,6 +12,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.LongSupplier; public class ShortPrefixCombFactoryTest extends UuidFactoryTest { @@ -108,11 +108,7 @@ public void testGetShortPrefixCombWithRandom() { public void testGetShortPrefixCombWithRandomFunction() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); ShortPrefixCombFactory factory = new ShortPrefixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java index 6481cb9c..a2b50d9c 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java @@ -4,7 +4,6 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -14,6 +13,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.LongSupplier; public class ShortSuffixCombFactoryTest extends UuidFactoryTest { @@ -109,11 +109,7 @@ public void testGetShortSuffixCombWithRandom() { public void testGetShortSuffixCombWithRandomFunction() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); ShortSuffixCombFactory factory = new ShortSuffixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java index 99a5be21..41b427af 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java @@ -4,7 +4,6 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import com.github.f4b6a3.uuid.util.CombUtil; import com.github.f4b6a3.uuid.util.UuidTime; @@ -18,6 +17,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.LongSupplier; public class SuffixCombFactoryTest extends UuidFactoryTest { @@ -103,11 +103,7 @@ public void testGetSuffixCombWithRandom() { public void testGetSuffixCombWithRandomFunction() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); SuffixCombFactory factory = new SuffixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java index cc7a4c0f..0f5a4290 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java @@ -5,13 +5,13 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.enums.UuidVersion; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import static org.junit.Assert.assertEquals; import java.util.Random; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.LongSupplier; public class RandomBasedFactoryTest extends UuidFactoryTest { @@ -63,11 +63,7 @@ public void testGetRandomBasedWithRandom() { public void testGetRandomBasedWithRandomFunction() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); RandomBasedFactory factory = new RandomBasedFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java index cafbf5c5..fc2d2668 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java @@ -5,7 +5,6 @@ import com.github.f4b6a3.uuid.UuidCreator; import com.github.f4b6a3.uuid.factory.UuidFactoryTest; -import com.github.f4b6a3.uuid.factory.function.RandomFunction; import com.github.f4b6a3.uuid.util.UuidTime; import com.github.f4b6a3.uuid.util.UuidUtil; @@ -23,7 +22,6 @@ import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; -import java.util.function.IntFunction; import java.util.function.LongSupplier; public class TimeOrderedEpochFactoryTest extends UuidFactoryTest { @@ -57,11 +55,7 @@ public void testWithRandomFunction() { assertNotNull(factory.create()); } { - IntFunction function = (length) -> { - byte[] bytes = new byte[length]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier function = () -> ThreadLocalRandom.current().nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function); assertNotNull(factory.create()); } @@ -72,11 +66,7 @@ public void testWithRandomFunction() { assertNotNull(factory.create()); } { - IntFunction function = (length) -> { - byte[] bytes = new byte[length]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier function = () -> ThreadLocalRandom.current().nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function, Clock.systemDefaultZone()); assertNotNull(factory.create()); } @@ -291,11 +281,7 @@ public void testGetTimeOrderedEpochWithRandom() { @Test public void testGetTimeOrderedEpochWithRandomFunction() { - RandomFunction randomFunction = x -> { - final byte[] bytes = new byte[x]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - }; + LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); TimeOrderedEpochFactory factory; From ece6a06af822c85e42d4d6e18243e08c54a00b09 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 9 Jun 2024 00:57:02 -0300 Subject: [PATCH 25/40] Refactor ClockSeqFunction --- .../factory/function/ClockSeqFunction.java | 159 +---------------- .../impl/DefaultClockSeqFunction.java | 166 +++++++++++++++++- .../com/github/f4b6a3/uuid/TestSuite.java | 2 +- .../function/{ => impl}/ClockSeqPoolTest.java | 4 +- .../impl/DefaultClockSeqFunctionTest.java | 8 +- 5 files changed, 168 insertions(+), 171 deletions(-) rename src/test/java/com/github/f4b6a3/uuid/factory/function/{ => impl}/ClockSeqPoolTest.java (96%) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java index ead195bc..1e6158dd 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/ClockSeqFunction.java @@ -51,7 +51,7 @@ public interface ClockSeqFunction extends LongUnaryOperator { * @return a number in the range 0 to 16383 (2^14-1) */ public static long getRandom() { - return toExpectedRange(RandomUtil.nextLong()); + return toExpectedRange(RandomUtil.newSecureRandom().nextLong()); } /** @@ -66,161 +66,4 @@ public static long getRandom() { public static long toExpectedRange(final long clockseq) { return clockseq & 0x0000000000003fffL; } - - /** - * Nested class that manages a pool of 16384 clock sequence values. - *

- * The pool is implemented as an array of 2048 bytes (16384 bits). Each bit of - * the array corresponds to a clock sequence value. - *

- * It is used to avoid that two time-based factories use the same clock sequence - * at same time in a class loader. - */ - public static final class ClockSeqPool { - - private final byte[] pool = new byte[2048]; - private static final int POOL_SIZE = 16384; // 2^14 = 16384 - - /** - * The minimum pool size, which is zero. - */ - public static final int POOL_MIN = 0x00000000; - - /** - * The maximum pool size, which is 16383 (2^14-1). - */ - public static final int POOL_MAX = 0x00003fff; // 2^14-1 = 16383 - - /** - * Take a value from the pool. - *

- * If the value to be taken is already in use, it is incremented until a free - * value is found and returned. - *

- * In the case that all pool values are in use, the pool is cleared and the last - * incremented value is returned. - *

- * It does nothing to negative arguments. - * - * @param take value to be taken from the pool - * @return the value to be borrowed if not used - */ - public synchronized int take(final int take) { - int value = take; - for (int i = 0; i < POOL_SIZE; i++) { - if (setBit(value)) { - return value; - } - value = ++value % POOL_SIZE; - } - clearPool(); - setBit(value); - return value; - } - - /** - * Take a random value from the pool. - * - * @return the random value to be borrowed if not used - */ - public synchronized int random() { - // Choose a random number between 0 and 16383 - int random = (RandomUtil.nextInt() & 0x7fffffff) % POOL_SIZE; - return this.take(random); - } - - /** - * Set a bit from the byte array that represents the pool. - *

- * This operation corresponds to setting a value as used. - *

- * It returns false if the value is not free. - *

- * It does nothing to negative arguments. - * - * @param value the value to be taken from the pool - * @return true if success - */ - private synchronized boolean setBit(int value) { - - if (value < 0) { - return false; - } - - final int byteIndex = value / 8; - final int bitIndex = value % 8; - - final int mask = (0x00000001 << bitIndex); - final boolean clear = (pool[byteIndex] & mask) == 0; - - if (clear) { - pool[byteIndex] = (byte) (pool[byteIndex] | mask); - return true; - } - - return false; - } - - /** - * Check if a value is used out of the pool. - * - * @param value a value to be checked in the pool - * @return true if the value is used - */ - public synchronized boolean isUsed(int value) { - - final int byteIndex = value / 8; - final int bitIndex = value % 8; - - final int mask = (0x00000001 << bitIndex); - boolean clear = (pool[byteIndex] & mask) == 0; - - return !clear; - } - - /** - * Check if a value is free in the pool. - * - * @param value a value to be checked in the pool - * @return true if the value is free - */ - public synchronized boolean isFree(int value) { - return !this.isUsed(value); - } - - /** - * Count the used values out of the pool - * - * @return the count of used values - */ - public synchronized int countUsed() { - int counter = 0; - for (int i = 0; i < POOL_SIZE; i++) { - if (this.isUsed(i)) { - counter++; - } - } - return counter; - } - - /** - * Count the free values in the pool. - * - * @return the count of free values - */ - public synchronized int countFree() { - return POOL_SIZE - this.countUsed(); - } - - /** - * Clear all bits of the byte array that represents the pool. - *

- * This corresponds to marking all pool values as free - */ - public synchronized void clearPool() { - for (int i = 0; i < pool.length; i++) { - pool[i] = 0; - } - } - } } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java index f43a39d6..37656649 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunction.java @@ -24,9 +24,7 @@ package com.github.f4b6a3.uuid.factory.function.impl; -import static com.github.f4b6a3.uuid.factory.function.ClockSeqFunction.ClockSeqPool.POOL_MIN; -import static com.github.f4b6a3.uuid.factory.function.ClockSeqFunction.ClockSeqPool.POOL_MAX; - +import java.util.SplittableRandom; import java.util.concurrent.atomic.AtomicInteger; import com.github.f4b6a3.uuid.factory.function.ClockSeqFunction; @@ -35,7 +33,6 @@ * Function that returns a clock sequence. * * @see ClockSeqFunction - * @see ClockSeqFunction.ClockSeqPool */ public final class DefaultClockSeqFunction implements ClockSeqFunction { @@ -71,9 +68,166 @@ public long applyAsLong(final long timestamp) { * @return a number */ public int next() { - if (this.sequence.incrementAndGet() > POOL_MAX) { - this.sequence.set(POOL_MIN); + if (this.sequence.incrementAndGet() > ClockSeqPool.POOL_MAX) { + this.sequence.set(ClockSeqPool.POOL_MIN); } return this.sequence.updateAndGet(POOL::take); } + + /** + * Nested class that manages a pool of 16384 clock sequence values. + *

+ * The pool is implemented as an array of 2048 bytes (16384 bits). Each bit of + * the array corresponds to a clock sequence value. + *

+ * It is used to avoid that two time-based factories use the same clock sequence + * at same time in a class loader. + */ + static final class ClockSeqPool { + + private final byte[] pool = new byte[2048]; + private static final int POOL_SIZE = 16384; // 2^14 = 16384 + + /** + * The minimum pool size, which is zero. + */ + public static final int POOL_MIN = 0x00000000; + + /** + * The maximum pool size, which is 16383 (2^14-1). + */ + public static final int POOL_MAX = 0x00003fff; // 2^14-1 = 16383 + + /** + * Take a value from the pool. + *

+ * If the value to be taken is already in use, it is incremented until a free + * value is found and returned. + *

+ * In the case that all pool values are in use, the pool is cleared and the last + * incremented value is returned. + *

+ * It does nothing to negative arguments. + * + * @param take value to be taken from the pool + * @return the value to be borrowed if not used + */ + public synchronized int take(final int take) { + int value = take; + for (int i = 0; i < POOL_SIZE; i++) { + if (setBit(value)) { + return value; + } + value = ++value % POOL_SIZE; + } + clearPool(); + setBit(value); + return value; + } + + /** + * Take a random value from the pool. + * + * @return the random value to be borrowed if not used + */ + public synchronized int random() { + // Choose a random number between 0 and 16383 + int random = Math.abs(new SplittableRandom().nextInt()) % POOL_SIZE; + return this.take(random); + } + + /** + * Set a bit from the byte array that represents the pool. + *

+ * This operation corresponds to setting a value as used. + *

+ * It returns false if the value is not free. + *

+ * It does nothing to negative arguments. + * + * @param value the value to be taken from the pool + * @return true if success + */ + private synchronized boolean setBit(int value) { + + if (value < 0) { + return false; + } + + final int byteIndex = value / 8; + final int bitIndex = value % 8; + + final int mask = (0x00000001 << bitIndex); + final boolean clear = (pool[byteIndex] & mask) == 0; + + if (clear) { + pool[byteIndex] = (byte) (pool[byteIndex] | mask); + return true; + } + + return false; + } + + /** + * Check if a value is used out of the pool. + * + * @param value a value to be checked in the pool + * @return true if the value is used + */ + public synchronized boolean isUsed(int value) { + + final int byteIndex = value / 8; + final int bitIndex = value % 8; + + final int mask = (0x00000001 << bitIndex); + boolean clear = (pool[byteIndex] & mask) == 0; + + return !clear; + } + + /** + * Check if a value is free in the pool. + * + * @param value a value to be checked in the pool + * @return true if the value is free + */ + public synchronized boolean isFree(int value) { + return !this.isUsed(value); + } + + /** + * Count the used values out of the pool + * + * @return the count of used values + */ + public synchronized int countUsed() { + int counter = 0; + for (int i = 0; i < POOL_SIZE; i++) { + if (this.isUsed(i)) { + counter++; + } + } + return counter; + } + + /** + * Count the free values in the pool. + * + * @return the count of free values + */ + public synchronized int countFree() { + return POOL_SIZE - this.countUsed(); + } + + /** + * Clear all bits of the byte array that represents the pool. + *

+ * This corresponds to marking all pool values as free + */ + public synchronized void clearPool() { + for (int i = 0; i < pool.length; i++) { + pool[i] = 0; + } + } + } } diff --git a/src/test/java/com/github/f4b6a3/uuid/TestSuite.java b/src/test/java/com/github/f4b6a3/uuid/TestSuite.java index 127387bf..d4601e84 100644 --- a/src/test/java/com/github/f4b6a3/uuid/TestSuite.java +++ b/src/test/java/com/github/f4b6a3/uuid/TestSuite.java @@ -17,7 +17,7 @@ import com.github.f4b6a3.uuid.codec.other.TimeOrderedCodecTest; import com.github.f4b6a3.uuid.factory.AbstRandomBasedFactoryTest; import com.github.f4b6a3.uuid.factory.AbstTimeBasedFactoryTest; -import com.github.f4b6a3.uuid.factory.function.ClockSeqPoolTest; +import com.github.f4b6a3.uuid.factory.function.impl.ClockSeqPoolTest; import com.github.f4b6a3.uuid.factory.function.impl.DefaultClockSeqFunctionTest; import com.github.f4b6a3.uuid.factory.function.impl.DefaultTimeFunctionTest; import com.github.f4b6a3.uuid.factory.function.impl.WindowsTimeFunctionTest; diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/function/ClockSeqPoolTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java similarity index 96% rename from src/test/java/com/github/f4b6a3/uuid/factory/function/ClockSeqPoolTest.java rename to src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java index 079be149..352b417c 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/function/ClockSeqPoolTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java @@ -1,4 +1,4 @@ -package com.github.f4b6a3.uuid.factory.function; +package com.github.f4b6a3.uuid.factory.function.impl; import org.junit.Test; @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.concurrent.ThreadLocalRandom; -import com.github.f4b6a3.uuid.factory.function.ClockSeqFunction.ClockSeqPool; +import com.github.f4b6a3.uuid.factory.function.impl.DefaultClockSeqFunction.ClockSeqPool; public class ClockSeqPoolTest { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunctionTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunctionTest.java index ddb1622c..3a187a29 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunctionTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultClockSeqFunctionTest.java @@ -43,7 +43,7 @@ public void testGetClockSequence1() { long first = 0; long last = 0; - int max = ClockSeqFunction.ClockSeqPool.POOL_MAX + 1; // 16,384 + int max = DefaultClockSeqFunction.ClockSeqPool.POOL_MAX + 1; // 16,384 DefaultClockSeqFunction clockSequence = new DefaultClockSeqFunction(); first = clockSequence.applyAsLong(CURRENT_TIMESTAMP); @@ -61,7 +61,7 @@ public void testGetClockSequence2() { int first = 0; int last = 0; - int max = ClockSeqFunction.ClockSeqPool.POOL_MAX + 1; // 16,384 + int max = DefaultClockSeqFunction.ClockSeqPool.POOL_MAX + 1; // 16,384 TimeBasedFactory factory = new TimeBasedFactory.Builder().withInstant(Instant.now()).build(); UUID uuid = factory.create(); @@ -81,7 +81,7 @@ public void testGetClockSequence2() { public void testGetClockSequenceUnique1() { HashSet set = new HashSet<>(); - int max = ClockSeqFunction.ClockSeqPool.POOL_MAX; // 16,383 + int max = DefaultClockSeqFunction.ClockSeqPool.POOL_MAX; // 16,383 DefaultClockSeqFunction clockSequence = new DefaultClockSeqFunction(); for (int i = 0; i < max; i++) { @@ -93,7 +93,7 @@ public void testGetClockSequenceUnique1() { public void testGetClockSequenceUnique2() { HashSet set = new HashSet<>(); - int max = ClockSeqFunction.ClockSeqPool.POOL_MAX; // 16,383 + int max = DefaultClockSeqFunction.ClockSeqPool.POOL_MAX; // 16,383 TimeBasedFactory factory = new TimeBasedFactory.Builder().withInstant(Instant.now()).build(); for (int i = 0; i < max; i++) { From e561d33528ef88466072a3aca7c26a694508c9b7 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 9 Jun 2024 01:05:50 -0300 Subject: [PATCH 26/40] Refactor RandomUtil --- .../uuid/factory/function/NodeIdFunction.java | 4 +- .../function/impl/DefaultRandomFunction.java | 76 +------------ .../function/impl/DefaultTimeFunction.java | 4 +- .../function/impl/RandomNodeIdFunction.java | 3 +- .../function/impl/WindowsTimeFunction.java | 4 +- .../f4b6a3/uuid/util/internal/RandomUtil.java | 107 +++++++++++++++--- 6 files changed, 103 insertions(+), 95 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java index 33f5fc4c..728f8dc2 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/NodeIdFunction.java @@ -48,7 +48,7 @@ public interface NodeIdFunction extends LongSupplier { * @return a number in the range 0 to 2^48-1. */ public static long getRandom() { - return toExpectedRange(RandomUtil.nextLong()); + return toExpectedRange(RandomUtil.newSecureRandom().nextLong()); } /** @@ -57,7 +57,7 @@ public static long getRandom() { * @return a number in the range 0 to 2^48-1. */ public static long getMulticastRandom() { - return toMulticast(RandomUtil.nextLong()); + return toMulticast(getRandom()); } /** diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java index ab78460e..51b4e128 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java @@ -24,91 +24,19 @@ package com.github.f4b6a3.uuid.factory.function.impl; -import java.security.SecureRandom; -import java.util.Random; -import java.util.concurrent.locks.ReentrantLock; - import com.github.f4b6a3.uuid.factory.function.RandomFunction; import com.github.f4b6a3.uuid.util.internal.RandomUtil; /** * Function that returns an array of bytes with the given length. - *

- * The current implementation uses a pool {@link SecureRandom}. - *

- * The pool size depends on the number of processors available, up to a maximum - * of 32. The minimum is 4. - *

- * The pool items are deleted very often to avoid holding them for too long. - * They are also deleted to avoid holding more instances than threads running. - *

- * The PRNG algorithm can be specified by system property or environment - * variable. See {@link RandomUtil#newSecureRandom()}. * * @see RandomFunction - * @see RandomUtil#newSecureRandom() + * @see RandomUtil */ public final class DefaultRandomFunction implements RandomFunction { - private static final int POOL_SIZE = processors(); - private static final Random[] POOL = new Random[POOL_SIZE]; - private static final ReentrantLock lock = new ReentrantLock(); - @Override public byte[] apply(final int length) { - - final byte[] bytes = new byte[length]; - current().nextBytes(bytes); - - // every now and then - if (bytes.length > 0 && bytes[0x00] == 0) { - // delete a random item from the pool - delete((new Random()).nextInt(POOL_SIZE)); - } - - return bytes; - } - - private static Random current() { - - // calculate the pool index given the current thread ID - final int index = (int) Thread.currentThread().getId() % POOL_SIZE; - - lock.lock(); - try { - // lazy loading instance - if (POOL[index] == null) { - POOL[index] = RandomUtil.newSecureRandom(); - } - return POOL[index]; - } finally { - lock.unlock(); - } - } - - private static void delete(int index) { - lock.lock(); - try { - POOL[index] = null; - } finally { - lock.unlock(); - } - } - - private static int processors() { - - final int min = 4; - final int max = 32; - - // get the number of processors from the runtime - final int processors = Runtime.getRuntime().availableProcessors(); - - if (processors < min) { - return min; - } else if (processors > max) { - return max; - } - - return processors; + return RandomUtil.nextBytes(length); } } \ No newline at end of file diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java index 706ad242..a061c57d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunction.java @@ -27,9 +27,9 @@ import static com.github.f4b6a3.uuid.util.UuidTime.TICKS_PER_MILLI; import java.time.Clock; +import java.util.SplittableRandom; import com.github.f4b6a3.uuid.factory.function.TimeFunction; -import com.github.f4b6a3.uuid.util.internal.RandomUtil; /** * Function that returns a number of 100-nanoseconds since 1970-01-01 (Unix @@ -46,7 +46,7 @@ public final class DefaultTimeFunction implements TimeFunction { private long lastTime = -1; // start the counter with a random number between 0 and 9,999 - private long counter = Math.abs(RandomUtil.nextLong() % TICKS_PER_MILLI); + private long counter = Math.abs(new SplittableRandom().nextLong()) % TICKS_PER_MILLI; // start the counter limit with a number between 10,000 and 19,999 private long counterMax = counter + TICKS_PER_MILLI; diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java index d1fca8e1..a985e998 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/RandomNodeIdFunction.java @@ -25,6 +25,7 @@ package com.github.f4b6a3.uuid.factory.function.impl; import com.github.f4b6a3.uuid.factory.function.NodeIdFunction; +import com.github.f4b6a3.uuid.util.internal.RandomUtil; /** * Function that returns a new random multicast node identifier. @@ -37,6 +38,6 @@ public final class RandomNodeIdFunction implements NodeIdFunction { @Override public long getAsLong() { - return NodeIdFunction.getMulticastRandom(); + return NodeIdFunction.toMulticast(RandomUtil.nextLong()); } } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java index d138b48d..6b8d25ca 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunction.java @@ -27,9 +27,9 @@ import static com.github.f4b6a3.uuid.util.UuidTime.TICKS_PER_MILLI; import java.time.Clock; +import java.util.SplittableRandom; import com.github.f4b6a3.uuid.factory.function.TimeFunction; -import com.github.f4b6a3.uuid.util.internal.RandomUtil; /** * Function that returns a number of 100-nanoseconds since 1970-01-01 (Unix @@ -55,7 +55,7 @@ public final class WindowsTimeFunction implements TimeFunction { private static final long TICKS_PER_GRANULARITY = TICKS_PER_MILLI * GRANULARITY; // start the counter with a random number between 0 and 159,999 - private long counter = Math.abs(RandomUtil.nextLong() % TICKS_PER_GRANULARITY); + private long counter = Math.abs(new SplittableRandom().nextLong()) % TICKS_PER_GRANULARITY; // start the counter limit with a number between 160,000 and 319,999 private long counterMax = counter + TICKS_PER_GRANULARITY; diff --git a/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java b/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java index 362f5bb1..23a41da1 100644 --- a/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java +++ b/src/main/java/com/github/f4b6a3/uuid/util/internal/RandomUtil.java @@ -26,37 +26,45 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.locks.ReentrantLock; /** - * Utility class that wraps a shared {@link SecureRandom} and provides new - * instances of {@link SecureRandom}. + * Utility class that provides random generator services. + *

+ * The current implementation uses a pool {@link SecureRandom}. + *

+ * The pool size depends on the number of processors available, up to a maximum + * of 32. The minimum is 4. + *

+ * The pool items are deleted very often to avoid holding them for too long. + * They are also deleted to avoid holding more instances than threads running. + *

+ * The PRNG algorithm can be specified by system property or environment + * variable. See {@link RandomUtil#newSecureRandom()}. */ public final class RandomUtil { - /** - * A globally shared {@link SecureRandom} instance. - */ - protected static final SecureRandom SHARED_RANDOM = newSecureRandom(); - private RandomUtil() { } /** - * Returns a random 32-bit number. + * Returns a random 64-bit number. * * @return a number */ - public static int nextInt() { - return SHARED_RANDOM.nextInt(); + public static long nextLong() { + return SecureRandomPool.nextLong(); } /** - * Returns a random 64-bit number. + * Returns an array of random bytes. * - * @return a number + * @param length the array length + * @return a byte array */ - public static long nextLong() { - return SHARED_RANDOM.nextLong(); + public static byte[] nextBytes(final int length) { + return SecureRandomPool.nextBytes(length); } /** @@ -110,4 +118,75 @@ public static SecureRandom newSecureRandom() { } return new SecureRandom(); } + + private static class SecureRandomPool { + + private static final int POOL_SIZE = processors(); + private static final Random[] POOL = new Random[POOL_SIZE]; + private static final ReentrantLock lock = new ReentrantLock(); + + private SecureRandomPool() { + } + + public static long nextLong() { + return ByteUtil.toNumber(nextBytes(Long.BYTES)); + } + + public static byte[] nextBytes(final int length) { + + final byte[] bytes = new byte[length]; + current().nextBytes(bytes); + + // every now and then + if (bytes.length > 0 && bytes[0x00] == 0) { + // delete a random item from the pool + delete((new Random()).nextInt(POOL_SIZE)); + } + + return bytes; + } + + private static Random current() { + + // calculate the pool index given the current thread ID + final int index = (int) Thread.currentThread().getId() % POOL_SIZE; + + lock.lock(); + try { + // lazy loading instance + if (POOL[index] == null) { + POOL[index] = RandomUtil.newSecureRandom(); + } + return POOL[index]; + } finally { + lock.unlock(); + } + } + + private static void delete(int index) { + lock.lock(); + try { + POOL[index] = null; + } finally { + lock.unlock(); + } + } + + private static int processors() { + + final int min = 4; + final int max = 32; + + // get the number of processors from the runtime + final int processors = Runtime.getRuntime().availableProcessors(); + + if (processors < min) { + return min; + } else if (processors > max) { + return max; + } + + return processors; + } + } } From 76dac16ef72f6d04d5ad0fcae1814755acaccf25 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 9 Jun 2024 02:46:02 -0300 Subject: [PATCH 27/40] Refactor tests Using SplittableRandom with a seed for reproducibility. --- .../com/github/f4b6a3/uuid/alt/GUIDTest.java | 31 +++++++------- .../function/BaseNRemainderDecoderTest.java | 13 +++--- .../function/BaseNRemainderEncoderTest.java | 13 +++--- .../factory/AbstRandomBasedFactoryTest.java | 42 ++++++++++--------- .../factory/AbstTimeBasedFactoryTest.java | 4 +- .../function/impl/ClockSeqPoolTest.java | 5 ++- .../impl/DefaultTimeFunctionTest.java | 6 ++- .../impl/WindowsTimeFunctionTest.java | 6 ++- .../nonstandard/PrefixCombFactoryTest.java | 18 ++++---- .../ShortPrefixCombFactoryTest.java | 10 ++--- .../ShortSuffixCombFactoryTest.java | 10 ++--- .../nonstandard/SuffixCombFactoryTest.java | 18 ++++---- .../rfc4122/RandomBasedFactoryTest.java | 10 ++--- .../factory/rfc4122/TimeBasedFactoryTest.java | 13 +++--- .../rfc4122/TimeOrderedEpochFactoryTest.java | 40 +++++++++--------- .../rfc4122/TimeOrderedFactoryTest.java | 13 +++--- .../github/f4b6a3/uuid/util/CombUtilTest.java | 10 ++--- .../f4b6a3/uuid/util/UuidBuilderTest.java | 22 ++++------ .../f4b6a3/uuid/util/UuidComparatorTest.java | 6 +-- .../github/f4b6a3/uuid/util/UuidUtilTest.java | 28 +++++++------ .../uuid/util/internal/SettingsUtilTest.java | 11 +++-- 21 files changed, 171 insertions(+), 158 deletions(-) diff --git a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java index 0d855fd7..58338476 100644 --- a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java @@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; import java.util.function.Function; import java.util.regex.Pattern; @@ -26,7 +27,7 @@ public class GUIDTest { @Test public void testConstructorGUID() { - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { final long msb = random.nextLong(); final long lsb = random.nextLong(); @@ -38,7 +39,7 @@ public void testConstructorGUID() { @Test public void testConstructorLongs() { - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { final long msb = random.nextLong(); final long lsb = random.nextLong(); @@ -50,7 +51,7 @@ public void testConstructorLongs() { @Test public void testConstructorJdkUUID() { - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { final long msb = random.nextLong(); final long lsb = random.nextLong(); @@ -62,7 +63,7 @@ public void testConstructorJdkUUID() { @Test public void testConstructorString() { - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { final long msb = random.nextLong(); final long lsb = random.nextLong(); @@ -76,10 +77,10 @@ public void testConstructorString() { @Test public void testConstructorBytes() { - Random random = new Random(); + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { byte[] bytes = new byte[GUID.GUID_BYTES]; - random.nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); GUID guid = new GUID(bytes); assertEquals(Arrays.toString(bytes), Arrays.toString(guid.toBytes())); } @@ -249,7 +250,7 @@ public void testV7() { @Test public void testToUUID() { - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { final long msb = random.nextLong(); final long lsb = random.nextLong(); @@ -270,11 +271,11 @@ public void testToString() { @Test public void testToBytes() { - Random random = new Random(); + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { byte[] bytes1 = new byte[16]; - random.nextBytes(bytes1); + (new Random(seeder.nextLong())).nextBytes(bytes1); GUID guid0 = new GUID(bytes1); byte[] bytes2 = guid0.toBytes(); @@ -287,19 +288,19 @@ public void testToBytes() { @Test public void testHashCode() { - Random random = new Random(); + SplittableRandom seeder = new SplittableRandom(1); byte[] bytes = new byte[GUID.GUID_BYTES]; // invoked on the same object for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - random.nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); GUID guid1 = new GUID(bytes); assertEquals(guid1.hashCode(), guid1.hashCode()); } // invoked on two equal objects for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - random.nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); GUID guid1 = new GUID(bytes); GUID guid2 = new GUID(bytes); assertEquals(guid1.hashCode(), guid2.hashCode()); @@ -309,12 +310,12 @@ public void testHashCode() { @Test public void testEquals() { - Random random = new Random(); + SplittableRandom seeder = new SplittableRandom(1); byte[] bytes = new byte[GUID.GUID_BYTES]; for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - random.nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); GUID guid1 = new GUID(bytes); GUID guid2 = new GUID(bytes); assertEquals(guid1, guid2); @@ -336,7 +337,7 @@ public void testEquals() { public void testCompareTo() { final long zero = 0L; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); byte[] bytes = new byte[GUID.GUID_BYTES]; for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java index baeb21ed..621f18c7 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java @@ -4,8 +4,9 @@ import java.math.BigInteger; import java.util.Arrays; +import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import org.junit.Test; @@ -30,11 +31,12 @@ public void testDecode() { @Test public void testMultiply() { + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 1000; i++) { byte[] bytes = new byte[UUID_BYTES]; - ThreadLocalRandom.current().nextBytes(bytes); - long multiplier = ThreadLocalRandom.current().nextInt() & 0x7fffffff; // positive - long addend = ThreadLocalRandom.current().nextInt() & 0x7fffffff; // positive + (new Random(seeder.nextLong())).nextBytes(bytes); + long multiplier = seeder.nextInt() & 0x7fffffff; // positive + long addend = seeder.nextInt() & 0x7fffffff; // positive BigInteger number1 = new BigInteger(1, bytes); BigInteger product1 = number1.multiply(BigInteger.valueOf(multiplier)).add(BigInteger.valueOf(addend)); @@ -77,11 +79,12 @@ protected static byte[] fromLongs(long[] longs) { private String getRandomString(BaseN base) { + SplittableRandom random = new SplittableRandom(1); char[] chars = new char[base.getLength()]; chars[0] = base.getPadding(); // to avoid overflow for (int i = 1; i < chars.length; i++) { - chars[i] = base.getAlphabet().get(ThreadLocalRandom.current().nextInt(base.getRadix())); + chars[i] = base.getAlphabet().get(random.nextInt(base.getRadix())); } return new String(chars); diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java index 4a6502f9..1a1d6538 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java @@ -4,7 +4,8 @@ import java.math.BigInteger; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; +import java.util.Random; +import java.util.SplittableRandom; import org.junit.Test; @@ -22,10 +23,10 @@ public class BaseNRemainderEncoderTest { @Test public void testEncode() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 1000; i++) { byte[] bytes = new byte[UUID_BYTES]; - ThreadLocalRandom.current().nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); UUID uuid = BinaryCodec.INSTANCE.decode(bytes); String string = Base62Codec.INSTANCE.encode(uuid); assertEquals(encode(Base62Codec.INSTANCE.getBase(), bytes), string); @@ -34,11 +35,11 @@ public void testEncode() { @Test public void testDivide() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 1000; i++) { byte[] bytes = new byte[UUID_BYTES]; - ThreadLocalRandom.current().nextBytes(bytes); - int divisor = ThreadLocalRandom.current().nextInt() & 0x7fffffff; // positive divisor + (new Random(seeder.nextLong())).nextBytes(bytes); + int divisor = seeder.nextInt() & 0x7fffffff; // positive divisor CustomDivider divider = x -> new long[] { x / divisor, x % divisor }; diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java index a179a476..14f8f620 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/AbstRandomBasedFactoryTest.java @@ -15,8 +15,8 @@ import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; @@ -25,10 +25,10 @@ public class AbstRandomBasedFactoryTest extends UuidFactoryTest { @Test public void testByteRandomNextLong() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 10; i++) { byte[] bytes = new byte[Long.BYTES]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> bytes); assertEquals(number, random.nextLong()); @@ -40,7 +40,7 @@ public void testByteRandomNextLong() { int size = Long.BYTES * longs; byte[] bytes = new byte[size]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); @@ -58,10 +58,10 @@ public void testByteRandomNextLong() { @Test public void testByteRandomNextBytes() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 10; i++) { byte[] bytes = new byte[Long.BYTES]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.SafeRandom((x) -> bytes); assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES))); } @@ -72,7 +72,7 @@ public void testByteRandomNextBytes() { int size = Long.BYTES * ints; byte[] bytes = new byte[size]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); @@ -92,10 +92,10 @@ public void testByteRandomNextBytes() { @Test public void testLogRandomNextLong() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 10; i++) { byte[] bytes = new byte[Long.BYTES]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> number); assertEquals(number, random.nextLong()); @@ -107,7 +107,7 @@ public void testLogRandomNextLong() { int size = Long.BYTES * ints; byte[] bytes = new byte[size]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); @@ -122,10 +122,10 @@ public void testLogRandomNextLong() { @Test public void testLogRandomNextBytes() { - + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < 10; i++) { byte[] bytes = new byte[Long.BYTES]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); long number = ByteBuffer.wrap(bytes).getLong(); AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> number); assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES))); @@ -137,7 +137,7 @@ public void testLogRandomNextBytes() { int size = Long.BYTES * ints; byte[] bytes = new byte[size]; - (new Random()).nextBytes(bytes); + (new Random(seeder.nextLong())).nextBytes(bytes); ByteBuffer buffer1 = ByteBuffer.wrap(bytes); ByteBuffer buffer2 = ByteBuffer.wrap(bytes); @@ -163,7 +163,7 @@ public void testLongRandom() { } { - long nextLong = ThreadLocalRandom.current().nextLong(); + long nextLong = new SplittableRandom(1).nextLong(); AbstRandomBasedFactory.IRandom random = new AbstRandomBasedFactory.FastRandom(() -> nextLong); byte[] bytes = random.nextBytes(Long.BYTES); ByteBuffer buffer = ByteBuffer.wrap(bytes); @@ -198,11 +198,12 @@ public void testLongRandom() { } { + SplittableRandom entropy = new SplittableRandom(1); long[] nextLong = { // - ThreadLocalRandom.current().nextLong(), // - ThreadLocalRandom.current().nextLong(), // - ThreadLocalRandom.current().nextLong(), // - ThreadLocalRandom.current().nextLong() /// + entropy.nextLong(), // + entropy.nextLong(), // + entropy.nextLong(), // + entropy.nextLong() /// }; int octects = nextLong.length * Byte.SIZE; @@ -237,9 +238,10 @@ public void testLongRandomWithFactory() { { // RandomBasedFactory + SplittableRandom random = new SplittableRandom(1); List list = new ArrayList<>(); - list.add(ThreadLocalRandom.current().nextLong()); - list.add(ThreadLocalRandom.current().nextLong()); + list.add(random.nextLong()); + list.add(random.nextLong()); UUID uuid1 = UuidUtil.setVersion(new UUID(list.get(0), list.get(1)), 4); RandomBasedFactory factory = new RandomBasedFactory(() -> list.remove(0)); UUID uuid2 = factory.create(); diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactoryTest.java index cd3b1d70..e58f6603 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/AbstTimeBasedFactoryTest.java @@ -3,7 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; import org.junit.Test; @@ -39,7 +39,7 @@ public void testSelectNodeIdentifierStrategy() { fail("It should use Random node identifier supplier"); } - Long number = ThreadLocalRandom.current().nextLong() & 0x0000ffffffffffffL; + Long number = new SplittableRandom(1).nextLong() & 0x0000ffffffffffffL; SettingsUtil.setProperty(SettingsUtil.PROPERTY_NODE, number.toString()); supplier = AbstTimeBasedFactory.selectNodeIdFunction(); assertEquals(number.longValue(), supplier.getAsLong()); diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java index 352b417c..c9d7d37e 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/ClockSeqPoolTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.*; import java.util.HashSet; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; import com.github.f4b6a3.uuid.factory.function.impl.DefaultClockSeqFunction.ClockSeqPool; @@ -125,6 +125,7 @@ public void testClockSequencePool5() throws InterruptedException { private static class TestThread extends Thread { private int index; + private static SplittableRandom random = new SplittableRandom(1); public static int[] list = new int[CLOCK_SEQUENCE_MAX]; private ClockSeqPool pool; @@ -136,7 +137,7 @@ public TestThread(ClockSeqPool pool, int index) { @Override public void run() { - int take = ThreadLocalRandom.current().nextInt(CLOCK_SEQUENCE_MAX); + int take = random.nextInt(CLOCK_SEQUENCE_MAX); list[index] = pool.take(take); } } diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunctionTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunctionTest.java index c0b8bdbb..5ecf3fc6 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunctionTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultTimeFunctionTest.java @@ -7,7 +7,7 @@ import java.time.Clock; import java.time.Instant; import java.time.ZoneOffset; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; public class DefaultTimeFunctionTest { @@ -33,10 +33,12 @@ public void testGetTimestampMillisecondWithClock() { final long ticks = (long) Math.pow(10, 4); final long bound = (long) Math.pow(2, 60) / ticks; + SplittableRandom random = new SplittableRandom(1); + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // instantiate a factory with a Clock that returns a fixed value - final long millis = Math.abs(ThreadLocalRandom.current().nextLong(bound)); + final long millis = Math.abs(random.nextLong(bound)); Clock clock = Clock.fixed(Instant.ofEpochMilli(millis), ZoneOffset.UTC); DefaultTimeFunction function = new DefaultTimeFunction(clock); diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunctionTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunctionTest.java index a6980ed0..40bd7d04 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunctionTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/function/impl/WindowsTimeFunctionTest.java @@ -7,7 +7,7 @@ import java.time.Clock; import java.time.Instant; import java.time.ZoneOffset; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; public class WindowsTimeFunctionTest { @@ -33,10 +33,12 @@ public void testGetTimestampMillisecondWithClock() { final long ticks = (long) Math.pow(10, 4); final long bound = (long) Math.pow(2, 60) / ticks; + SplittableRandom random = new SplittableRandom(1); + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // instantiate a factory with a Clock that returns a fixed value - final long millis = Math.abs(ThreadLocalRandom.current().nextLong(bound)); + final long millis = Math.abs(random.nextLong(bound)); Clock clock = Clock.fixed(Instant.ofEpochMilli(millis), ZoneOffset.UTC); WindowsTimeFunction function = new WindowsTimeFunction(clock); diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java index c9c65524..989a441e 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/PrefixCombFactoryTest.java @@ -15,8 +15,8 @@ import java.time.Instant; import java.util.Arrays; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class PrefixCombFactoryTest extends UuidFactoryTest { @@ -40,10 +40,12 @@ public void testGetPrefixComb() { @Test public void testGetPrefixCombCheckTimestamp() { + SplittableRandom random = new SplittableRandom(1); + for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - long random = ThreadLocalRandom.current().nextLong(1L << 48); - Clock clock = Clock.fixed(Instant.ofEpochMilli(random), Clock.systemUTC().getZone()); + long time = random.nextLong(1L << 48); + Clock clock = Clock.fixed(Instant.ofEpochMilli(time), Clock.systemUTC().getZone()); Instant instant1 = clock.instant(); long timestamp1 = UuidTime.toUnixTimestamp(instant1); @@ -87,8 +89,8 @@ public void testGetPrefixCombCheckTime() { public void testGetPrefixCombWithRandom() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - Random random = new Random(); - PrefixCombFactory factory = new PrefixCombFactory(random); + SplittableRandom seeder = new SplittableRandom(1); + PrefixCombFactory factory = new PrefixCombFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -102,9 +104,9 @@ public void testGetPrefixCombWithRandom() { @Test public void testGetPrefixCombWithRandomFunction() { - + SplittableRandom random = new SplittableRandom(1); UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier randomFunction = () -> random.nextLong(); PrefixCombFactory factory = new PrefixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { @@ -143,7 +145,7 @@ public void testGetPrefixCombInParallel() throws InterruptedException { public void testMinAndMax() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0000ffffffffffffL; for (int i = 0; i < 100; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java index db925fa1..43f9ad74 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortPrefixCombFactoryTest.java @@ -10,8 +10,8 @@ import java.util.Arrays; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class ShortPrefixCombFactoryTest extends UuidFactoryTest { @@ -91,8 +91,8 @@ public void testGetShortPrefixCombCheckTimeWithDifferentInterval() { public void testGetShortPrefixCombWithRandom() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - Random random = new Random(); - ShortPrefixCombFactory factory = new ShortPrefixCombFactory(random); + SplittableRandom seeder = new SplittableRandom(1); + ShortPrefixCombFactory factory = new ShortPrefixCombFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -106,9 +106,9 @@ public void testGetShortPrefixCombWithRandom() { @Test public void testGetShortPrefixCombWithRandomFunction() { - + SplittableRandom random = new SplittableRandom(1); UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier randomFunction = () -> random.nextLong(); ShortPrefixCombFactory factory = new ShortPrefixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java index a2b50d9c..b5c00466 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/ShortSuffixCombFactoryTest.java @@ -11,8 +11,8 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class ShortSuffixCombFactoryTest extends UuidFactoryTest { @@ -92,8 +92,8 @@ public void testGetShortSuffixCombCheckTimeWithDifferentInterval() { public void testGetShortSuffixCombWithRandom() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - Random random = new Random(); - ShortSuffixCombFactory factory = new ShortSuffixCombFactory(random); + SplittableRandom seeder = new SplittableRandom(1); + ShortSuffixCombFactory factory = new ShortSuffixCombFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -107,9 +107,9 @@ public void testGetShortSuffixCombWithRandom() { @Test public void testGetShortSuffixCombWithRandomFunction() { - + SplittableRandom random = new SplittableRandom(1); UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier randomFunction = () -> random.nextLong(); ShortSuffixCombFactory factory = new ShortSuffixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java index 41b427af..3f0e9918 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/nonstandard/SuffixCombFactoryTest.java @@ -15,8 +15,8 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class SuffixCombFactoryTest extends UuidFactoryTest { @@ -39,11 +39,11 @@ public void testGetSuffixComb() { @Test public void testGetSuffixCombCheckTimestamp() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - long random = ThreadLocalRandom.current().nextLong(1L << 48); - Clock clock = Clock.fixed(Instant.ofEpochMilli(random), Clock.systemUTC().getZone()); + long time = random.nextLong(1L << 48); + Clock clock = Clock.fixed(Instant.ofEpochMilli(time), Clock.systemUTC().getZone()); Instant instant1 = clock.instant(); long timestamp1 = UuidTime.toUnixTimestamp(instant1); @@ -86,8 +86,8 @@ public void testGetSuffixCombCheckTime() { public void testGetSuffixCombWithRandom() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - Random random = new Random(); - SuffixCombFactory factory = new SuffixCombFactory(random); + SplittableRandom seeder = new SplittableRandom(1); + SuffixCombFactory factory = new SuffixCombFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -101,9 +101,9 @@ public void testGetSuffixCombWithRandom() { @Test public void testGetSuffixCombWithRandomFunction() { - + SplittableRandom random = new SplittableRandom(1); UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier randomFunction = () -> random.nextLong(); SuffixCombFactory factory = new SuffixCombFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { @@ -141,7 +141,7 @@ public void testGetSuffixCombInParallel() throws InterruptedException { public void testMinAndMax() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0000ffffffffffffL; for (int i = 0; i < 100; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java index 0f5a4290..ab639a7b 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/RandomBasedFactoryTest.java @@ -9,8 +9,8 @@ import static org.junit.Assert.assertEquals; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class RandomBasedFactoryTest extends UuidFactoryTest { @@ -47,8 +47,8 @@ public void testGetRandomBasedFast() { public void testGetRandomBasedWithRandom() { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - Random random = new Random(); - RandomBasedFactory factory = new RandomBasedFactory(random); + SplittableRandom seeder = new SplittableRandom(1); + RandomBasedFactory factory = new RandomBasedFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -61,9 +61,9 @@ public void testGetRandomBasedWithRandom() { @Test public void testGetRandomBasedWithRandomFunction() { - + SplittableRandom random = new SplittableRandom(1); UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier randomFunction = () -> random.nextLong(); RandomBasedFactory factory = new RandomBasedFactory(randomFunction); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactoryTest.java index a7a068be..c79ece30 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeBasedFactoryTest.java @@ -16,9 +16,8 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; public class TimeBasedFactoryTest extends UuidFactoryTest { @@ -136,18 +135,18 @@ public void testGetTimeBasedInParallel() throws InterruptedException { @Test public void testGetTimeBasedWithOptionalArguments() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // Get 46 random bits to generate a date from the year 1970 to 2193. // (2^46 / 10000 / 60 / 60 / 24 / 365.25 + 1970 A.D. = ~2193 A.D.) - final Instant instant = Instant.ofEpochMilli(ThreadLocalRandom.current().nextLong() >>> 24); + final Instant instant = Instant.ofEpochMilli(random.nextLong() >>> 24); // Get 14 random bits random to generate the clock sequence - final int clockseq = ThreadLocalRandom.current().nextInt() & 0x000003ff; + final int clockseq = random.nextInt() & 0x000003ff; // Get 48 random bits for the node identifier, and set the multicast bit to ONE - final long nodeid = ThreadLocalRandom.current().nextLong() & 0x0000ffffffffffffL | 0x0000010000000000L; + final long nodeid = random.nextLong() & 0x0000ffffffffffffL | 0x0000010000000000L; // Create a time-based UUID with those random values UUID uuid = UuidCreator.getTimeBased(instant, clockseq, nodeid); @@ -166,7 +165,7 @@ public void testGetTimeBasedWithOptionalArguments() { public void testMinAndMax() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0fffffffffffffffL; for (int i = 0; i < 100; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java index fc2d2668..04afd91e 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedEpochFactoryTest.java @@ -12,7 +12,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.security.SecureRandom; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; @@ -21,7 +20,6 @@ import java.util.SplittableRandom; import java.util.TreeSet; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.LongSupplier; public class TimeOrderedEpochFactoryTest extends UuidFactoryTest { @@ -34,39 +32,37 @@ public void testDefault() { @Test public void testWithRandom() { + SplittableRandom seeder = new SplittableRandom(1); { - Random random = new Random(); - TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(random); + TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(new Random(seeder.nextLong())); assertNotNull(factory.create()); } { - SecureRandom random = new SecureRandom(); - TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(random); + TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(new Random(seeder.nextLong())); assertNotNull(factory.create()); } } @Test public void testWithRandomFunction() { + SplittableRandom random = new SplittableRandom(1); { - SplittableRandom random = new SplittableRandom(); LongSupplier function = () -> random.nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function); assertNotNull(factory.create()); } { - LongSupplier function = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier function = () -> random.nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function); assertNotNull(factory.create()); } { - SplittableRandom random = new SplittableRandom(); LongSupplier function = () -> random.nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function, Clock.systemDefaultZone()); assertNotNull(factory.create()); } { - LongSupplier function = () -> ThreadLocalRandom.current().nextLong(); + LongSupplier function = () -> random.nextLong(); TimeOrderedEpochFactory factory = new TimeOrderedEpochFactory(function, Clock.systemDefaultZone()); assertNotNull(factory.create()); } @@ -116,11 +112,11 @@ public void testGetTimeOrderedEpoch() { @Test public void testGetTimeOrderedEpochCheckTimestamp() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - long random = ThreadLocalRandom.current().nextLong(1L << 48); - Clock clock = Clock.fixed(Instant.ofEpochMilli(random), Clock.systemUTC().getZone()); + long time = random.nextLong(1L << 48); + Clock clock = Clock.fixed(Instant.ofEpochMilli(time), Clock.systemUTC().getZone()); Instant instant1 = clock.instant(); long timestamp1 = UuidTime.toGregTimestamp(instant1); @@ -222,12 +218,12 @@ private void checkCreationTime(UUID[] list, long startTime, long endTime) { @Test public void testGetTimeOrderedEpochWithRandom() { - Random random = new Random(); + SplittableRandom seeder = new SplittableRandom(1); TimeOrderedEpochFactory factory; { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; - factory = new TimeOrderedEpochFactory(random); + factory = new TimeOrderedEpochFactory(new Random(seeder.nextLong())); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { list[i] = factory.create(); @@ -240,6 +236,7 @@ public void testGetTimeOrderedEpochWithRandom() { { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; + Random random = new Random(seeder.nextLong()); factory = TimeOrderedEpochFactory.builder().withRandom(random).withIncrementPlus1().build(); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { @@ -253,6 +250,7 @@ public void testGetTimeOrderedEpochWithRandom() { { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; + Random random = new Random(seeder.nextLong()); factory = TimeOrderedEpochFactory.builder().withRandom(random).withIncrementPlusN().build(); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { @@ -266,6 +264,7 @@ public void testGetTimeOrderedEpochWithRandom() { { UUID[] list = new UUID[DEFAULT_LOOP_MAX]; + Random random = new Random(seeder.nextLong()); factory = TimeOrderedEpochFactory.builder().withRandom(random).withIncrementPlusN(1_000_000).build(); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { @@ -280,8 +279,8 @@ public void testGetTimeOrderedEpochWithRandom() { @Test public void testGetTimeOrderedEpochWithRandomFunction() { - - LongSupplier randomFunction = () -> ThreadLocalRandom.current().nextLong(); + SplittableRandom random = new SplittableRandom(1); + LongSupplier randomFunction = () -> random.nextLong(); TimeOrderedEpochFactory factory; @@ -341,14 +340,15 @@ public void testGetTimeOrderedEpochWithRandomFunction() { @Test public void testGetTimeOrderedEpochInParallel() throws InterruptedException { - Random random = new Random(); Clock clock = Clock.systemDefaultZone(); + SplittableRandom seeder = new SplittableRandom(1); Thread[] threads = new Thread[THREAD_TOTAL]; TestThread.clearHashSet(); // Instantiate and start many threads for (int i = 0; i < THREAD_TOTAL; i++) { + Random random = new Random(seeder.nextLong()); threads[i] = new TestThread(new TimeOrderedEpochFactory(random, clock), DEFAULT_LOOP_MAX); threads[i].start(); } @@ -431,7 +431,7 @@ public void testWithFixedClock() { public void testMinAndMax() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0000ffffffffffffL; for (int i = 0; i < 100; i++) { @@ -462,7 +462,7 @@ public void testMinAndMax() { public void testRandom() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0000ffffffffffffL; for (int i = 0; i < 100; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactoryTest.java index 5e414fe5..63bf6b84 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/rfc4122/TimeOrderedFactoryTest.java @@ -15,9 +15,8 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; public class TimeOrderedFactoryTest extends UuidFactoryTest { @@ -135,18 +134,18 @@ public void testGetTimeOrderedInParallel() throws InterruptedException { @Test public void testGetTimeOrderedWithOptionalArguments() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // Get 46 random bits to generate a date from the year 1970 to 2193. // (2^46 / 10000 / 60 / 60 / 24 / 365.25 + 1970 A.D. = ~2193 A.D.) - final Instant instant = Instant.ofEpochMilli(ThreadLocalRandom.current().nextLong() >>> 24); + final Instant instant = Instant.ofEpochMilli(random.nextLong() >>> 24); // Get 14 random bits random to generate the clock sequence - final int clockseq = ThreadLocalRandom.current().nextInt() & 0x000003ff; + final int clockseq = random.nextInt() & 0x000003ff; // Get 48 random bits for the node identifier, and set the multicast bit to ONE - final long nodeid = ThreadLocalRandom.current().nextLong() & 0x0000ffffffffffffL | 0x0000010000000000L; + final long nodeid = random.nextLong() & 0x0000ffffffffffffL | 0x0000010000000000L; // Create a time-based UUID with those random values UUID uuid = UuidCreator.getTimeOrdered(instant, clockseq, nodeid); @@ -208,7 +207,7 @@ public void testGetTimeOrderedCheckOrder() { public void testMinAndMax() { long time = 0; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); final long mask = 0x0fffffffffffffffL; for (int i = 0; i < 100; i++) { diff --git a/src/test/java/com/github/f4b6a3/uuid/util/CombUtilTest.java b/src/test/java/com/github/f4b6a3/uuid/util/CombUtilTest.java index a20f9ef0..01c62d83 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/CombUtilTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/CombUtilTest.java @@ -6,7 +6,7 @@ import java.time.Instant; import java.time.ZoneOffset; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; import org.junit.Test; @@ -37,11 +37,11 @@ public void testGetPrefixWithClock() { final int bits = 48; final long bound = (long) Math.pow(2, bits); - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // instantiate a factory with a Clock that returns a fixed value - final long millis = Math.abs(ThreadLocalRandom.current().nextLong(bound)); + final long millis = Math.abs(random.nextLong(bound)); Clock clock = Clock.fixed(Instant.ofEpochMilli(millis), ZoneOffset.UTC); AbstRandomBasedFactory factory = new PrefixCombFactory(clock); @@ -71,11 +71,11 @@ public void testGetSuffixWithClock() { final int bits = 48; final long bound = (long) Math.pow(2, bits); - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { // instantiate a factory with a Clock that returns a fixed value - final long millis = Math.abs(ThreadLocalRandom.current().nextLong(bound)); + final long millis = Math.abs(random.nextLong(bound)); Clock clock = Clock.fixed(Instant.ofEpochMilli(millis), ZoneOffset.UTC); AbstRandomBasedFactory factory = new SuffixCombFactory(clock); diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java index 6587570e..c84400b5 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidBuilderTest.java @@ -6,6 +6,7 @@ import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; import org.junit.Test; @@ -15,7 +16,6 @@ public class UuidBuilderTest { private static final int DEFAULT_LOOP_MAX = 1_000; - private static final Random seeder = new Random(1L); @Test public void testVersionNumber() { @@ -23,8 +23,8 @@ public void testVersionNumber() { assertEquals(0x0L, new UuidBuilder().put((long) 0L).put((long) 0L).build().version()); assertEquals(0xfL, new UuidBuilder().put((long) -1L).put((long) -1L).build().version()); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < 15; i++) { - Random random = new Random(seeder.nextLong()); assertEquals(i, new UuidBuilder(i).put(random.nextLong()).put(random.nextLong()).build().version()); } } @@ -32,9 +32,9 @@ public void testVersionNumber() { @Test public void testPutTwoLongsWithoutVersionNumber() { + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Random random = new Random(seeder.nextLong()); long msb = random.nextLong(); long lsb = random.nextLong(); @@ -50,10 +50,9 @@ public void testPutTwoLongsWithVersion4() { int version = 4; + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Random random = new Random(seeder.nextLong()); - long msb = random.nextLong(); long lsb = random.nextLong(); @@ -69,10 +68,9 @@ public void testPutFourIntsWithVersion4() { int version = 4; + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Random random = new Random(seeder.nextLong()); - int part1 = random.nextInt(); int part2 = random.nextInt(); int part3 = random.nextInt(); @@ -93,15 +91,14 @@ public void testPutSixteenBytesWithVersion4() { int version = 4; + SplittableRandom seeder = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Random random = new Random(seeder.nextLong()); - byte[] bytes1 = new byte[8]; - random.nextBytes(bytes1); + (new Random(seeder.nextLong())).nextBytes(bytes1); byte[] bytes2 = new byte[8]; - random.nextBytes(bytes2); + (new Random(seeder.nextLong())).nextBytes(bytes2); long msb = ByteUtil.toNumber(bytes1); long lsb = ByteUtil.toNumber(bytes2); @@ -117,10 +114,9 @@ public void testPutTwoIntsFourShortsWithVersion8() { int version = 8; + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Random random = new Random(seeder.nextLong()); - int p1 = random.nextInt(); short p2 = (short) random.nextInt(); short p3 = (short) random.nextInt(); diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java index 5a4368e3..ce956ee3 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java @@ -4,7 +4,7 @@ import java.math.BigInteger; import java.nio.ByteBuffer; -import java.util.Random; +import java.util.SplittableRandom; import java.util.UUID; import org.junit.Test; @@ -75,7 +75,7 @@ public void testCompareDefault() { final long zero = 0L; byte[] bytes = new byte[16]; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); @@ -164,7 +164,7 @@ public void testCompareOpaque() { final long zero = 0L; byte[] bytes = new byte[16]; - Random random = new Random(); + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java index fd3b6c47..57a13095 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidUtilTest.java @@ -5,7 +5,7 @@ import java.time.Instant; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; import org.junit.Test; @@ -78,10 +78,10 @@ public void testCheckCompatibility() { @Test public void testGetTimestamp() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Instant instant = UuidTime.fromGregTimestamp(ThreadLocalRandom.current().nextLong() & GREG_TIMESTAMP_MASK); + Instant instant = UuidTime.fromGregTimestamp(random.nextLong() & GREG_TIMESTAMP_MASK); long unixTimestamp = UuidTime.toUnixTimestamp(instant); long gregTimestamp = UuidTime.toGregTimestamp(instant); @@ -105,10 +105,10 @@ public void testGetTimestamp() { @Test public void testGetInstant() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - Instant instant = UuidTime.fromGregTimestamp(ThreadLocalRandom.current().nextLong() & GREG_TIMESTAMP_MASK); + Instant instant = UuidTime.fromGregTimestamp(random.nextLong() & GREG_TIMESTAMP_MASK); TimeBasedFactory factory1 = TimeBasedFactory.builder().withInstant(instant).build(); UUID uuid1 = factory1.create(); @@ -129,8 +129,9 @@ public void testGetInstant() { @Test public void testGetClockSequence() { + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - long clockSequence1 = ThreadLocalRandom.current().nextLong() & CLOCK_SEQUENCE_MASK; + long clockSequence1 = random.nextLong() & CLOCK_SEQUENCE_MASK; UUID uuid = TimeBasedFactory.builder().withClockSeq(clockSequence1).build().create(); long clockSequence2 = getClockSequence(uuid); assertEquals(clockSequence1, clockSequence2); @@ -139,8 +140,9 @@ public void testGetClockSequence() { @Test public void testGetNodeIdentifier() { + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - long nodeIdentifier1 = ThreadLocalRandom.current().nextLong() & NODE_IDENTIFIER_MASK; + long nodeIdentifier1 = random.nextLong() & NODE_IDENTIFIER_MASK; UUID uuid = TimeBasedFactory.builder().withNodeId(nodeIdentifier1).build().create(); long nodeIdentifier2 = getNodeIdentifier(uuid); assertEquals(nodeIdentifier1, nodeIdentifier2); @@ -149,10 +151,10 @@ public void testGetNodeIdentifier() { @Test public void testGetLocalDomain() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - int localIdentifier1 = ThreadLocalRandom.current().nextInt(); - byte localDomain1 = (byte) ThreadLocalRandom.current().nextInt(); + int localIdentifier1 = random.nextInt(); + byte localDomain1 = (byte) random.nextInt(); UUID uuid = UuidCreator.getDceSecurity(localDomain1, localIdentifier1); byte localDomain2 = getLocalDomain(uuid); assertEquals(localDomain1, localDomain2); @@ -161,10 +163,10 @@ public void testGetLocalDomain() { @Test public void testGetLocalIdentifier() { - + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { - int localIdentifier1 = ThreadLocalRandom.current().nextInt(); - byte localDomain1 = (byte) ThreadLocalRandom.current().nextInt(); + int localIdentifier1 = random.nextInt(); + byte localDomain1 = (byte) random.nextInt(); UUID uuid = UuidCreator.getDceSecurity(localDomain1, localIdentifier1); int localIdentifier2 = getLocalIdentifier(uuid); assertEquals(localIdentifier1, localIdentifier2); diff --git a/src/test/java/com/github/f4b6a3/uuid/util/internal/SettingsUtilTest.java b/src/test/java/com/github/f4b6a3/uuid/util/internal/SettingsUtilTest.java index 0d468b8c..c3378a06 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/internal/SettingsUtilTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/internal/SettingsUtilTest.java @@ -2,7 +2,7 @@ import static org.junit.Assert.*; -import java.util.concurrent.ThreadLocalRandom; +import java.util.SplittableRandom; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -22,8 +22,9 @@ public static void afterClass() { @Test public void testSetNodeIdentifier() { + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < 100; i++) { - long number = ThreadLocalRandom.current().nextLong() >>> 16; + long number = random.nextLong() >>> 16; SettingsUtil.setNodeIdentifier(number); long result = SettingsUtil.getNodeIdentifier(); assertEquals(number, result); @@ -32,8 +33,9 @@ public void testSetNodeIdentifier() { @Test public void testSetProperty() { + SplittableRandom random = new SplittableRandom(1); for (int i = 0; i < 100; i++) { - long number = ThreadLocalRandom.current().nextLong() >>> 16; + long number = random.nextLong() >>> 16; String string = Long.toString(number); SettingsUtil.setProperty(SettingsUtil.PROPERTY_NODE, string); long result = SettingsUtil.getNodeIdentifier(); @@ -43,7 +45,8 @@ public void testSetProperty() { @Test public void testSetPropertyWith0x() { - long number = ThreadLocalRandom.current().nextLong() >>> 16; + SplittableRandom random = new SplittableRandom(1); + long number = random.nextLong() >>> 16; String string = "0x" + Long.toHexString(number); SettingsUtil.setProperty(SettingsUtil.PROPERTY_NODE, string); long result = SettingsUtil.getNodeIdentifier(); From 1fbbe803924aa8ddfefe6b6421a2c7dae0551b5d Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 19:07:48 -0300 Subject: [PATCH 28/40] Regular maintenance --- .../java/com/github/f4b6a3/uuid/alt/GUID.java | 119 +++++++++--------- .../github/f4b6a3/uuid/codec/StringCodec.java | 95 +++++++------- .../codec/base/function/Base16Encoder.java | 64 +++++----- .../codec/base/function/Base32Encoder.java | 53 ++++---- .../codec/base/function/Base64Encoder.java | 44 +++---- .../codec/base/function/BaseNEncoder.java | 4 + .../com/github/f4b6a3/uuid/alt/GUIDTest.java | 45 +++++++ .../f4b6a3/uuid/codec/StringCodecTest.java | 6 +- 8 files changed, 234 insertions(+), 196 deletions(-) diff --git a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java index 0ab8dd0c..a1e3de78 100644 --- a/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java +++ b/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java @@ -117,7 +117,6 @@ public final class GUID implements Serializable, Comparable { */ public static final int GUID_BYTES = 16; - private static final long MASK_04 = 0x0000_0000_0000_000fL; private static final long MASK_08 = 0x0000_0000_0000_00ffL; private static final long MASK_12 = 0x0000_0000_0000_0fffL; private static final long MASK_16 = 0x0000_0000_0000_ffffL; @@ -210,7 +209,7 @@ public GUID(String string) { */ public static GUID v1() { - final long time = gregorian(); + final long time = gregorian(Instant.now()); final long msb = (time << 32) | ((time >>> 16) & (MASK_16 << 16)) | ((time >>> 48) & MASK_12); final long lsb = LazyHolder.random() | MULTICAST; @@ -313,7 +312,7 @@ public static GUID v5(GUID namespace, String name) { */ public static GUID v6() { - final long time = gregorian(); + final long time = gregorian(Instant.now()); final long msb = ((time & ~MASK_12) << 4) | (time & MASK_12); final long lsb = LazyHolder.random() | MULTICAST; @@ -336,7 +335,7 @@ public static GUID v7() { final long time = System.currentTimeMillis(); - final long msb = (time << 16) | (LazyHolder.random() & MASK_16); + final long msb = (time << 16) | (LazyHolder.random() & MASK_12); final long lsb = LazyHolder.random(); return version(msb, lsb, 7); @@ -474,9 +473,8 @@ else if (c < d) return 0; } - private static long gregorian() { + static long gregorian(final Instant now) { // 1582-10-15T00:00:00.000Z - Instant now = Instant.now(); final long greg = 12219292800L; final long nano = now.getNano(); final long secs = now.getEpochSecond() + greg; @@ -484,32 +482,10 @@ private static long gregorian() { return time; } - private static class LazyHolder { - - // The JVM unique number tries to mitigate the fact that the thread - // local random is not seeded with a secure random seed by default. - // Their seeds are based on temporal data and predefined constants. - // Although the seeds are unique per JVM, they are not across JVMs. - // It helps to generate different sequences of numbers even if two - // ThreadLocalRandom are by chance instantiated with the same seed. - // Of course it doesn't better the output, but doesn't hurt either. - static final long JVM_UNIQUE_NUMBER = new SecureRandom().nextLong(); - - private static long random() { - return ThreadLocalRandom.current().nextLong() ^ JVM_UNIQUE_NUMBER; - } - } - - private static GUID hash(int version, String algorithm, GUID namespace, String name) { + static GUID hash(int version, String algorithm, GUID namespace, String name) { Objects.requireNonNull(name, "Null name"); - - MessageDigest hasher = null; - try { - hasher = MessageDigest.getInstance(algorithm); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e.getMessage()); - } + MessageDigest hasher = hasher(algorithm); if (namespace != null) { ByteBuffer ns = ByteBuffer.allocate(16); @@ -527,13 +503,19 @@ private static GUID hash(int version, String algorithm, GUID namespace, String n return version(msb, lsb, version); } - private static GUID version(long hi, long lo, int version) { + static MessageDigest hasher(String algorithm) { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e.getMessage()); + } + } + static GUID version(long hi, long lo, int version) { // set the 4 most significant bits of the 7th byte - final long msb = (hi & 0xffff_ffff_ffff_0fffL) | (version & MASK_04) << 12; // RFC-4122 version + final long msb = (hi & 0xffff_ffff_ffff_0fffL) | (version & 0xfL) << 12; // RFC-4122 version // set the 2 most significant bits of the 9th byte to 1 and 0 final long lsb = (lo & 0x3fff_ffff_ffff_ffffL) | 0x8000_0000_0000_0000L; // RFC-4122 variant - return new GUID(msb, lsb); } @@ -561,18 +543,18 @@ static final class Parser { mapping['7'] = 7; mapping['8'] = 8; mapping['9'] = 9; - mapping['A'] = 10; - mapping['B'] = 11; - mapping['C'] = 12; - mapping['D'] = 13; - mapping['E'] = 14; - mapping['F'] = 15; mapping['a'] = 10; mapping['b'] = 11; mapping['c'] = 12; mapping['d'] = 13; mapping['e'] = 14; mapping['f'] = 15; + mapping['A'] = 10; + mapping['B'] = 11; + mapping['C'] = 12; + mapping['D'] = 13; + mapping['E'] = 14; + mapping['F'] = 15; MAP = mapping; } @@ -583,11 +565,7 @@ static final class Parser { public static GUID parse(final String string) { - if (string == null || string.length() != GUID.GUID_CHARS) { - throw newIllegalArgumentException(string); - } - - validateDashPositions(string); + validate(string); long msb = 0; long lsb = 0; @@ -615,38 +593,57 @@ public static GUID parse(final String string) { return new GUID(msb, lsb); } - protected static void validateDashPositions(final String string) { - if (string.charAt(DASH_POSITION_1) != '-' || string.charAt(DASH_POSITION_2) != '-' - || string.charAt(DASH_POSITION_3) != '-' || string.charAt(DASH_POSITION_4) != '-') { - throw newIllegalArgumentException(string); + public static boolean valid(final String guid) { + try { + parse(guid); + return true; + } catch (IllegalArgumentException e) { + return false; } } - private static RuntimeException newIllegalArgumentException(final String str) { - return new IllegalArgumentException("Invalid UUID: " + str); - } - - protected static long get(final String string, int i) { + private static long get(final String string, int i) { final int chr = string.charAt(i); if (chr > 255) { - throw newIllegalArgumentException(string); + throw exception(string); } final byte value = MAP[chr]; if (value < 0) { - throw newIllegalArgumentException(string); + throw exception(string); } return value & 0xffL; } - public static boolean valid(final String guid) { - try { - parse(guid); - return true; - } catch (IllegalArgumentException e) { - return false; + private static RuntimeException exception(final String str) { + return new IllegalArgumentException("Invalid UUID: " + str); + } + + private static void validate(final String string) { + if (string == null || string.length() != GUID_CHARS) { + throw exception(string); } + if (string.charAt(DASH_POSITION_1) != '-' || string.charAt(DASH_POSITION_2) != '-' + || string.charAt(DASH_POSITION_3) != '-' || string.charAt(DASH_POSITION_4) != '-') { + throw exception(string); + } + } + } + + private static class LazyHolder { + + // The JVM unique number tries to mitigate the fact that the thread + // local random is not seeded with a secure random seed by default. + // Their seeds are based on temporal data and predefined constants. + // Although the seeds are unique per JVM, they are not across JVMs. + // It helps to generate different sequences of numbers even if two + // ThreadLocalRandom are by chance instantiated with the same seed. + // Of course it doesn't better the output, but doesn't hurt either. + static final long JVM_UNIQUE_NUMBER = new SecureRandom().nextLong(); + + private static long random() { + return ThreadLocalRandom.current().nextLong() ^ JVM_UNIQUE_NUMBER; } } } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java index 700b9e13..e048fabf 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java @@ -62,22 +62,22 @@ public class StringCodec implements UuidCodec { */ public static final StringCodec INSTANCE = new StringCodec(); + private static final int DASH_POSITION_1 = 8; + private static final int DASH_POSITION_2 = 13; + private static final int DASH_POSITION_3 = 18; + private static final int DASH_POSITION_4 = 23; + + private static final int LENGTH_WITH_DASH = 36; + private static final int LENGTH_WITHOUT_DASH = 32; + private static final int LENGTH_WITH_URN_PREFIX = 45; + private static final int LENGTH_WITH_CURLY_BRACES = 38; + private static final byte[] MAP = Base16Codec.INSTANCE.getBase().getMap().array(); private static final CharArray ALPHABET = Base16Codec.INSTANCE.getBase().getAlphabet(); private static final String URN_PREFIX = "urn:uuid:"; private static final boolean JAVA_VERSION_GREATER_THAN_8 = JavaVersionUtil.getJavaVersion() > 8; - private static final int WITH_DASH_UUID_LENGTH = 36; - private static final int WITHOUT_DASH_UUID_LENGTH = 32; - private static final int URN_PREFIX_UUID_LENGTH = 45; - private static final int CURLY_BRACES_UUID_LENGTH = 38; - - private static final int DASH_POSITION_1 = 8; - private static final int DASH_POSITION_2 = 13; - private static final int DASH_POSITION_3 = 18; - private static final int DASH_POSITION_4 = 23; - /** * Get a string from a UUID. *

@@ -166,78 +166,71 @@ public UUID decode(final String string) { throw InvalidUuidException.newInstance(string); } - final String modified = modifyString(string); + final String modified = modify(string); - if (modified.length() == WITH_DASH_UUID_LENGTH) { + if (modified.length() == LENGTH_WITH_DASH) { + validate(modified); + return parse(modified); + } - validateDashPositions(modified); + if (modified.length() == LENGTH_WITHOUT_DASH) { + return Base16Codec.INSTANCE.decode(modified); + } - long msb = 0; - long lsb = 0; + throw InvalidUuidException.newInstance(modified); + } - for (int i = 0; i < 8; i++) { - msb = (msb << 4) | get(modified, i); - } + private UUID parse(final String string) { - for (int i = 9; i < 13; i++) { - msb = (msb << 4) | get(modified, i); - } + long msb = 0L; + long lsb = 0L; - for (int i = 14; i < 18; i++) { - msb = (msb << 4) | get(modified, i); - } + for (int i = 0; i < 8; i++) { + msb = (msb << 4) | get(string, i); + } - for (int i = 19; i < 23; i++) { - lsb = (lsb << 4) | get(modified, i); - } + for (int i = 9; i < 13; i++) { + msb = (msb << 4) | get(string, i); + } - for (int i = 24; i < 36; i++) { - lsb = (lsb << 4) | get(modified, i); - } + for (int i = 14; i < 18; i++) { + msb = (msb << 4) | get(string, i); + } - return new UUID(msb, lsb); + for (int i = 19; i < 23; i++) { + lsb = (lsb << 4) | get(string, i); } - if (modified.length() == WITHOUT_DASH_UUID_LENGTH) { - return Base16Codec.INSTANCE.decode(modified); + for (int i = 24; i < 36; i++) { + lsb = (lsb << 4) | get(string, i); } - throw InvalidUuidException.newInstance(modified); + return new UUID(msb, lsb); } - /** - * Returns a modified string without URN prefix and curly braces. - *

- * It removes URN prefix and curly braces from the original string. - * - * @param string a string - * @return a substring - */ - protected static String modifyString(final String string) { + protected static String modify(final String string) { // UUID URN format: "urn:uuid:00000000-0000-0000-0000-000000000000" - if (string.length() == URN_PREFIX_UUID_LENGTH && string.startsWith(URN_PREFIX)) { - // Remove the URN prefix: "urn:uuid:" - return string.substring(URN_PREFIX.length()); + if (string.length() == LENGTH_WITH_URN_PREFIX && string.startsWith(URN_PREFIX)) { + return string.substring(URN_PREFIX.length()); // Remove the URN prefix: "urn:uuid:" } // Curly braces format: "{00000000-0000-0000-0000-000000000000}" - if (string.length() == CURLY_BRACES_UUID_LENGTH && string.startsWith("{") && string.endsWith("}")) { - // Remove curly braces: '{' and '}' - return string.substring(1, string.length() - 1); + if (string.length() == LENGTH_WITH_CURLY_BRACES && string.startsWith("{") && string.endsWith("}")) { + return string.substring(1, string.length() - 1); // Remove curly braces: '{' and '}' } return string; } - protected static void validateDashPositions(final String string) { + private static void validate(final String string) { if (string.charAt(DASH_POSITION_1) != '-' || string.charAt(DASH_POSITION_2) != '-' || string.charAt(DASH_POSITION_3) != '-' || string.charAt(DASH_POSITION_4) != '-') { throw InvalidUuidException.newInstance(string); } } - protected long get(final String string, int i) { + private long get(final String string, final int i) { final int chr = string.charAt(i); if (chr > 255) { diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java index 6da687ea..dfa0bb82 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base16Encoder.java @@ -55,39 +55,39 @@ public String apply(UUID uuid) { final long msb = uuid.getMostSignificantBits(); final long lsb = uuid.getLeastSignificantBits(); - chars[0x00] = alphabet.get((int) (msb >>> 0x3c & 0xf)); - chars[0x01] = alphabet.get((int) (msb >>> 0x38 & 0xf)); - chars[0x02] = alphabet.get((int) (msb >>> 0x34 & 0xf)); - chars[0x03] = alphabet.get((int) (msb >>> 0x30 & 0xf)); - chars[0x04] = alphabet.get((int) (msb >>> 0x2c & 0xf)); - chars[0x05] = alphabet.get((int) (msb >>> 0x28 & 0xf)); - chars[0x06] = alphabet.get((int) (msb >>> 0x24 & 0xf)); - chars[0x07] = alphabet.get((int) (msb >>> 0x20 & 0xf)); - chars[0x08] = alphabet.get((int) (msb >>> 0x1c & 0xf)); - chars[0x09] = alphabet.get((int) (msb >>> 0x18 & 0xf)); - chars[0x0a] = alphabet.get((int) (msb >>> 0x14 & 0xf)); - chars[0x0b] = alphabet.get((int) (msb >>> 0x10 & 0xf)); - chars[0x0c] = alphabet.get((int) (msb >>> 0x0c & 0xf)); - chars[0x0d] = alphabet.get((int) (msb >>> 0x08 & 0xf)); - chars[0x0e] = alphabet.get((int) (msb >>> 0x04 & 0xf)); - chars[0x0f] = alphabet.get((int) (msb & 0xf)); + chars[0x00] = get(msb >>> 0x3c & 0xf); + chars[0x01] = get(msb >>> 0x38 & 0xf); + chars[0x02] = get(msb >>> 0x34 & 0xf); + chars[0x03] = get(msb >>> 0x30 & 0xf); + chars[0x04] = get(msb >>> 0x2c & 0xf); + chars[0x05] = get(msb >>> 0x28 & 0xf); + chars[0x06] = get(msb >>> 0x24 & 0xf); + chars[0x07] = get(msb >>> 0x20 & 0xf); + chars[0x08] = get(msb >>> 0x1c & 0xf); + chars[0x09] = get(msb >>> 0x18 & 0xf); + chars[0x0a] = get(msb >>> 0x14 & 0xf); + chars[0x0b] = get(msb >>> 0x10 & 0xf); + chars[0x0c] = get(msb >>> 0x0c & 0xf); + chars[0x0d] = get(msb >>> 0x08 & 0xf); + chars[0x0e] = get(msb >>> 0x04 & 0xf); + chars[0x0f] = get(msb >>> 0x00 & 0xf); - chars[0x10] = alphabet.get((int) (lsb >>> 0x3c & 0xf)); - chars[0x11] = alphabet.get((int) (lsb >>> 0x38 & 0xf)); - chars[0x12] = alphabet.get((int) (lsb >>> 0x34 & 0xf)); - chars[0x13] = alphabet.get((int) (lsb >>> 0x30 & 0xf)); - chars[0x14] = alphabet.get((int) (lsb >>> 0x2c & 0xf)); - chars[0x15] = alphabet.get((int) (lsb >>> 0x28 & 0xf)); - chars[0x16] = alphabet.get((int) (lsb >>> 0x24 & 0xf)); - chars[0x17] = alphabet.get((int) (lsb >>> 0x20 & 0xf)); - chars[0x18] = alphabet.get((int) (lsb >>> 0x1c & 0xf)); - chars[0x19] = alphabet.get((int) (lsb >>> 0x18 & 0xf)); - chars[0x1a] = alphabet.get((int) (lsb >>> 0x14 & 0xf)); - chars[0x1b] = alphabet.get((int) (lsb >>> 0x10 & 0xf)); - chars[0x1c] = alphabet.get((int) (lsb >>> 0x0c & 0xf)); - chars[0x1d] = alphabet.get((int) (lsb >>> 0x08 & 0xf)); - chars[0x1e] = alphabet.get((int) (lsb >>> 0x04 & 0xf)); - chars[0x1f] = alphabet.get((int) (lsb & 0xf)); + chars[0x10] = get(lsb >>> 0x3c & 0xf); + chars[0x11] = get(lsb >>> 0x38 & 0xf); + chars[0x12] = get(lsb >>> 0x34 & 0xf); + chars[0x13] = get(lsb >>> 0x30 & 0xf); + chars[0x14] = get(lsb >>> 0x2c & 0xf); + chars[0x15] = get(lsb >>> 0x28 & 0xf); + chars[0x16] = get(lsb >>> 0x24 & 0xf); + chars[0x17] = get(lsb >>> 0x20 & 0xf); + chars[0x18] = get(lsb >>> 0x1c & 0xf); + chars[0x19] = get(lsb >>> 0x18 & 0xf); + chars[0x1a] = get(lsb >>> 0x14 & 0xf); + chars[0x1b] = get(lsb >>> 0x10 & 0xf); + chars[0x1c] = get(lsb >>> 0x0c & 0xf); + chars[0x1d] = get(lsb >>> 0x08 & 0xf); + chars[0x1e] = get(lsb >>> 0x04 & 0xf); + chars[0x1f] = get(lsb >>> 0x00 & 0xf); return new String(chars); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java index abe50289..f9fe2c81 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base32Encoder.java @@ -55,36 +55,35 @@ public String apply(UUID uuid) { long msb = uuid.getMostSignificantBits(); long lsb = uuid.getLeastSignificantBits(); - chars[0x00] = alphabet.get((int) ((msb >>> 59) & 0b11111)); - chars[0x01] = alphabet.get((int) ((msb >>> 54) & 0b11111)); - chars[0x02] = alphabet.get((int) ((msb >>> 49) & 0b11111)); - chars[0x03] = alphabet.get((int) ((msb >>> 44) & 0b11111)); - chars[0x04] = alphabet.get((int) ((msb >>> 39) & 0b11111)); - chars[0x05] = alphabet.get((int) ((msb >>> 34) & 0b11111)); - chars[0x06] = alphabet.get((int) ((msb >>> 29) & 0b11111)); - chars[0x07] = alphabet.get((int) ((msb >>> 24) & 0b11111)); - chars[0x08] = alphabet.get((int) ((msb >>> 19) & 0b11111)); - chars[0x09] = alphabet.get((int) ((msb >>> 14) & 0b11111)); - chars[0x0a] = alphabet.get((int) ((msb >>> 9) & 0b11111)); - chars[0x0b] = alphabet.get((int) ((msb >>> 4) & 0b11111)); + chars[0x00] = get((msb >>> 59) & 0b11111); + chars[0x01] = get((msb >>> 54) & 0b11111); + chars[0x02] = get((msb >>> 49) & 0b11111); + chars[0x03] = get((msb >>> 44) & 0b11111); + chars[0x04] = get((msb >>> 39) & 0b11111); + chars[0x05] = get((msb >>> 34) & 0b11111); + chars[0x06] = get((msb >>> 29) & 0b11111); + chars[0x07] = get((msb >>> 24) & 0b11111); + chars[0x08] = get((msb >>> 19) & 0b11111); + chars[0x09] = get((msb >>> 14) & 0b11111); + chars[0x0a] = get((msb >>> 9) & 0b11111); + chars[0x0b] = get((msb >>> 4) & 0b11111); - chars[0x0c] = alphabet.get((int) ((msb << 1) & 0b11111) | (int) ((lsb >>> 63) & 0b11111)); + chars[0x0c] = get(((msb << 1) & 0b11111) | ((lsb >>> 63) & 0b11111)); - chars[0x0d] = alphabet.get((int) ((lsb >>> 58) & 0b11111)); - chars[0x0e] = alphabet.get((int) ((lsb >>> 53) & 0b11111)); - chars[0x0f] = alphabet.get((int) ((lsb >>> 48) & 0b11111)); - chars[0x10] = alphabet.get((int) ((lsb >>> 43) & 0b11111)); - chars[0x11] = alphabet.get((int) ((lsb >>> 38) & 0b11111)); - chars[0x12] = alphabet.get((int) ((lsb >>> 33) & 0b11111)); - chars[0x13] = alphabet.get((int) ((lsb >>> 28) & 0b11111)); - chars[0x14] = alphabet.get((int) ((lsb >>> 23) & 0b11111)); - chars[0x15] = alphabet.get((int) ((lsb >>> 18) & 0b11111)); - chars[0x16] = alphabet.get((int) ((lsb >>> 13) & 0b11111)); - chars[0x17] = alphabet.get((int) ((lsb >>> 8) & 0b11111)); - chars[0x18] = alphabet.get((int) ((lsb >>> 3) & 0b11111)); - chars[0x19] = alphabet.get((int) ((lsb << 2) & 0b11111)); + chars[0x0d] = get((lsb >>> 58) & 0b11111); + chars[0x0e] = get((lsb >>> 53) & 0b11111); + chars[0x0f] = get((lsb >>> 48) & 0b11111); + chars[0x10] = get((lsb >>> 43) & 0b11111); + chars[0x11] = get((lsb >>> 38) & 0b11111); + chars[0x12] = get((lsb >>> 33) & 0b11111); + chars[0x13] = get((lsb >>> 28) & 0b11111); + chars[0x14] = get((lsb >>> 23) & 0b11111); + chars[0x15] = get((lsb >>> 18) & 0b11111); + chars[0x16] = get((lsb >>> 13) & 0b11111); + chars[0x17] = get((lsb >>> 8) & 0b11111); + chars[0x18] = get((lsb >>> 3) & 0b11111); + chars[0x19] = get((lsb << 2) & 0b11111); return new String(chars); } - } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java index 0c145968..9cd42401 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/Base64Encoder.java @@ -53,30 +53,30 @@ public String apply(UUID uuid) { long msb = uuid.getMostSignificantBits(); long lsb = uuid.getLeastSignificantBits(); - chars[0x00] = alphabet.get((int) ((msb >>> 58) & 0b111111)); - chars[0x01] = alphabet.get((int) ((msb >>> 52) & 0b111111)); - chars[0x02] = alphabet.get((int) ((msb >>> 46) & 0b111111)); - chars[0x03] = alphabet.get((int) ((msb >>> 40) & 0b111111)); - chars[0x04] = alphabet.get((int) ((msb >>> 34) & 0b111111)); - chars[0x05] = alphabet.get((int) ((msb >>> 28) & 0b111111)); - chars[0x06] = alphabet.get((int) ((msb >>> 22) & 0b111111)); - chars[0x07] = alphabet.get((int) ((msb >>> 16) & 0b111111)); - chars[0x08] = alphabet.get((int) ((msb >>> 10) & 0b111111)); - chars[0x09] = alphabet.get((int) ((msb >>> 4) & 0b111111)); + chars[0x00] = get((msb >>> 58) & 0b111111); + chars[0x01] = get((msb >>> 52) & 0b111111); + chars[0x02] = get((msb >>> 46) & 0b111111); + chars[0x03] = get((msb >>> 40) & 0b111111); + chars[0x04] = get((msb >>> 34) & 0b111111); + chars[0x05] = get((msb >>> 28) & 0b111111); + chars[0x06] = get((msb >>> 22) & 0b111111); + chars[0x07] = get((msb >>> 16) & 0b111111); + chars[0x08] = get((msb >>> 10) & 0b111111); + chars[0x09] = get((msb >>> 4) & 0b111111); - chars[0x0a] = alphabet.get((int) (msb << 2 & 0b111111) | (int) ((lsb >>> 62) & 0b111111)); + chars[0x0a] = get(((msb << 2) & 0b111111) | ((lsb >>> 62) & 0b111111)); - chars[0x0b] = alphabet.get((int) ((lsb >>> 56) & 0b111111)); - chars[0x0c] = alphabet.get((int) ((lsb >>> 50) & 0b111111)); - chars[0x0d] = alphabet.get((int) ((lsb >>> 44) & 0b111111)); - chars[0x0e] = alphabet.get((int) ((lsb >>> 38) & 0b111111)); - chars[0x0f] = alphabet.get((int) ((lsb >>> 32) & 0b111111)); - chars[0x10] = alphabet.get((int) ((lsb >>> 26) & 0b111111)); - chars[0x11] = alphabet.get((int) ((lsb >>> 20) & 0b111111)); - chars[0x12] = alphabet.get((int) ((lsb >>> 14) & 0b111111)); - chars[0x13] = alphabet.get((int) ((lsb >>> 8) & 0b111111)); - chars[0x14] = alphabet.get((int) ((lsb >>> 2) & 0b111111)); - chars[0x15] = alphabet.get((int) ((lsb << 4) & 0b111111)); + chars[0x0b] = get((lsb >>> 56) & 0b111111); + chars[0x0c] = get((lsb >>> 50) & 0b111111); + chars[0x0d] = get((lsb >>> 44) & 0b111111); + chars[0x0e] = get((lsb >>> 38) & 0b111111); + chars[0x0f] = get((lsb >>> 32) & 0b111111); + chars[0x10] = get((lsb >>> 26) & 0b111111); + chars[0x11] = get((lsb >>> 20) & 0b111111); + chars[0x12] = get((lsb >>> 14) & 0b111111); + chars[0x13] = get((lsb >>> 8) & 0b111111); + chars[0x14] = get((lsb >>> 2) & 0b111111); + chars[0x15] = get((lsb << 4) & 0b111111); return new String(chars); } diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java index 3768d0ab..7ce3b891 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/base/function/BaseNEncoder.java @@ -54,4 +54,8 @@ public BaseNEncoder(BaseN base) { this.base = base; this.alphabet = base.getAlphabet(); } + + protected char get(final long index) { + return alphabet.get((int) index); + } } diff --git a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java index 58338476..8f098f10 100644 --- a/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/alt/GUIDTest.java @@ -5,6 +5,7 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.Arrays; import java.util.Random; import java.util.SplittableRandom; @@ -410,6 +411,50 @@ public void testCompareTo() { } } + @Test + public void testProtectedGregorian() { + testProtectedGregorianInstant(Instant.parse("1582-10-15T00:00:00.000Z")); + testProtectedGregorianInstant(Instant.parse("1970-01-01T00:00:00.000Z")); + testProtectedGregorianInstant(Instant.parse("1955-11-12T06:38:00.000Z")); + testProtectedGregorianInstant(Instant.parse("1985-10-26T09:00:00.000Z")); + testProtectedGregorianInstant(Instant.parse("2015-10-21T07:28:00.000Z")); + } + + private static void testProtectedGregorianInstant(Instant instant) { + long epoch = 12219292800L; // seconds since "1582-10-15T00:00:00.000Z" + assertEquals(GUID.gregorian(instant) / 10_000_000L, epoch + instant.getEpochSecond()); + } + + @Test + public void testProtectedHash() { + String name = "THIS IS A TEST"; + GUID guid = GUID.v3(null, name); + UUID uuid = UUID.nameUUIDFromBytes(name.getBytes(StandardCharsets.UTF_8)); + assertEquals(guid.toString(), uuid.toString()); + } + + @Test + public void testProtectedHasher() { + assertNotNull(GUID.hasher("MD5")); + assertNotNull(GUID.hasher("SHA-1")); + try { + GUID.hasher("AAA"); + fail("Should throw exception"); + } catch (IllegalArgumentException e) { + // success + } + } + + @Test + public void testProtectedVersion() { + for (int i = 0; i < 32; i++) { + GUID guid = GUID.version(GUID.NIL.getMostSignificantBits(), GUID.NIL.getLeastSignificantBits(), i); + assertEquals(guid.getMostSignificantBits() & 0xffffffffffff0fffL, 0L); + assertEquals(guid.getLeastSignificantBits() & 0x3fffffffffffffffL, 0L); + assertEquals(guid.version(), i % 16); + } + } + @Test public void testValid() { testValidator((String string) -> { diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java index 611fa008..fbcca884 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java @@ -232,19 +232,19 @@ public void testModifyString() { { // 00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modifyString(string)); + assertEquals(string, StringCodec.modify(string)); } { // urn:uuid:00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modifyString(URN_PREFIX + string)); + assertEquals(string, StringCodec.modify(URN_PREFIX + string)); } { // {00000000-0000-0000-0000-000000000000} String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modifyString("{" + string + "}")); + assertEquals(string, StringCodec.modify("{" + string + "}")); } } From 77f69b7f77b3dd308f14d6db19e7c1046a1a3292 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 19:54:19 -0300 Subject: [PATCH 29/40] Rename StringCodec and BinaryCodec Changes: * BinaryCodec -> StandardBinaryCodec * StringCodec -> StandardStringCodec --- .../com/github/f4b6a3/uuid/UuidCreator.java | 12 ++--- ...aryCodec.java => StandardBinaryCodec.java} | 6 ++- ...ingCodec.java => StandardStringCodec.java} | 25 +++++----- .../github/f4b6a3/uuid/codec/UriCodec.java | 2 +- .../github/f4b6a3/uuid/codec/UrnCodec.java | 4 +- .../f4b6a3/uuid/codec/other/NcnameCodec.java | 10 ++-- .../f4b6a3/uuid/factory/UuidFactory.java | 8 ++-- .../f4b6a3/uuid/codec/BinaryCodecTest.java | 10 ++-- .../f4b6a3/uuid/codec/StringCodecTest.java | 16 +++---- .../uuid/codec/base/BaseNCodec1Test.java | 4 +- .../function/BaseNRemainderDecoderTest.java | 8 ++-- .../function/BaseNRemainderEncoderTest.java | 4 +- .../uuid/codec/other/SlugCodecTest.java | 4 +- .../f4b6a3/uuid/factory/UuidFactoryTest.java | 4 +- .../f4b6a3/uuid/util/UuidComparatorTest.java | 46 +++++++++---------- 15 files changed, 84 insertions(+), 79 deletions(-) rename src/main/java/com/github/f4b6a3/uuid/codec/{BinaryCodec.java => StandardBinaryCodec.java} (93%) rename src/main/java/com/github/f4b6a3/uuid/codec/{StringCodec.java => StandardStringCodec.java} (90%) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index 1292012d..c9083f53 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -32,8 +32,8 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; -import com.github.f4b6a3.uuid.codec.BinaryCodec; -import com.github.f4b6a3.uuid.codec.StringCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardStringCodec; import com.github.f4b6a3.uuid.enums.UuidLocalDomain; import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.exception.InvalidUuidException; @@ -135,7 +135,7 @@ public static UUID getMax() { * @throws InvalidUuidException if the argument is invalid */ public static byte[] toBytes(final UUID uuid) { - return BinaryCodec.INSTANCE.encode(uuid); + return StandardBinaryCodec.INSTANCE.encode(uuid); } /** @@ -148,7 +148,7 @@ public static byte[] toBytes(final UUID uuid) { * @throws InvalidUuidException if the argument is invalid */ public static UUID fromBytes(byte[] uuid) { - return BinaryCodec.INSTANCE.decode(uuid); + return StandardBinaryCodec.INSTANCE.decode(uuid); } /** @@ -161,7 +161,7 @@ public static UUID fromBytes(byte[] uuid) { * @throws InvalidUuidException if the argument is invalid */ public static String toString(UUID uuid) { - return StringCodec.INSTANCE.encode(uuid); + return StandardStringCodec.INSTANCE.encode(uuid); } /** @@ -184,7 +184,7 @@ public static String toString(UUID uuid) { * @throws InvalidUuidException if the argument is invalid */ public static UUID fromString(String uuid) { - return StringCodec.INSTANCE.decode(uuid); + return StandardStringCodec.INSTANCE.decode(uuid); } /** diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StandardBinaryCodec.java similarity index 93% rename from src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java rename to src/main/java/com/github/f4b6a3/uuid/codec/StandardBinaryCodec.java index 1614804d..c2a0292d 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/BinaryCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StandardBinaryCodec.java @@ -33,13 +33,15 @@ * Codec for UUID binary encoding as defined in the RFC-4122. *

* The UUID is encoded as 16 octets (bytes). + *

+ * Read: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-format */ -public class BinaryCodec implements UuidCodec { +public class StandardBinaryCodec implements UuidCodec { /** * A shared immutable instance. */ - public static final BinaryCodec INSTANCE = new BinaryCodec(); + public static final StandardBinaryCodec INSTANCE = new StandardBinaryCodec(); /** * Get an array of bytes from a UUID. diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/StandardStringCodec.java similarity index 90% rename from src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java rename to src/main/java/com/github/f4b6a3/uuid/codec/StandardStringCodec.java index e048fabf..c3c11669 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/StringCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/StandardStringCodec.java @@ -33,34 +33,37 @@ import com.github.f4b6a3.uuid.util.internal.JavaVersionUtil; /** - * Codec for UUID string representation as defined in RFC-4122. + * Codec for UUID canonical string as defined in RFC-4122. *

- * The string representation, also referred as canonical textual representation, - * is a string of 32 hexadecimal (base-16) digits, displayed in five groups + * In the canonical textual representation, the 16 bytes of a UUID are + * represented as 32 hexadecimal (base-16) digits, displayed in five groups * separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 * hexadecimal characters and 4 hyphens). *

- * This codec decodes (parses) strings in these formats, with/without hyphens: + * This codec decodes (parses) strings in these formats: *

    - *
  • 00000000-0000-V000-0000-000000000000 (canonical string) - *
  • {00000000-0000-V000-0000-000000000000} (MS GUID string) - *
  • urn:uuid:00000000-0000-V000-0000-000000000000 (URN UUID string) + *
  • 000000000000V0000000000000000000 (hexadecimal string) + *
  • 00000000-0000-0000-0000-000000000000 (THE canonical string) + *
  • {00000000-0000-0000-0000-000000000000} (Microsoft string) + *
  • urn:uuid:00000000-0000-0000-0000-000000000000 (URN string) *
*

* The encoding and decoding processes can be much faster (7x) than * {@link UUID#toString()} and {@link UUID#fromString(String)} in JDK 8. *

* If you prefer a string representation without hyphens, use - * {@link Base16Codec} instead of {@link StringCodec}. {@link Base16Codec} can - * be much faster (22x) than doing + * {@link Base16Codec} instead of {@link StandardStringCodec}. + * {@link Base16Codec} can be much faster (22x) than doing * uuid.toString().replaceAll("-", ""). + *

+ * Read: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-format */ -public class StringCodec implements UuidCodec { +public class StandardStringCodec implements UuidCodec { /** * A shared immutable instance. */ - public static final StringCodec INSTANCE = new StringCodec(); + public static final StandardStringCodec INSTANCE = new StandardStringCodec(); private static final int DASH_POSITION_1 = 8; private static final int DASH_POSITION_2 = 13; diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java index 0fa4e37f..f8928881 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/UriCodec.java @@ -81,7 +81,7 @@ public UUID decode(URI uri) { if (!isUuidUri(uri)) { throw InvalidUuidException.newInstance(uri); } - return StringCodec.INSTANCE.decode(uri.toString()); + return StandardStringCodec.INSTANCE.decode(uri.toString()); } /** diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java index 49a1b0bf..c281344a 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/UrnCodec.java @@ -66,7 +66,7 @@ public class UrnCodec implements UuidCodec { @Override public String encode(UUID uuid) { UuidValidator.validate(uuid); - return URN_PREFIX + StringCodec.INSTANCE.encode(uuid); + return URN_PREFIX + StandardStringCodec.INSTANCE.encode(uuid); } /** @@ -81,7 +81,7 @@ public UUID decode(String urn) { if (!isUuidUrn(urn)) { throw InvalidUuidException.newInstance(urn); } - return StringCodec.INSTANCE.decode(urn); + return StandardStringCodec.INSTANCE.decode(urn); } /** diff --git a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java index 8126c256..96092966 100644 --- a/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java +++ b/src/main/java/com/github/f4b6a3/uuid/codec/other/NcnameCodec.java @@ -27,7 +27,7 @@ import java.util.Arrays; import java.util.UUID; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.UuidCodec; import com.github.f4b6a3.uuid.codec.base.Base32Codec; import com.github.f4b6a3.uuid.codec.base.Base64UrlCodec; @@ -175,7 +175,7 @@ public String encode(UUID uuid) { UuidValidator.validate(uuid); int version = uuid.version(); - byte[] bytes = BinaryCodec.INSTANCE.encode(uuid); + byte[] bytes = StandardBinaryCodec.INSTANCE.encode(uuid); int[] ints = ByteUtil.toInts(bytes); int variant = (ints[2] & 0xf0000000) >>> 24; @@ -187,7 +187,7 @@ public String encode(UUID uuid) { bytes = ByteUtil.fromInts(ints); bytes[15] = (byte) ((bytes[15] & 0xff) >>> this.shift); - UUID uuuu = BinaryCodec.INSTANCE.decode(bytes); + UUID uuuu = StandardBinaryCodec.INSTANCE.decode(bytes); String encoded = this.codec.encode(uuuu).substring(0, this.length - 1); // if base is 64, use upper case version, else use lower case @@ -222,7 +222,7 @@ public UUID decode(String ncname) { String substring = ncname.substring(1, ncname.length()); UUID uuid = this.codec.decode(substring + padding); - byte[] bytes = BinaryCodec.INSTANCE.encode(uuid); + byte[] bytes = StandardBinaryCodec.INSTANCE.encode(uuid); bytes[15] = (byte) ((bytes[15] & 0xff) << this.shift); int[] ints = ByteUtil.toInts(bytes); @@ -237,6 +237,6 @@ public UUID decode(String ncname) { bytes = ByteUtil.fromInts(ints); - return BinaryCodec.INSTANCE.decode(bytes); + return StandardBinaryCodec.INSTANCE.decode(bytes); } } diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java index dcf7a09c..eff1bfb4 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/UuidFactory.java @@ -29,8 +29,8 @@ import java.util.Objects; import java.util.UUID; -import com.github.f4b6a3.uuid.codec.BinaryCodec; -import com.github.f4b6a3.uuid.codec.StringCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardStringCodec; import com.github.f4b6a3.uuid.enums.UuidLocalDomain; import com.github.f4b6a3.uuid.enums.UuidNamespace; import com.github.f4b6a3.uuid.enums.UuidVersion; @@ -354,7 +354,7 @@ protected static byte[] namespaceBytes(UuidNamespace namespace) { */ protected static byte[] namespaceBytes(UUID namespace) { if (namespace != null) { - return BinaryCodec.INSTANCE.encode(namespace); + return StandardBinaryCodec.INSTANCE.encode(namespace); } return null; // the name space can be null } @@ -368,7 +368,7 @@ protected static byte[] namespaceBytes(UUID namespace) { */ protected static byte[] namespaceBytes(String namespace) { if (namespace != null) { - return BinaryCodec.INSTANCE.encode(StringCodec.INSTANCE.decode(namespace)); + return StandardBinaryCodec.INSTANCE.encode(StandardStringCodec.INSTANCE.decode(namespace)); } return null; // the name space can be null } diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/BinaryCodecTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/BinaryCodecTest.java index da33b5eb..c4e4a175 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/BinaryCodecTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/BinaryCodecTest.java @@ -16,7 +16,7 @@ public class BinaryCodecTest { @Test public void testEncode() { - BinaryCodec codec = new BinaryCodec(); + StandardBinaryCodec codec = new StandardBinaryCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { // UuidCreator.toBytes(); @@ -44,7 +44,7 @@ public void testEncode() { @Test public void testDecode() { - BinaryCodec codec = new BinaryCodec(); + StandardBinaryCodec codec = new StandardBinaryCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { // UuidCreator.fromBytes(); @@ -72,7 +72,7 @@ public void testDecode() { @Test public void testEncodeAndDecode() { - final BinaryCodec codec = new BinaryCodec(); + final StandardBinaryCodec codec = new StandardBinaryCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { UUID uuid = UUID.randomUUID(); @@ -84,7 +84,7 @@ public void testEncodeAndDecode() { @Test public void testEncodeInvalidUuidException() { - BinaryCodec codec = new BinaryCodec(); + StandardBinaryCodec codec = new StandardBinaryCodec(); { try { @@ -118,7 +118,7 @@ public void testEncodeInvalidUuidException() { @Test public void testDecodeInvalidUuidException() { - BinaryCodec codec = new BinaryCodec(); + StandardBinaryCodec codec = new StandardBinaryCodec(); { try { diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java index fbcca884..0b4b13a0 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/StringCodecTest.java @@ -21,7 +21,7 @@ public class StringCodecTest { @Test public void testEncode() { - StringCodec codec = new StringCodec(); + StandardStringCodec codec = new StandardStringCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { // UuidCreator.toString(); @@ -45,7 +45,7 @@ public void testEncode() { @Test public void testDecode() { - StringCodec codec = new StringCodec(); + StandardStringCodec codec = new StandardStringCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { // UuidCreator.fromString(); @@ -100,7 +100,7 @@ public void testDecode() { @Test public void testEncodeAndDecode() { - final StringCodec codec = new StringCodec(); + final StandardStringCodec codec = new StandardStringCodec(); for (int i = 0; i < DEFAULT_LOOP_LIMIT; i++) { UUID uuid = UUID.randomUUID(); @@ -112,7 +112,7 @@ public void testEncodeAndDecode() { @Test public void testEncodeInvalidUuidException() { - StringCodec codec = new StringCodec(); + StandardStringCodec codec = new StandardStringCodec(); { try { @@ -146,7 +146,7 @@ public void testEncodeInvalidUuidException() { @Test public void testDecodeInvalidUuidException() { - StringCodec codec = new StringCodec(); + StandardStringCodec codec = new StandardStringCodec(); try { String string = new UUID(0L, 0L).toString(); @@ -232,19 +232,19 @@ public void testModifyString() { { // 00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modify(string)); + assertEquals(string, StandardStringCodec.modify(string)); } { // urn:uuid:00000000-0000-0000-0000-000000000000 String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modify(URN_PREFIX + string)); + assertEquals(string, StandardStringCodec.modify(URN_PREFIX + string)); } { // {00000000-0000-0000-0000-000000000000} String string = UUID.randomUUID().toString(); - assertEquals(string, StringCodec.modify("{" + string + "}")); + assertEquals(string, StandardStringCodec.modify("{" + string + "}")); } } diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec1Test.java b/src/test/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec1Test.java index 1c901154..4729970d 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec1Test.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/base/BaseNCodec1Test.java @@ -3,7 +3,7 @@ import static org.junit.Assert.*; import org.junit.Test; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.UuidCodec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; @@ -16,7 +16,7 @@ public class BaseNCodec1Test { private static final int DEFAULT_LOOP_LIMIT = 100; - private static final UuidCodec CODEC_BYTES = new BinaryCodec(); + private static final UuidCodec CODEC_BYTES = new StandardBinaryCodec(); // Alphabet used by BigInteger.toString(32); protected static final char[] ALPHABET_JAVA = "0123456789abcdefghijklmnopqrstuv".toCharArray(); diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java index 621f18c7..ef3001e1 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderDecoderTest.java @@ -10,7 +10,7 @@ import org.junit.Test; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.base.Base62Codec; import com.github.f4b6a3.uuid.codec.base.BaseN; @@ -23,7 +23,7 @@ public void testDecode() { for (int i = 0; i < 1000; i++) { String string = getRandomString(Base62Codec.INSTANCE.getBase()); UUID uuid = Base62Codec.INSTANCE.decode(string); - byte[] bytes = BinaryCodec.INSTANCE.encode(uuid); + byte[] bytes = StandardBinaryCodec.INSTANCE.encode(uuid); assertEquals(Arrays.toString(decode(Base62Codec.INSTANCE.getBase(), string)), Arrays.toString(bytes)); } } @@ -68,13 +68,13 @@ public void testMultiply() { } protected static long[] toLongs(byte[] bytes) { - UUID uuid = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid = StandardBinaryCodec.INSTANCE.decode(bytes); return new long[] { uuid.getMostSignificantBits(), uuid.getLeastSignificantBits() }; } protected static byte[] fromLongs(long[] longs) { UUID uuid = new UUID(longs[0], longs[1]); - return BinaryCodec.INSTANCE.encode(uuid); + return StandardBinaryCodec.INSTANCE.encode(uuid); } private String getRandomString(BaseN base) { diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java index 1a1d6538..4a59a152 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/base/function/BaseNRemainderEncoderTest.java @@ -9,7 +9,7 @@ import org.junit.Test; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.base.Base62Codec; import com.github.f4b6a3.uuid.codec.base.BaseN; import com.github.f4b6a3.uuid.codec.base.BaseNCodec.CustomDivider; @@ -27,7 +27,7 @@ public void testEncode() { for (int i = 0; i < 1000; i++) { byte[] bytes = new byte[UUID_BYTES]; (new Random(seeder.nextLong())).nextBytes(bytes); - UUID uuid = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid = StandardBinaryCodec.INSTANCE.decode(bytes); String string = Base62Codec.INSTANCE.encode(uuid); assertEquals(encode(Base62Codec.INSTANCE.getBase(), bytes), string); } diff --git a/src/test/java/com/github/f4b6a3/uuid/codec/other/SlugCodecTest.java b/src/test/java/com/github/f4b6a3/uuid/codec/other/SlugCodecTest.java index fab4301a..9edcff1c 100644 --- a/src/test/java/com/github/f4b6a3/uuid/codec/other/SlugCodecTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/codec/other/SlugCodecTest.java @@ -4,7 +4,7 @@ import org.junit.Test; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.UuidCodec; import com.github.f4b6a3.uuid.exception.InvalidUuidException; @@ -16,7 +16,7 @@ public class SlugCodecTest { private static final int DEFAULT_LOOP_LIMIT = 100; - private static final UuidCodec CODEC_BYTES = new BinaryCodec(); + private static final UuidCodec CODEC_BYTES = new StandardBinaryCodec(); @Test public void testEncode() { diff --git a/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java b/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java index f3b2bb43..3c0c4134 100644 --- a/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/factory/UuidFactoryTest.java @@ -1,7 +1,7 @@ package com.github.f4b6a3.uuid.factory; import com.github.f4b6a3.uuid.UuidCreator; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.UuidCodec; import com.github.f4b6a3.uuid.factory.function.NodeIdFunction; import com.github.f4b6a3.uuid.util.UuidUtil; @@ -19,7 +19,7 @@ public abstract class UuidFactoryTest { protected static final String DUPLICATE_UUID_MSG = "A duplicate UUID was created"; - private static final UuidCodec bytesCodec = new BinaryCodec(); + private static final UuidCodec bytesCodec = new StandardBinaryCodec(); protected static final int THREAD_TOTAL = availableProcessors(); diff --git a/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java b/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java index ce956ee3..91f11acd 100644 --- a/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java +++ b/src/test/java/com/github/f4b6a3/uuid/util/UuidComparatorTest.java @@ -9,7 +9,7 @@ import org.junit.Test; -import com.github.f4b6a3.uuid.codec.BinaryCodec; +import com.github.f4b6a3.uuid.codec.StandardBinaryCodec; import com.github.f4b6a3.uuid.codec.other.TimeOrderedCodec; public class UuidComparatorTest { @@ -80,13 +80,13 @@ public void testCompareDefault() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid1 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid2 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); - UUID uuid3 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -107,13 +107,13 @@ public void testCompareDefault() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(zero).putLong(random.nextLong()).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid1 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(zero).putLong(random.nextLong()).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid2 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); - UUID uuid3 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -134,13 +134,13 @@ public void testCompareDefault() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(zero).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid1 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(zero).array(); bytes = setVersion(bytes, 1); // set version 1 - UUID uuid2 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); - UUID uuid3 = BinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(rearrange(bytes)); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -168,12 +168,12 @@ public void testCompareOpaque() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); - UUID uuid1 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(random.nextLong()).array(); - UUID uuid2 = BinaryCodec.INSTANCE.decode(bytes); - UUID uuid3 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(bytes); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -190,12 +190,12 @@ public void testCompareOpaque() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(zero).putLong(random.nextLong()).array(); - UUID uuid1 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(zero).putLong(random.nextLong()).array(); - UUID uuid2 = BinaryCodec.INSTANCE.decode(bytes); - UUID uuid3 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(bytes); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -212,12 +212,12 @@ public void testCompareOpaque() { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(zero).array(); - UUID uuid1 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid1 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number1 = new BigInteger(1, bytes); bytes = ByteBuffer.allocate(16).putLong(random.nextLong()).putLong(zero).array(); - UUID uuid2 = BinaryCodec.INSTANCE.decode(bytes); - UUID uuid3 = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid2 = StandardBinaryCodec.INSTANCE.decode(bytes); + UUID uuid3 = StandardBinaryCodec.INSTANCE.decode(bytes); BigInteger number2 = new BigInteger(1, bytes); BigInteger number3 = new BigInteger(1, bytes); @@ -234,16 +234,16 @@ public void testCompareOpaque() { } private byte[] setVersion(byte[] bytes, int version) { - UUID uuid = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid = StandardBinaryCodec.INSTANCE.decode(bytes); uuid = UuidUtil.setVersion(uuid, version); - return BinaryCodec.INSTANCE.encode(uuid); + return StandardBinaryCodec.INSTANCE.encode(uuid); } private byte[] rearrange(byte[] bytes) { - UUID uuid = BinaryCodec.INSTANCE.decode(bytes); + UUID uuid = StandardBinaryCodec.INSTANCE.decode(bytes); uuid = UuidUtil.setVersion(uuid, 6); uuid = TimeOrderedCodec.INSTANCE.decode(uuid); uuid = UuidUtil.setVersion(uuid, 1); - return BinaryCodec.INSTANCE.encode(uuid); + return StandardBinaryCodec.INSTANCE.encode(uuid); } } From 0446bc5519036f5a7677b1a5356c6b7cf3e08478 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 21:29:54 -0300 Subject: [PATCH 30/40] Update README.md --- README.md | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 37b0d261..e75747e6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ - - UUID Creator ====================================================== This is a Java library for generating [Universally Unique Identifiers](https://en.wikipedia.org/wiki/Universally_unique_identifier). -The Internet standard [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562) was published in May 2024, making RFC 4122 obsolete. This library is fully compliant with the new RFC, as it was developed following the evolution of the new standard until its publication. +This library is fully compliant with [RFC 9562](https://www.rfc-editor.org/rfc/rfc9562), the Internet standard which obsoletes [RFC 4122](https://www.rfc-editor.org/rfc/rfc9562). List of implemented UUID subtypes: @@ -21,21 +19,21 @@ This library solves some of the JDK's UUID issues: | Problem | Solution | |---------|----------| -| `UUID` can't generate Gregorian time-based UUIDs (UUIDv1). | Use:

  • [`UuidCreator.getTimeBased()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getTimeBased()); or
  • [`GUID.v1()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#v1()).
| -| `UUID` can't generate SHA-1 UUIDs (UUIDv5). | Use:
  • [`UuidCreator.getNameBasedSha1()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getNameBasedSha1(java.util.UUID,java.lang.String)); or
  • [`GUID.v5()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#v5(com.github.f4b6a3.uuid.alt.GUID,java.lang.String)).
| -| `UUID` has no validation method, which makes developers use `UUID.fromString()` or regular expression for validation. | Use:
  • [`UuidValidator.isValid()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/util/UuidValidator.html#isValid(java.lang.String)); or
  • [`GUID.valid()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#valid(java.lang.String)).
| -| `UUID.nameUUIDFromBytes()`, which generates MD5 UUIDs (UUIDv3), does not have a namespace parameter as required by the standard. | Use:
  • [`UuidCreator.getNameBasedMd5()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getNameBasedMd5(java.util.UUID,java.lang.String)); or
  • [`GUID.v3()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#v3(com.github.f4b6a3.uuid.alt.GUID,java.lang.String)).
| +| `UUID` can't generate Gregorian time-based UUIDs (UUIDv1). | Use [`UuidCreator.getTimeBased()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getTimeBased()). | +| `UUID` can't generate SHA-1 UUIDs (UUIDv5). | Use [`UuidCreator.getNameBasedSha1()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getNameBasedSha1(java.util.UUID,java.lang.String)) | +| `UUID.nameUUIDFromBytes()`, which generates MD5 UUIDs (UUIDv3), does not have a namespace parameter as required by the standard. | Use [`UuidCreator.getNameBasedMd5()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getNameBasedMd5(java.util.UUID,java.lang.String)) | +| `UUID` has no validation method, which makes developers use `UUID.fromString()` or regular expression for validation. | Use [`UuidValidator.isValid()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/util/UuidValidator.html#isValid(java.lang.String)). | | Some methods such as `UUID.timestamp()` are strongly related to UUIDv1, even though it's impossible to generate UUIDv1. | Use [`UuidUtil`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/util/UuidUtil.html). | -| `UUID.randomUUID()` can be slow due to [lack of entropy](https://medium.com/@RamLakshmanan/java-uuid-generation-performance-impact-cec888b7d9b8) in the operating system. | Use:
  • [`UuidCreator.getRandomBasedFast()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getRandomBasedFast()); or
  • [`GUID.v4()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#v4()).
However, keep in mind that none of them are cryptographically secure. | +| `UUID.randomUUID()` can be slow due to [lack of entropy](https://medium.com/@RamLakshmanan/java-uuid-generation-performance-impact-cec888b7d9b8) in the operating system. | Use [`UuidCreator.getRandomBasedFast()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#getRandomBasedFast()).
However, keep in mind that it is not cryptographically secure. | | `UUID.compareTo()` [behaves unexpectedly](https://yoshiori.hatenablog.com/entry/2024/02/22/173322) due to signed `long` comparisons, causing non-alphabetical sorting. | Use [`UuidComparator`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/util/UuidComparator.html). | -| `UUID.fromString()` allows non-canonical strings like `0-0-0-0-0` as valid UUID strings. | Use:
  • [`UuidCreator.fromString()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#fromString(java.lang.String)); or
  • [`new GUID()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/alt/GUID.html#%3Cinit%3E(java.lang.String)).
| +| `UUID.fromString()` allows non-standard strings like `0-0-0-0-0` as valid UUID strings. | Use [`UuidCreator.fromString()`](https://javadoc.io/static/com.github.f4b6a3/uuid-creator/5.3.7/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html#fromString(java.lang.String)). | -This project contains a [micro benchmark](https://github.com/f4b6a3/uuid-creator/tree/master/benchmark) and a good amount of [unit tests](https://github.com/f4b6a3/uuid-creator/tree/master/src/test/java/com/github/f4b6a3/uuid). +This project contains a [micro benchmark](https://github.com/f4b6a3/uuid-creator/tree/master/benchmark) and a good amount of [unit tests](https://github.com/f4b6a3/uuid-creator/tree/master/src/test/java/com/github/f4b6a3/uuid), with more than 90% coverage. -Read the [Wiki pages](https://github.com/f4b6a3/uuid-creator/wiki) and the [Javadocs](https://javadoc.io/doc/com.github.f4b6a3/uuid-creator). +For more information, read the the [Javadocs](https://javadoc.io/doc/com.github.f4b6a3/uuid-creator) and the [Wiki pages](https://github.com/f4b6a3/uuid-creator/wiki). > **NOTE**: -> This software is not supported or maintained by any organization. This information may be useful if you believe that having an organization behind a project is a criterion for deciding whether software can be adopted or not. +> This software is not supported or maintained by any organization. This information may be useful when having an organization behind a project is a criterion for deciding whether software can be adopted or not. Dependency ------------------------------------------------------ @@ -71,9 +69,9 @@ Module and bundle names are the same as the root package name. Usage ------------------------------------------------------ -All UUID types can be created from the facade [`UuidCreator`](https://javadoc.io/doc/com.github.f4b6a3/uuid-creator/latest/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html). +All UUID subtypes can be created from the facade [`UuidCreator`](https://javadoc.io/doc/com.github.f4b6a3/uuid-creator/latest/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html). -The goal of this class is to make most of the library's functionality available in a single place so that you developers don't have to worry about the internals of the library. All you need is to decide which type of UUID you need for your application and call the respective generation method. If in doubt, read the documentation and check the source code. +The goal of the facade is to make most of the library's functionality available in a single place so that you don't have to worry about the internals of the library. All you need is to decide which UUID subtype you need for your application and call the respective generation method. If in doubt, read the documentation and check out the source code. Create a [UUIDv1](https://github.com/f4b6a3/uuid-creator/wiki/1.1.-UUIDv1): @@ -119,9 +117,6 @@ UUID uuid = UuidCreator.getTimeOrderedEpoch(); > **NOTE:** > A UUID version is a [**UUID subtype**](https://www.rfc-editor.org/rfc/rfc9562#name-iana-uuid-subtype-registry-). The word "version" is not used in the sense that a higher version number makes the previous one obsolete. There are 8 subtypes of UUID and each of them is assigned a number; for example, a UUIDv7 is a UUID of subtype 7. Likewise, a UUID variant is a [**UUID type**](https://www.rfc-editor.org/rfc/rfc9562#section-4.1). There are 4 types of UUID: (1) the prehistoric one, (2) the one described in RFC 9562, (3) the one belonging to Microsoft and (4) the one reserved for the future. RFC 9562 retains the terms “version” and “variant” for compatibility with previous specifications and existing implementations. -> **PERSONAL NOTE:** -> The library can do a lot more than the examples above (much more than I should have done). So I sincerely hope that most people are satisfied with this. In other words, your like is my payment. Anther thing I want to say is that the name of this software is UUID Creator or uuid-creator. Use "f4b6a3" or "com.github.f4b6a3" only when necessary to avoid doubt, as this is just a unique package name to follow Java convention (I know it wasn't a good idea, but I can't change it anymore). - Alternative API ------------------------------------------------------ @@ -129,8 +124,6 @@ Alternative API This new API was also designed to be an alternative to [`UuidCreator`](https://javadoc.io/doc/com.github.f4b6a3/uuid-creator/latest/com.github.f4b6a3.uuid/com/github/f4b6a3/uuid/UuidCreator.html) with three goals in mind: clean interface, simple implementation, and high performance. It was inspired by popular libraries for [Javascript](https://www.npmjs.com/package/uuid) and [Python](https://docs.python.org/3/library/uuid.html). -Additionaly, it does not block during GUID generation due to the **non-cryptographic** random number generator used by its factory methods. However, it is not recommended when the security of “cryptographic quality” generators is considered necessary. - ```java GUID guid = GUID.v1(); ``` @@ -153,7 +146,10 @@ GUID guid = GUID.v6(); GUID guid = GUID.v7(); ``` -### Generate JDK's UUID from GUID's API +> **NOTE:** +> It uses a **non-cryptographic** PRNG. So it doesn't block when generating random-based UUIDs. However, it is not recommended when the security provided by “cryptographic quality” generators is considered necessary. + +### Generate JDK's UUID using the alternative API You can generate JDK's UUIDs using GUID's API. For example, you can generate a JDK's UUID version 7 with this simple statement: @@ -163,13 +159,6 @@ UUID uuid = GUID.v7().toUUID(); When you call `toUUID()` the internal value of GUID is copied to the new JDK's UUID. -Deprecation ------------------------------------------------------- - -The methods which use a UUID as a "name" parameter such as [`UuidCreator.getNameBasedMd5(UUID name)`](https://github.com/f4b6a3/uuid-creator/blob/79e049eeeb43a7cd288f4c73f0d0daa6c339c7d6/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java#L656) are **deprecated**. They will be removed soon after the new RFC is published. For more details, please read https://github.com/f4b6a3/uuid-creator/issues/91. - -The [`v8()`](https://github.com/f4b6a3/uuid-creator/blob/master/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java#L355) method of the alternative [`GUID`](https://github.com/f4b6a3/uuid-creator/blob/master/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java) class is also **deprecated** and will be removed soon. - Other identifier generators ------------------------------------------------------ @@ -183,3 +172,9 @@ License ------------------------------------------------------ This library is Open Source software released under the [MIT license](https://opensource.org/licenses/MIT). + +------------------------------------------------------ + +_Personal Notes:_ +1. _The library can do much more than the examples shown in this document (much more than I should have done). I hope most people find this project useful. In other words, your like is my payment._ +2. _The name of this software is UUID Creator or uuid-creator. Use "com.github.f4b6a3" or "f4b6a3" only when necessary to avoid doubt, as this is just a unique package name to follow Java convention (now I know it wasn't a good idea)._ From 6270f1b7e5dbff7d6f5509051a72c6c4cbdd6237 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 21:30:45 -0300 Subject: [PATCH 31/40] Update CREDITS.md Thanks! --- CREDITS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.md b/CREDITS.md index 6d257c46..6f5e3d92 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -18,3 +18,4 @@ The people who contributed to this open source project. * [Adam Gent](https://github.com/agentgt) * [BaoHo](https://github.com/tri-bao) * [Nicola](https://github.com/nicolarosada) +* [Jay Patel](https://github.com/pateljay15) From a2555007e8de9f6d7cb5364a5203207914afd125 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 22:07:24 -0300 Subject: [PATCH 32/40] Update CHANGELOG.md --- CHANGELOG.md | 22 ++++++++++++++++++---- README.md | 4 ++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f853d29e..c2101ebf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ All notable changes to this project will be documented in this file. Nothing unreleased. +## [6.0.0] - 2024-07-07 + +This version has breaking changes. + +- Added `UuidBuilder` as a helper for generating custom UUIDs (UUIDv8); +- Renamed `StringCodec` to `StandardStringCodec`; +- Renamed `BinaryCodec` to `StandardBinaryCodec`; +- Removed `GUID.v8()` (deprecated); +- Removed `UuidCreator.getNameBasedMD5()` with `UUID` as name parameter (deprecated); +- Removed `UuidCreator.getNameBasedSHA1()` with `UUID` as name parameter (deprecated); +- Removed several code-smells in order improve code-quality and adhere to SOLID principles (by Jay Patel); +- Many refactorings and optimizations. + ## [5.3.7] - 2023-12-22 Regular maintenance. @@ -71,7 +84,7 @@ Add support for `RandomGenerator` in Java 17. #70 Please go to v5.2.0 due to incorrect MAX UUID. -This version contains has breaking changes. +This version has breaking changes. - Added Max UUID (**wrong!**, fixed in v5.2.0). #67 - Added implementations for UUID v7. #67 @@ -368,7 +381,7 @@ Change name-based generators to prevent thread contention #26 - Update javadoc - Coverage: 85.8% -### Remoded +### Removed Remove `TlsSecureRandom` // replaced by SharedRandom Remove `NetworkData` // too much properties Remove `Fingerprint` // too complex @@ -390,14 +403,15 @@ Remove `Fingerprint` // too complex - Updated javadoc - Test coverage: 87.4% -### Remoded +### Removed - Removed UuidCreatorException // used by overrun exception - Removed IllegalUuidException // use IllegalArgumentException instead - Removed UuidSettings.getNodeIdentifierDeprecated // remove deprecated - Renamed UuidSettings to UuidCreatorSettings -[unreleased]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-5.3.7...HEAD +[unreleased]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-6.0.0...HEAD +[6.0.0]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-5.3.7...uuid-creator-6.0.0 [5.3.7]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-5.3.6...uuid-creator-5.3.7 [5.3.6]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-5.3.5...uuid-creator-5.3.6 [5.3.5]: https://github.com/f4b6a3/uuid-creator/compare/uuid-creator-5.3.4...uuid-creator-5.3.5 diff --git a/README.md b/README.md index e75747e6..6e196aae 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,14 @@ Maven: com.github.f4b6a3 uuid-creator - 5.3.7 + 6.0.0 ``` Gradle: ``` -implementation 'com.github.f4b6a3:uuid-creator:5.3.3' +implementation 'com.github.f4b6a3:uuid-creator:6.0.0' ``` See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/uuid-creator). From cc1c808df7972bec4ac511f09489695f15adf402 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sat, 6 Jul 2024 22:29:37 -0300 Subject: [PATCH 33/40] Rename path component `rfc4122` to `standard` --- .../com/github/f4b6a3/uuid/UuidCreator.java | 22 +++++++++---------- .../DceSecurityFactory.java | 2 +- .../NameBasedMd5Factory.java | 2 +- .../NameBasedSha1Factory.java | 2 +- .../RandomBasedFactory.java | 4 ++-- .../TimeBasedFactory.java | 2 +- .../TimeOrderedEpochFactory.java | 2 +- .../TimeOrderedFactory.java | 2 +- .../com/github/f4b6a3/uuid/TestSuite.java | 14 ++++++------ .../factory/AbstRandomBasedFactoryTest.java | 2 +- .../impl/DefaultClockSeqFunctionTest.java | 2 +- .../DceSecurityFactoryTest.java | 2 +- .../NameBasedMd5FactoryTest.java | 2 +- .../NameBasedSha1FactoryTest.java | 2 +- .../RandomBasedFactoryTest.java | 2 +- .../TimeBasedFactoryTest.java | 2 +- .../TimeOrderedEpochFactoryTest.java | 2 +- .../TimeOrderedFactoryTest.java | 2 +- .../f4b6a3/uuid/uniq/UniquenessTest1.java | 2 +- .../f4b6a3/uuid/uniq/UniquenessTest2.java | 2 +- .../f4b6a3/uuid/uniq/UniquenessTest3.java | 2 +- .../github/f4b6a3/uuid/util/UuidUtilTest.java | 6 ++--- 22 files changed, 41 insertions(+), 41 deletions(-) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/DceSecurityFactory.java (99%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/NameBasedMd5Factory.java (97%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/NameBasedSha1Factory.java (97%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/RandomBasedFactory.java (96%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeBasedFactory.java (97%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeOrderedEpochFactory.java (99%) rename src/main/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeOrderedFactory.java (98%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/DceSecurityFactoryTest.java (97%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/NameBasedMd5FactoryTest.java (99%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/NameBasedSha1FactoryTest.java (99%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/RandomBasedFactoryTest.java (98%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeBasedFactoryTest.java (99%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeOrderedEpochFactoryTest.java (99%) rename src/test/java/com/github/f4b6a3/uuid/factory/{rfc4122 => standard}/TimeOrderedFactoryTest.java (99%) diff --git a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java index c9083f53..c781c78e 100644 --- a/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java +++ b/src/main/java/com/github/f4b6a3/uuid/UuidCreator.java @@ -43,14 +43,14 @@ import com.github.f4b6a3.uuid.factory.nonstandard.ShortPrefixCombFactory; import com.github.f4b6a3.uuid.factory.nonstandard.ShortSuffixCombFactory; import com.github.f4b6a3.uuid.factory.nonstandard.SuffixCombFactory; -import com.github.f4b6a3.uuid.factory.rfc4122.DceSecurityFactory; -import com.github.f4b6a3.uuid.factory.rfc4122.NameBasedMd5Factory; -import com.github.f4b6a3.uuid.factory.rfc4122.NameBasedSha1Factory; -import com.github.f4b6a3.uuid.factory.rfc4122.RandomBasedFactory; -import com.github.f4b6a3.uuid.factory.rfc4122.TimeBasedFactory; -import com.github.f4b6a3.uuid.factory.rfc4122.TimeOrderedFactory; +import com.github.f4b6a3.uuid.factory.standard.DceSecurityFactory; +import com.github.f4b6a3.uuid.factory.standard.NameBasedMd5Factory; +import com.github.f4b6a3.uuid.factory.standard.NameBasedSha1Factory; +import com.github.f4b6a3.uuid.factory.standard.RandomBasedFactory; +import com.github.f4b6a3.uuid.factory.standard.TimeBasedFactory; +import com.github.f4b6a3.uuid.factory.standard.TimeOrderedEpochFactory; +import com.github.f4b6a3.uuid.factory.standard.TimeOrderedFactory; import com.github.f4b6a3.uuid.util.MachineId; -import com.github.f4b6a3.uuid.factory.rfc4122.TimeOrderedEpochFactory; /** * Facade for everything. @@ -744,7 +744,7 @@ public static UUID getNameBasedMd5(String namespace, byte[] name) { *

* The name string is encoded into a sequence of bytes using UTF-8. *

- * Name spaces predefined by RFC-4122 (Appendix C): + * Name spaces predefined by RFC 9562 (Appendix C): *