提交 40bef572 编写于 作者: MaxKey单点登录官方's avatar MaxKey单点登录官方

UUIDV1

UUIDV1
上级 1b2f924f
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;
}
}
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();
}
}
}
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();
}
}
}
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();
}
\ No newline at end of file
// $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;
}
}
\ No newline at end of file
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);
}
}
......@@ -3,7 +3,7 @@ package com.connsec.util;
import java.util.Date;
//import java.util.UUID;
import org.apache.tsik.uuid.UUID;
import org.maxkey.uuid.UUID;
import org.junit.Test;
import org.maxkey.util.UUIDGenerator;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册