JAVA-8279 Split or move core java module

This commit is contained in:
mikr
2021-11-13 21:22:34 +01:00
parent 7295717c59
commit 6367e31787
40 changed files with 560 additions and 80 deletions

View File

@@ -0,0 +1,5 @@
## Core Java UUID
### Relevant Articles:
- [Generating Alphanumeric UUID String in Java](https://www.baeldung.com/java-generate-alphanumeric-uuid)
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-uuid</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-uuid</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>core-java-uuid</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<executable>java</executable>
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
<arguments>
<argument>-Xmx300m</argument>
<argument>-XX:+UseParallelGC</argument>
<argument>-classpath</argument>
<classpath />
<argument>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/*IntTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>run-benchmarks</id>
<!-- <phase>integration-test</phase> -->
<phase>none</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<classpathScope>test</classpathScope>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath />
<argument>org.openjdk.jmh.Main</argument>
<argument>.*</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<assertj-core.version>3.10.0</assertj-core.version>
<maven-javadoc-plugin.version>3.0.0-M1</maven-javadoc-plugin.version>
<source.version>1.8</source.version>
<target.version>1.8</target.version>
</properties>
</project>

View File

@@ -0,0 +1,202 @@
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;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Random;
import java.util.UUID;
public class UUIDGenerator {
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
/**
* Type 1 UUID Generation
*/
public static UUID generateType1UUID() {
long most64SigBits = get64MostSignificantBitsForVersion1();
long least64SigBits = get64LeastSignificantBitsForVersion1();
return new UUID(most64SigBits, least64SigBits);
}
private static long get64LeastSignificantBitsForVersion1() {
Random random = new Random();
long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL;
long variant3BitFlag = 0x8000000000000000L;
return random63BitLong + variant3BitFlag;
}
private static long get64MostSignificantBitsForVersion1() {
LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0);
Duration duration = Duration.between(start, LocalDateTime.now());
long seconds = duration.getSeconds();
long nanos = duration.getNano();
long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100;
long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4;
long version = 1 << 12;
return (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificatBitOfTime;
}
/**
* Type 3 UUID Generation
*
* @throws UnsupportedEncodingException
*/
public static UUID generateType3UUID(String namespace, String name) throws UnsupportedEncodingException {
byte[] nameSpaceBytes = bytesFromUUID(namespace);
byte[] nameBytes = name.getBytes("UTF-8");
byte[] result = joinBytes(nameSpaceBytes, nameBytes);
return UUID.nameUUIDFromBytes(result);
}
/**
* Type 4 UUID Generation
*/
public static UUID generateType4UUID() {
UUID uuid = UUID.randomUUID();
return uuid;
}
/**
* Type 5 UUID Generation
*
* @throws UnsupportedEncodingException
*/
public static UUID generateType5UUID(String namespace, String name) throws UnsupportedEncodingException {
byte[] nameSpaceBytes = bytesFromUUID(namespace);
byte[] nameBytes = name.getBytes("UTF-8");
byte[] result = joinBytes(nameSpaceBytes, nameBytes);
return type5UUIDFromBytes(result);
}
public static UUID type5UUIDFromBytes(byte[] name) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException nsae) {
throw new InternalError("SHA-1 not supported", nsae);
}
byte[] bytes = Arrays.copyOfRange(md.digest(name), 0, 16);
bytes[6] &= 0x0f; /* clear version */
bytes[6] |= 0x50; /* set to version 5 */
bytes[8] &= 0x3f; /* clear variant */
bytes[8] |= 0x80; /* set to IETF variant */
return constructType5UUID(bytes);
}
private static UUID constructType5UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++)
msb = (msb << 8) | (data[i] & 0xff);
for (int i = 8; i < 16; i++)
lsb = (lsb << 8) | (data[i] & 0xff);
return new UUID(msb, lsb);
}
/**
* Unique Keys Generation Using Message Digest and Type 4 UUID
*
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static String generateUniqueKeysWithUUIDAndMessageDigest() throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(UUID.randomUUID()
.toString()
.getBytes("UTF-8"));
String digest = bytesToHex(salt.digest());
return digest;
}
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private static byte[] bytesFromUUID(String uuidHexString) {
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));
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);
return (byte) ((firstDigit << 4) + secondDigit);
}
public static byte[] joinBytes(byte[] byteArray1, byte[] byteArray2) {
int finalLength = byteArray1.length + byteArray2.length;
byte[] result = new byte[finalLength];
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];
}
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 = getLeastAndMostSignificantBitsVersion5(hash, 0);
long lsb = getLeastAndMostSignificantBitsVersion5(hash, 8);
// 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 getLeastAndMostSignificantBitsVersion5(final byte[] src, final int offset) {
long ans = 0;
for (int i = offset + 7; i >= offset; i -= 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
return ans;
}
}

View File

@@ -0,0 +1,6 @@
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -0,0 +1,9 @@
# Root logger
log4j.rootLogger=INFO, file, stdout
# Write to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,74 @@
package com.baeldung.uuid;
import org.junit.jupiter.api.Test;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
class UUIDGeneratorUnitTest {
private static final String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
private static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
@Test
public void version_1_UUID_is_generated_with_correct_length_version_and_variant() {
UUID uuid = UUIDGenerator.generateType1UUID();
assertEquals(36, uuid.toString().length());
assertEquals(1, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_3_UUID_is_correctly_generated_for_domain_baeldung_com() throws UnsupportedEncodingException {
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "baeldung.com");
assertEquals("23785b78-0132-3ac6-aff6-cfd5be162139", uuid.toString());
assertEquals(3, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_3_UUID_is_correctly_generated_for_domain_d() throws UnsupportedEncodingException {
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "d");
assertEquals("dbd41ecb-f466-33de-b309-1468addfc63b", uuid.toString());
assertEquals(3, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_4_UUID_is_generated_with_correct_length_version_and_variant() {
UUID uuid = UUIDGenerator.generateType4UUID();
assertEquals(36, uuid.toString().length());
assertEquals(4, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com() throws UnsupportedEncodingException {
UUID uuid = UUIDGenerator.generateType5UUID(NAMESPACE_URL, "baeldung.com");
assertEquals("aeff44a5-8a61-52b6-bcbe-c8e5bd7d0300", uuid.toString());
assertEquals(5, uuid.version());
assertEquals(2, uuid.variant());
}
@Test
public void version_5_UUID_is_correctly_generated_for_domain_baeldung_name() {
UUID uuid = UUIDGenerator.generateType5UUID("baeldung.com");
assertEquals("efd5462b-b07a-52a3-94ea-bf575c0e0e75", uuid.toString());
assertEquals(5, uuid.version());
assertEquals(2, uuid.variant());
}
}

View File

@@ -0,0 +1,6 @@
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -0,0 +1,9 @@
# Root logger
log4j.rootLogger=INFO, file, stdout
# Write to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>