Browse Source

UUIDV1

UUIDV1
shimingxy 5 years ago
parent
commit
40bef5723d

+ 58 - 0
maxkey-core/src/main/java/org/maxkey/uuid/NodeIDGetter.java

@@ -0,0 +1,58 @@
+package org.maxkey.uuid;
+//$Id$
+
+//
+//(C) Copyright 2005 VeriSign, Inc.  All Rights Reserved.
+//
+//VeriSign, Inc. shall have no responsibility, financial or
+//otherwise, for any consequences arising out of the use of
+//this material. The program material is provided on an "AS IS"
+//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+//express or implied. The user is responsible for determining
+//any necessary third party rights or authorizations that may
+//be required for the use of the materials. Users are advised 
+//that they may need authorizations under certain patents from 
+//Microsoft and IBM, or others. Please see notice.txt file. 
+//VeriSign disclaims any obligation to notify the user of any 
+//such third party rights.
+//
+
+public class NodeIDGetter
+{
+ private static Object lock = new Object();
+ private static byte[] nodeID = null;
+
+ private NodeIDGetter() { throw new Error(); }
+
+ private static native void getNodeID(byte[] nodeID);
+
+ public static byte[] getNodeID()
+ {
+	if(nodeID == null) {
+	    synchronized(lock) {
+		if(nodeID == null) {
+		    try {
+			byte[] data = new UUID("00000000-0000-0000-0000-" 
+	    + System.getProperty("org.apache.tsik.uuid.nodeid")).toByteArray();
+			nodeID = new byte[6];
+			System.arraycopy(data, 10, nodeID, 0, 6);
+			return nodeID;
+		    } catch(Exception ex) {
+			// phooey.
+		    }
+
+		    try {
+			System.loadLibrary("NodeIDGetter");
+			nodeID = new byte[6];
+			getNodeID(nodeID);
+		    } catch(LinkageError ex) {
+			// phooey again.
+		    }
+
+		    nodeID = UUIDRandomness.randomNodeID();
+		}
+	    }
+	}
+	return nodeID;
+ }
+}

+ 56 - 0
maxkey-core/src/main/java/org/maxkey/uuid/TimestampUUIDGenerator.java

@@ -0,0 +1,56 @@
+package org.maxkey.uuid;
+//$Id$
+
+//
+//(C) Copyright 2005 VeriSign, Inc.  All Rights Reserved.
+//
+//VeriSign, Inc. shall have no responsibility, financial or
+//otherwise, for any consequences arising out of the use of
+//this material. The program material is provided on an "AS IS"
+//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+//express or implied. The user is responsible for determining
+//any necessary third party rights or authorizations that may
+//be required for the use of the materials. Users are advised 
+//that they may need authorizations under certain patents from 
+//Microsoft and IBM, or others. Please see notice.txt file. 
+//VeriSign disclaims any obligation to notify the user of any 
+//such third party rights.
+//
+
+/**
+* A more solid timestamp-based UUID generator, this one keeps its
+* timestamps within a millisecond or so of the current time, and is
+* thread-safe.
+*/
+public class TimestampUUIDGenerator
+ extends UnsynchronizedTimestampUUIDGenerator
+ implements UUIDGenerator
+{
+ /**
+  * Creates a UUIDGenerator with the specified clock sequence number
+  * and node ID.
+  *
+  * @throws NullPointerException if node == null
+  * @throws IllegalArgumentException if clock_sequence is out of 
+  *  range or node.length != 6
+  */
+ public TimestampUUIDGenerator(int clock_sequence,
+				  byte[] node)
+ {
+	super(clock_sequence, node);
+ }
+
+ /**
+  * Generates a new UUID.
+  *
+  * @throws IllegalStateException if adjustmentOverflow() throws it
+  */
+ public UUID nextUUID()
+ {
+	synchronized(this) {
+	    checkSystemTime();
+	    return super.nextUUID();
+	}
+ }
+
+}

+ 363 - 0
maxkey-core/src/main/java/org/maxkey/uuid/UUID.java

@@ -0,0 +1,363 @@
+package org.maxkey.uuid;
+
+//$Id$
+
+//
+//(C) Copyright 2005 VeriSign, Inc.  All Rights Reserved.
+//
+//VeriSign, Inc. shall have no responsibility, financial or
+//otherwise, for any consequences arising out of the use of
+//this material. The program material is provided on an "AS IS"
+//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+//express or implied. The user is responsible for determining
+//any necessary third party rights or authorizations that may
+//be required for the use of the materials. Users are advised 
+//that they may need authorizations under certain patents from 
+//Microsoft and IBM, or others. Please see notice.txt file. 
+//VeriSign disclaims any obligation to notify the user of any 
+//such third party rights.
+//
+
+/**
+* Immutable representation of a Universally Unique Identifier (UUID),
+* also known (less presumptuously) as a Globally Unique Identifier (GUID).
+* These identifiers can be generated in a distributed fashion without
+* central coordination, and are reasonably small (128 bits), making them
+* suitable for a wide range of purposes.
+*
+* @see http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
+* @see http://www.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt
+*/
+
+import java.io.*;
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+public final class UUID implements Serializable
+{
+ /**
+	 * 
+	 */
+	private static final long serialVersionUID = 687078561200656066L;
+// Format variants.
+ public static final int VARIANT_NCS = 0x00;
+ public static final int VARIANT_NCS_MASK = 0x80;
+ public static final int VARIANT_DCE = 0x80;
+ public static final int VARIANT_DCE_MASK = 0xC0;
+ public static final int VARIANT_MICROSOFT = 0xC0;
+ public static final int VARIANT_MICROSOFT_MASK = 0xE0;
+ public static final int VARIANT_RESERVED = 0xE0;
+ public static final int VARIANT_RESERVED_MASK = 0xE0;
+
+ // Version numbers for VARIANT_DCE.
+ public static final int VERSION_TIMESTAMP = 0x1000;
+ public static final int VERSION_UID = 0x2000;
+ public static final int VERSION_NAME = 0x3000;
+ public static final int VERSION_RANDOM = 0x4000;
+ public static final int VERSION_MASK = 0xF000;
+
+ // Data representing the UUID.
+ private transient int time_low;
+ private transient short time_mid, time_hi_and_version;
+ private transient byte clock_seq_hi_and_reserved;
+ private transient byte clock_seq_low;
+ private transient byte[] node;
+
+ // Some annotations so we don't have to compute them multiple times.
+ private transient int hash_code;
+ private transient String string_rep;
+ private transient byte[] binary_rep;
+
+ private static UUIDGenerator default_generator;
+
+ /**
+  * The distinguished nil UUID, one whose bits are all zeroes.
+  */
+ public static final UUID nil = new UUID((int)0,
+                                         (short)0,
+                                         (short)0,
+                                         (byte)0,
+                                         (byte)0,
+                                         new byte[] { 0, 0, 0, 0, 0, 0 });
+
+ /**
+  * Creates a new UUID with the specified value.
+  *
+  * @throws NullPointerException if node is null
+  * @throws IllegalArgumentException if node.length != 6
+  */
+ public UUID(int time_low,
+             short time_mid,
+             short time_hi_and_version,
+             byte clock_seq_low,
+             byte clock_seq_hi_and_reserved,
+             byte[] node)
+     throws NullPointerException, IllegalArgumentException
+ {
+     if(node == null) throw new NullPointerException();
+     if(node.length != 6) throw new IllegalArgumentException();
+
+     this.time_low = time_low;
+     this.time_mid = time_mid;
+     this.time_hi_and_version = time_hi_and_version;
+     this.clock_seq_low = clock_seq_low;
+     this.clock_seq_hi_and_reserved = clock_seq_hi_and_reserved;
+     this.node = new byte[6];
+     System.arraycopy(node, 0, this.node, 0, 6);
+ }
+
+ /**
+  * Creates a UUID from its string representation.
+  *
+  * @throws NullPointerException if s is null
+  * @throws IllegalArgumentException if s.length() != 36 or any expected hyphens are missing
+  * @throws NumberFormatException if an expected hex digit isn't one
+  */
+ public UUID(String s)
+     throws NullPointerException,
+            IllegalArgumentException,
+            NumberFormatException
+ {
+     if(s == null) throw new NullPointerException();
+     if(s.length() != 36) throw new IllegalArgumentException();
+     time_low = parseHex(s.substring(0, 8));
+     if(s.charAt(8) != '-') throw new IllegalArgumentException();
+     time_mid = (short) parseHex(s.substring(9, 13));
+     if(s.charAt(13) != '-') throw new IllegalArgumentException();
+     time_hi_and_version = (short) parseHex(s.substring(14, 18));
+     if(s.charAt(18) != '-') throw new IllegalArgumentException();
+     clock_seq_hi_and_reserved = (byte) parseHex(s.substring(19, 21));
+     clock_seq_low = (byte) parseHex(s.substring(21, 23));
+     if(s.charAt(23) != '-') throw new IllegalArgumentException();
+     node = new byte[6];
+     for(int i = 0; i < 6; i++)
+         node[i] = (byte) parseHex(s.substring(2 * i + 24, 2 * i + 26));
+ }
+
+ /**
+  * Reads the 16 bytes of a UUID from the specified
+  * DataInput source.
+  *
+  * @throws NullPointerException if in == null
+  * @throws IOException if the read fails
+  */
+ public UUID(DataInput in) throws IOException
+ {
+     if(in == null) throw new NullPointerException();
+     readData(in);
+ }
+
+ /**
+  * Constructs a UUID from 16 data bytes.
+  *
+  * @throws NullPointerException if data == null
+  * @throws IllegalArgumentException if data.length != 16
+  */
+ public UUID(byte[] data)
+ {
+     if(data == null) throw new NullPointerException();
+     if(data.length != 16) throw new IllegalArgumentException();
+     try {
+         readData(new DataInputStream(new ByteArrayInputStream(data)));
+     } catch(IOException ex) {
+         throw new IllegalArgumentException();
+     }
+ }
+
+ private void readData(DataInput in) throws IOException
+ {
+     time_low = in.readInt();
+     time_mid = in.readShort();
+     time_hi_and_version = in.readShort();
+     clock_seq_hi_and_reserved = in.readByte();
+     clock_seq_low = in.readByte();
+     node = new byte[6];
+     in.readFully(node);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+     readData(in);
+ }
+
+ /**
+  * Writes the 16 data bytes of this UUID to the specified
+  * DataOutput interface.
+  *
+  * @throws IOException if the DataOutput interface does
+  */
+ public void writeData(DataOutput out) throws IOException
+ {
+     out.writeInt(time_low);
+     out.writeShort(time_mid);
+     out.writeShort(time_hi_and_version);
+     out.writeByte(clock_seq_hi_and_reserved);
+     out.writeByte(clock_seq_low);
+     out.write(node);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+     writeData(out);
+ }
+
+ /*
+  * Returns true if two UUIDs are equal by value.
+  */
+ public boolean equals(Object obj)
+ {
+     if(obj == null || !(obj instanceof UUID))
+         return false;
+
+     UUID other = (UUID) obj;
+
+     if(this == other) return true;
+
+     if(hash_code != 0 &&
+        other.hash_code != 0 &&
+        hash_code != other.hash_code)
+         return false;
+
+     return
+         time_low == other.time_low &&
+         time_mid == other.time_mid &&
+         time_hi_and_version == other.time_hi_and_version &&
+         clock_seq_low == other.clock_seq_low &&
+         clock_seq_hi_and_reserved == other.clock_seq_hi_and_reserved &&
+         Arrays.equals(node, other.node);
+ }
+
+ /**
+  * Returns a hash code for this UUID.
+  */
+ public int hashCode()
+ {
+     if(hash_code == 0) {
+         synchronized(this) {
+             if(hash_code == 0) {
+                 hash_code = toString().hashCode();
+                 if(hash_code == 0)
+                     hash_code = -1;
+             }
+         }
+     }
+     return hash_code;
+ }
+
+ /**
+  * Utility method for toString().
+  */
+ private static void appendHex(StringBuffer sb, long num, int digits)
+ {
+     if(digits > 0 && digits < 16)
+         num = num & ((1L << (digits * 4)) - 1);
+
+     String str = Long.toHexString(num);
+     int len = str.length();
+     while(len < digits) {
+         sb.append('0');
+         len++;
+     }
+     sb.append(str);
+ }
+
+ /**
+  * Utility method for UUID(String) constructor.
+  */
+ private static int parseHex(String s) throws NumberFormatException
+ {
+     if(s.charAt(0) == '-')
+         throw new NumberFormatException();
+
+     return Integer.parseInt(s, 16);
+ }
+
+ /**
+  * Returns the string representation of this UUID.
+  */
+ public String toString()
+ {
+     if(string_rep == null) {
+         synchronized(this) {
+             if(string_rep == null) {
+                 StringBuffer sb = new StringBuffer();
+                 appendHex(sb, time_low, 8);
+                 sb.append('-');
+                 appendHex(sb, time_mid, 4);
+                 sb.append('-');
+                 appendHex(sb, time_hi_and_version, 4);
+                 sb.append('-');
+                 appendHex(sb, clock_seq_hi_and_reserved, 2);
+                 appendHex(sb, clock_seq_low, 2);
+                 sb.append('-');
+                 for(int i = 0; i < 6; i++)
+                     appendHex(sb, node[i], 2);
+                 string_rep = sb.toString();
+             }
+         }
+     }
+     return string_rep;
+ }
+
+ /**
+  * Returns an array of 16 bytes containing the binary representation
+  * of this UUID.
+  */
+ public byte[] toByteArray()
+ {
+     if(binary_rep == null) {
+         synchronized(this) {
+             if(binary_rep == null) {
+                 try {
+                     ByteArrayOutputStream baos = new ByteArrayOutputStream(16);
+                     writeData(new DataOutputStream(baos));
+                     binary_rep = baos.toByteArray();
+                 } catch(IOException ex) {
+                     throw new RuntimeException();
+                 }
+             }
+         }
+     }
+     return (byte[]) binary_rep.clone();
+ }
+
+ /**
+  * Creates a new, unique UUID.
+  */
+ public static UUID generate()
+ {
+     if(default_generator == null)
+         default_generator = new TimestampUUIDGenerator(UUIDRandomness.randomClockSequence(), NodeIDGetter.getNodeID());
+     
+     return default_generator.nextUUID();
+ }
+
+ /**
+  * Creates a UUID based on a hash of a namespace designator
+  * UUID and a name.
+  */
+ public static UUID fromName(UUID namespace, String name)
+ {
+     try {
+         MessageDigest md5 = MessageDigest.getInstance("MD5");
+         ByteArrayOutputStream baos = new ByteArrayOutputStream();
+         DataOutputStream dos = new DataOutputStream(baos);
+
+         namespace.writeData(dos);
+         dos.flush();
+         md5.update(baos.toByteArray());
+         baos.reset();
+         dos.writeUTF(name);
+         dos.flush();
+         byte[] data = baos.toByteArray();
+         md5.update(data, 2, data.length - 2);
+         data = md5.digest(); // this should be 16 bytes
+         UUID uuid = new UUID(data);
+         uuid.clock_seq_hi_and_reserved = (byte) ((uuid.clock_seq_hi_and_reserved & ~VARIANT_DCE_MASK) | VARIANT_DCE);
+         uuid.time_hi_and_version = (short) ((uuid.time_hi_and_version & ~VERSION_MASK) | VERSION_NAME);
+         return uuid;
+     } catch(Exception ex) {
+         throw new RuntimeException();
+     }
+ }
+}

+ 12 - 0
maxkey-core/src/main/java/org/maxkey/uuid/UUIDGenerator.java

@@ -0,0 +1,12 @@
+package org.maxkey.uuid;
+
+/**
+ * An interface representing an object that generates UUIDs.
+ */
+public interface UUIDGenerator
+{
+    /**
+     * Generates a new unique UUID according to this generator's rules.
+     */
+    UUID nextUUID();
+}

+ 58 - 0
maxkey-core/src/main/java/org/maxkey/uuid/UUIDRandomness.java

@@ -0,0 +1,58 @@
+// $Id$
+
+//
+// (C) Copyright 2005 VeriSign, Inc.  All Rights Reserved.
+//
+// VeriSign, Inc. shall have no responsibility, financial or
+// otherwise, for any consequences arising out of the use of
+// this material. The program material is provided on an "AS IS"
+// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. The user is responsible for determining
+// any necessary third party rights or authorizations that may
+// be required for the use of the materials. Users are advised 
+// that they may need authorizations under certain patents from 
+// Microsoft and IBM, or others. Please see notice.txt file. 
+// VeriSign disclaims any obligation to notify the user of any 
+// such third party rights.
+//
+
+package org.maxkey.uuid;
+
+import java.security.*;
+
+public final class UUIDRandomness
+{
+    static SecureRandom random = new SecureRandom();
+
+    private UUIDRandomness()
+    {
+	throw new Error();
+    }
+
+    public static byte[] randomNodeID()
+    {
+	byte[] id = new byte[6];
+	synchronized(random) {
+	    random.nextBytes(id);
+	}
+	id[0] |= 0x01;
+	return id;
+    }
+
+    public static int randomClockSequence()
+    {
+	synchronized(random) {
+	    return random.nextInt(16384);
+	}
+    }
+
+    public static int nextRandomClockSequence(int prev)
+    {
+	int next;
+	synchronized(random) {
+	    next = random.nextInt(16383);
+	}
+	if(next >= prev) next++;
+	return next;
+    }
+}

+ 114 - 0
maxkey-core/src/main/java/org/maxkey/uuid/UnsynchronizedTimestampUUIDGenerator.java

@@ -0,0 +1,114 @@
+package org.maxkey.uuid;
+
+//$Id$
+
+//
+//(C) Copyright 2005 VeriSign, Inc.  All Rights Reserved.
+//
+//VeriSign, Inc. shall have no responsibility, financial or
+//otherwise, for any consequences arising out of the use of
+//this material. The program material is provided on an "AS IS"
+//BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+//express or implied. The user is responsible for determining
+//any necessary third party rights or authorizations that may
+//be required for the use of the materials. Users are advised 
+//that they may need authorizations under certain patents from 
+//Microsoft and IBM, or others. Please see notice.txt file. 
+//VeriSign disclaims any obligation to notify the user of any 
+//such third party rights.
+//
+
+/**
+* As simple and fast of a timestamp-based UUIDGenerator as is practical.
+* This class is not thread-safe, and the timestamp field in its UUIDs is
+* not reliably close to the actual time.
+*/
+public class UnsynchronizedTimestampUUIDGenerator implements UUIDGenerator
+{
+ /**
+  * Number of milliseconds between the Gregorian calendar
+  * cutover and the Unix epoch.
+  */
+ public static final long EPOCH_OFFSET = 12219292800000L;
+
+ /**
+  * Number of units of UUID time resolution per unit of system
+  * clock resolution.
+  */
+ public static final long CLOCK_RES = 10000L;
+
+ protected long last_time;
+ protected long clock_adj;
+ protected int clock_sequence;
+ protected byte[] node;
+
+ /**
+  * Creates a UUIDGenerator with the specified clock sequence number
+  * and node ID.
+  *
+  * @throws NullPointerException if node == null
+  * @throws IllegalArgumentException if clock_sequence is out of range or node.length != 6
+  */
+ public UnsynchronizedTimestampUUIDGenerator(int clock_sequence,
+                                             byte[] node)
+ {
+     if(clock_sequence < 0 || clock_sequence >= 16384)
+         throw new IllegalArgumentException();
+     if(node == null)
+         throw new NullPointerException();
+     if(node.length != 6)
+         throw new IllegalArgumentException();
+
+     this.clock_sequence = clock_sequence;
+     this.node = (byte[]) node.clone();
+     checkSystemTime();
+ }
+
+ /**
+  * Reads the current system time and updates last_time, clock_sequence
+  * and clock_adj based on it.
+  */
+ protected void checkSystemTime() {
+     long sys_time = System.currentTimeMillis();
+
+     /* If monotonicity is lost, bump clock_sequence. */
+     if(sys_time < last_time)
+         clock_sequence = UUIDRandomness.nextRandomClockSequence(clock_sequence);
+
+     /* If the clock ticked, clear the adjustment. */
+     if(sys_time != last_time) {
+         last_time = sys_time;
+         clock_adj = 0;
+     }
+ }
+
+ /**
+  * Called when clock_adj >= CLOCK_RES, expected to take corrective action.
+  * May throw an IllegalStateException if corrective action fails.
+  */
+ protected void adjustmentOverflow() throws IllegalStateException
+ {
+     checkSystemTime();
+     if(clock_adj >= CLOCK_RES)
+         throw new IllegalStateException();
+ }
+
+ /**
+  * Generates a new UUID.
+  *
+  * @throws IllegalStateException if adjustmentOverflow() throws it
+  */
+ public UUID nextUUID()
+ {
+     long unique_time = (last_time + EPOCH_OFFSET) * CLOCK_RES + clock_adj;
+     if(++clock_adj > CLOCK_RES) adjustmentOverflow();
+
+     return new UUID((int) (unique_time & 0xFFFFFFFF),
+                     (short) ((unique_time >> 32) & 0xFFFF),
+                     (short) (((unique_time >> 48) & 0x0FFF) | UUID.VERSION_TIMESTAMP),
+                     (byte) (clock_sequence & 0xFF),
+                     (byte) (((clock_sequence >> 8) & 0x3F) | UUID.VARIANT_DCE),
+                     node);
+ }
+}
+

+ 1 - 1
maxkey-core/src/test/java/com/connsec/util/UUIDGeneratorTest.java

@@ -3,7 +3,7 @@ package com.connsec.util;
 import java.util.Date;
 import java.util.Date;
 //import java.util.UUID;
 //import java.util.UUID;
 
 
-import org.apache.tsik.uuid.UUID;
+import org.maxkey.uuid.UUID;
 import org.junit.Test;
 import org.junit.Test;
 import org.maxkey.util.UUIDGenerator;
 import org.maxkey.util.UUIDGenerator;
 
 

BIN
maxkey-lib/other/tsik-1.0.0.jar


+ 2 - 0
maxkey-protocols/maxkey-protocol-tokenbased/bin/main/.gitignore

@@ -0,0 +1,2 @@
+/META-INF/
+/org/