[uuid] Added method to generate UUID identifiers for version 5 (#10948)

Signed-off-by: Diego Torres <dtorres.py@gmail.com>
This commit is contained in:
Diego Torres 2021-06-24 16:10:31 -04:00 committed by GitHub
parent 0c656299d0
commit f66bfa5088
2 changed files with 59 additions and 7 deletions

View File

@ -1,6 +1,8 @@
package com.baeldung.uuid;
import java.io.UnsupportedEncodingException;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
@ -132,21 +134,21 @@ public class UUIDGenerator {
}
private static byte[] bytesFromUUID(String uuidHexString) {
String normalizedUUIDHexString = uuidHexString.replace("-","");
String normalizedUUIDHexString = uuidHexString.replace("-", "");
assert normalizedUUIDHexString.length() == 32;
byte[] bytes = new byte[16];
for (int i = 0; i < 16; i++) {
byte b = hexToByte(normalizedUUIDHexString.substring(i*2, i*2+2));
byte b = hexToByte(normalizedUUIDHexString.substring(i * 2, i * 2 + 2));
bytes[i] = b;
}
return bytes;
}
public static byte hexToByte(String hexString) {
int firstDigit = Character.digit(hexString.charAt(0),16);
int secondDigit = Character.digit(hexString.charAt(1),16);
int firstDigit = Character.digit(hexString.charAt(0), 16);
int secondDigit = Character.digit(hexString.charAt(1), 16);
return (byte) ((firstDigit << 4) + secondDigit);
}
@ -154,14 +156,54 @@ public class UUIDGenerator {
int finalLength = byteArray1.length + byteArray2.length;
byte[] result = new byte[finalLength];
for(int i = 0; i < byteArray1.length; i++) {
for (int i = 0; i < byteArray1.length; i++) {
result[i] = byteArray1[i];
}
for(int i = 0; i < byteArray2.length; i++) {
result[byteArray1.length+i] = byteArray2[i];
for (int i = 0; i < byteArray2.length; i++) {
result[byteArray1.length + i] = byteArray2[i];
}
return result;
}
public static UUID generateType5UUID(String name) {
try {
byte[] bytes = name.getBytes(StandardCharsets.UTF_8);
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] hash = md.digest(bytes);
long msb = peekLong(hash, 0, ByteOrder.BIG_ENDIAN);
long lsb = peekLong(hash, 8, ByteOrder.BIG_ENDIAN);
// Set the version field
msb &= ~(0xfL << 12);
msb |= ((long) 5) << 12;
// Set the variant field to 2
lsb &= ~(0x3L << 62);
lsb |= 2L << 62;
return new UUID(msb, lsb);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
private static long peekLong(final byte[] src, final int offset, final ByteOrder order) {
long ans = 0;
if (order == ByteOrder.BIG_ENDIAN) {
for (int i = offset; i < offset + 8; i += 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
} else {
for (int i = offset + 7; i >= offset; i -= 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
}
return ans;
}
}

View File

@ -61,4 +61,14 @@ class UUIDGeneratorUnitTest {
assertEquals(5, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com_without_namespace() throws UnsupportedEncodingException {
UUID uuid = UUIDGenerator.generateType5UUID("baeldung.com");
assertEquals("a3c27ab0-2b46-55ef-b50e-0e5c57bfea94", uuid.toString());
assertEquals(5, uuid.version());
assertEquals(2, uuid.variant());
}
}