INT-1188, Added support for MAC address discovery to ensure Global uniqueness of UUID
This commit is contained in:
@@ -77,7 +77,8 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
|
||||
public MessageHeaders(Map<String, Object> headers) {
|
||||
this.headers = (headers != null) ? new HashMap<String, Object>(headers) : new HashMap<String, Object>();
|
||||
this.headers.put(ID, TimeBasedUUIDGenerator.generateId());
|
||||
//this.headers.put(ID, TimeBasedUUIDGenerator.generateId());
|
||||
this.headers.put(ID, UUID.randomUUID());
|
||||
this.headers.put(TIMESTAMP, new Long(System.currentTimeMillis()));
|
||||
if (this.headers.get(HISTORY) == null) {
|
||||
this.headers.put(HISTORY, new MessageHistory());
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
*/
|
||||
package org.springframework.integration.core;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Will generate time-based UUID (version 1 UUID).
|
||||
* This will allow Message ID to be unique but also contain an
|
||||
@@ -28,6 +33,27 @@ import java.util.UUID;
|
||||
class TimeBasedUUIDGenerator {
|
||||
public static final Object lock = new Object();
|
||||
private static long lastTime;
|
||||
private static final Log logger = LogFactory.getLog(TimeBasedUUIDGenerator.class);
|
||||
private static long macAddressAsLong = 0;
|
||||
|
||||
static {
|
||||
try {
|
||||
InetAddress address = InetAddress.getLocalHost();
|
||||
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
|
||||
if (ni != null) {
|
||||
byte[] mac = ni.getHardwareAddress();
|
||||
//Converts array of unsigned bytes to an long
|
||||
if (mac != null) {
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
macAddressAsLong |= mac[i] & 0xFF;
|
||||
macAddressAsLong <<= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will generate unique time based UUID where the next UUID is
|
||||
@@ -45,6 +71,7 @@ class TimeBasedUUIDGenerator {
|
||||
*/
|
||||
public final static UUID generateIdFromTimestamp(long currentTimeMillis){
|
||||
long time;
|
||||
long macNanoTime;
|
||||
synchronized (lock) {
|
||||
if (currentTimeMillis > lastTime) {
|
||||
lastTime = currentTimeMillis;
|
||||
@@ -63,7 +90,17 @@ class TimeBasedUUIDGenerator {
|
||||
|
||||
// hi Time
|
||||
time |= 0x1000 | ((currentTimeMillis >> 48) & 0x0FFF); // version 1
|
||||
|
||||
return new UUID(time, System.nanoTime());
|
||||
|
||||
macNanoTime = macAddressAsLong;
|
||||
if (macNanoTime == 0){
|
||||
logger.warn("Can not determine machine's MAC address. Will use System.nanoTime() for UUID generation, however there is a slim chance of it not being globally unique");
|
||||
macNanoTime = System.nanoTime();
|
||||
} else {
|
||||
//considering the type of time returned by nanoTime, this will ensure that
|
||||
// even if more then one process is running on the same machine, the id is still unique
|
||||
macNanoTime |= System.nanoTime() & 0xFF;
|
||||
macNanoTime <<= 8;
|
||||
}
|
||||
return new UUID(time, macNanoTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.core;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class TimeBasedUUIDGeneratorTests {
|
||||
|
||||
@Test
|
||||
public void testGreaterThen(){
|
||||
UUID id = TimeBasedUUIDGenerator.generateId();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
UUID newId = TimeBasedUUIDGenerator.generateId();
|
||||
// tests, that newly created UUID is always greater then the previous one.
|
||||
Assert.assertTrue(newId.compareTo(id) == 1);
|
||||
id = newId;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testUniqueness(){
|
||||
long timestamp = System.currentTimeMillis();
|
||||
UUID id = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
UUID newId = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp);
|
||||
// tests, that newly created UUID is always greater then the previous one.
|
||||
Assert.assertTrue(newId.compareTo(id) == 1);
|
||||
id = newId;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user