From 87988b50322c97beeb3f7a39e1555cfb14326815 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Mon, 4 Nov 2013 18:40:36 -0500 Subject: [PATCH] INT-3064 Message ID Generation Use the SPR 4.0.0 Message ID Generation algorithm. JIRA: https://jira.springsource.org/browse/INT-3064 --- build.gradle | 2 - .../integration/MessageHeaders.java | 49 +++++++++++++++---- src/reference/docbook/message.xml | 14 ++---- src/reference/docbook/whats-new.xml | 4 +- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index 1af9cd8564..dd03d4936e 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,6 @@ subprojects { subproject -> junitVersion = '4.11' log4jVersion = '1.2.12' mockitoVersion = '1.9.5' - eaioUUIDVersion = '3.2' ftpServerVersion = '1.0.6' @@ -194,7 +193,6 @@ project('spring-integration-core') { compile "org.springframework:spring-context:$springVersion" compile "org.springframework:spring-tx:$springVersion" compile "org.springframework.retry:spring-retry:$springRetryVersion" - compile "com.eaio.uuid:uuid:$eaioUUIDVersion" compile("org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion", optional) compile("com.fasterxml.jackson.core:jackson-databind:$jackson2Version", optional) compile('com.jayway.jsonpath:json-path:0.8.1', optional) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java index c71a1ee1c9..da00aa3269 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java @@ -20,12 +20,15 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.math.BigInteger; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; @@ -33,8 +36,6 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.eaio.uuid.UUIDGen; - /** * The headers for a {@link Message}.
* IMPORTANT: MessageHeaders are immutable. Any mutating operation (e.g., put(..), putAll(..) etc.) @@ -55,6 +56,7 @@ import com.eaio.uuid.UUIDGen; * @author Mark Fisher * @author Oleg Zhurakousky * @author Gary Russell + * @author Rossen Stoyanchev */ public final class MessageHeaders implements Map, Serializable { @@ -64,6 +66,8 @@ public final class MessageHeaders implements Map, Serializable { private static volatile IdGenerator idGenerator = null; + private static final IdGenerator defaultIdGenerator = new AlternativeJdkIdGenerator(); + /** * The key for the Message ID. This is an automatically generated UUID and * should never be explicitly set in the header map except in the @@ -100,13 +104,8 @@ public final class MessageHeaders implements Map, Serializable { public MessageHeaders(Map headers) { this.headers = (headers != null) ? new HashMap(headers) : new HashMap(); - if (MessageHeaders.idGenerator == null) { - UUID uuid = new UUID(UUIDGen.newTime(), UUIDGen.getClockSeqAndNode()); - this.headers.put(ID, uuid); - } - else { - this.headers.put(ID, MessageHeaders.idGenerator.generateId()); - } + IdGenerator generatorToUse = (idGenerator != null) ? idGenerator : defaultIdGenerator; + this.headers.put(ID, generatorToUse.generateId()); this.headers.put(TIMESTAMP, new Long(System.currentTimeMillis())); } @@ -285,6 +284,38 @@ public final class MessageHeaders implements Map, Serializable { } + /** + * A variation of {@link UUID#randomUUID()} that uses {@link SecureRandom} only for + * the initial seed and {@link Random} thereafter, which provides better performance + * in exchange for less securely random id's. + */ + public static class AlternativeJdkIdGenerator implements IdGenerator { + + private final Random random; + + public AlternativeJdkIdGenerator() { + byte[] seed = new SecureRandom().generateSeed(8); + this.random = new Random(new BigInteger(seed).longValue()); + } + + public UUID generateId() { + + byte[] randomBytes = new byte[16]; + this.random.nextBytes(randomBytes); + + long mostSigBits = 0; + for (int i = 0; i < 8; i++) { + mostSigBits = (mostSigBits << 8) | (randomBytes[i] & 0xff); + } + long leastSigBits = 0; + for (int i = 8; i < 16; i++) { + leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xff); + } + + return new UUID(mostSigBits, leastSigBits); + } + } + public static class SimpleIncrementingIdGenerator implements IdGenerator { private final AtomicLong topBits = new AtomicLong(); diff --git a/src/reference/docbook/message.xml b/src/reference/docbook/message.xml index 891786eea8..88fd49ae56 100644 --- a/src/reference/docbook/message.xml +++ b/src/reference/docbook/message.xml @@ -121,10 +121,11 @@ When a message transitions through an application, each time it is mutated (e.g. by a transformer) a new message id is assigned. The message id is - a UUID. Beginning with Spring Integration 3.0, the default strategy - used for id generation is to use the com.eaio.uuid package to - generate Type 1 UUIDs. This is much more efficient than the previous - java.util.UUID.randomUUID() implementation. + a UUID. Beginning with Spring Integration 3.0, + the default strategy used for id generation is more efficient than the previous + java.util.UUID.randomUUID() implementation. It uses simple random + numbers based on a secure random seed, instead of creating a secure random + number each time. A different UUID generation strategy can be selected by declaring a bean that implements @@ -147,11 +148,6 @@ can be used in cases where a UUID is not really needed and a simple incrementing value is sufficient. - - The default strategy of creating Type 1 UUIDs may present security concerns for some users - because the UUID contains the MAC address of a network interface on the platform. For these - users, an alternate strategy should be selected. - diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index 53b20bc8bd..0a4e18d4d4 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -467,8 +467,8 @@ Message ID Generation Previously, message ids were generated using the JDK UUID.randomUUID() method. With this - release, the default mechanism has been changed to use the com.eaio.uuid package which - generates Type 1 UUIDs, and is significantly faster. In addition, the ability to change + release, the default mechanism has been changed to use a more efficient algorithm which + is significantly faster. In addition, the ability to change the strategy used to generate message ids has been added. For more information see .