package com.digi.config.util; import java.io.*; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Date; /** * A universally unique identifier (UUID). This UUID uses 128-bits to form * the unique identifier. * * The most significant long can be decomposed into the following * unsigned fields: *
* 0xFFFFFFFFFFFFFFFF time ** The least significant long can be decomposed into the following * unsigned fields: *
* 0xFFFFFFFF00000000 random * 0x00000000FFFFFFFF node ** The time field is a 64-bit timestamp measured in milliseconds since * January 1, 1970, 00:00:00 GMT. The random field is set to a 32-bit random * number, and The node field is set to an 32-bit IEEE 802 address. */ public final class UUID implements Serializable, Comparable { /** * random number generator for UUID generation */ private static final SecureRandom secRand=new SecureRandom(); /** Serialization version id of this object. Were fixing it to maintain compatability with previous versions */ private static final long serialVersionUID=-5279696515406579267L; /** * The most significant 64 bits. */ private long mostSig=0; /** * The least significant 64 bits. */ private long leastSig=0; /** * Construct a universally unique identifier (UUID). This UUID uses 128-bits to form * the unique identifier. * * The most significant long can be decomposed into the following * unsigned fields: *
* 0xFFFFFFFFFFFFFFFF time
*
* The least significant long can be decomposed into the following
* unsigned fields:
*
* 0xFFFFFFFF00000000 random
* 0x00000000FFFFFFFF node
*
* The time field is a 64-bit timestamp measured in milliseconds since
* January 1, 1970, 00:00:00 GMT. The random field is set to a 32-bit random
* number, and The node field is set to an 32-bit IEEE 802 address.
*/
public UUID() {
this((long)(new Date()).getTime(), (int)(secRand.nextLong()));
}
/**
* Construct a UUID based on specified time and random components. The node component will be generated
* in the normal fashion.
*
* Construct a universally unique identifier (UUID) based on user specified time
* and random components. The node component will be generated in the normal fashion
*
* This UUID uses 128-bits to form the unique identifier as follows:
*
* The most significant long can be decomposed into the following
* unsigned fields:
*
* 0xFFFFFFFFFFFFFFFF time
*
* The least significant long can be decomposed into the following
* unsigned fields:
*
* 0xFFFFFFFF00000000 random
* 0x00000000FFFFFFFF node
*
* The time field is a 64-bit timestamp measured in milliseconds since
* January 1, 1970, 00:00:00 GMT. The random field is set to a 32-bit random
* number, and The node field is set to an 32-bit IEEE 802 address.
*/
public UUID(long time, int random) {
// Insert time in most significant field
this.mostSig=time;
// Move random into high half of least significant field
this.leastSig=(this.leastSig&0x00000000ffffffffL)|(((long)random)<<32);
// Get InetAddress and move into low half of least significant field
byte ipBytes[];
try {
ipBytes=InetAddress.getLocalHost().getAddress();
}
catch (UnknownHostException e) {
// Unable to get the host IP address, just use random # sequence then.
ipBytes=new byte[4];
secRand.nextBytes(ipBytes);
}
// Once we have the bytes of the ip address, map them into a long by
// doing a series of add/shift
// operations for each byte in the address.
long inetAddr=0;
for (int i=0; i<4; i++) {
// due to the sign bit we can't just do a straight bitwise OR
// operation. This is because
// ORing a byte with a long first converts the byte to a long
// before performing the operation
// if the msb of the byte is 1 then sign extension is done when
// the conversion to a long takes
// place. This screws up the bitwise OR operation. To avoid this
// we check the msb by seeing if
// the value is negative and if it is we handle it appropriately
if (ipBytes[i]>=0) {
inetAddr+=ipBytes[i];
}
else {
inetAddr+=((long)128+(ipBytes[i]&0x7f));
}
inetAddr<<=8;
}
inetAddr>>=8;
leastSig|=inetAddr;
//System.out.println("Generated UUID. Value =
// ("+Long.toHexString(mostSig)+","+Long.toHexString(leastSig)+")");
}
/**
* Construct a UUID of a known value
*/
public UUID(long mostSig, long leastSig) {
this.mostSig=mostSig;
this.leastSig=leastSig;
}
/**
* Construct a UUID based on a stringified UUID value. This value must have
* been generated from UUID.toString()
*/
public UUID(String stringUuid) {
int underscore=stringUuid.indexOf('_');
this.mostSig=Long.parseLong(stringUuid.substring(0, underscore));
this.leastSig=Long.parseLong(stringUuid.substring(underscore+1));
}
/**
* Returns the most significant 64 bits of the service ID.
*/
public long getMostSignificantBits() {
return mostSig;
}
/**
* Returns the least significant 64 bits of the service ID.
*/
public long getLeastSignificantBits() {
return leastSig;
}
/**
* Writes out 16 bytes in standard network byte order.
*
* @param out the output stream to write 16 bytes to
*/
public void writeBytes(DataOutput out) throws IOException {
out.writeLong(mostSig);
out.writeLong(leastSig);
}
public int hashCode() {
return(int)((mostSig>>32)^mostSig^(leastSig>>32)^leastSig);
}
/**
* UU IDs are equal if they represent the same 128-bit value.
*
* @return true iff the provided object is a UUID and
* it's 128-bit value matches our 128-bit value; otherwise return false.
*/
public boolean equals(Object obj) {
if (!(obj instanceof UUID)) {
return false;
}
UUID sid=(UUID)obj;
return(mostSig==sid.mostSig&&leastSig==sid.leastSig);
}
/**
* Returns a Stringified version of the UUID
*
* @return a String version of the UUID
*/
public String toString() {
//NOTE: this is used as the filename for the PrtJob data while it's waiting to be
//processed. However it is formatted, it needs to be a valid filename.
return(Long.toString(mostSig)+"_" +Long.toString(leastSig));
}
/**
* Allows this object to be compared to another object of the same type to
* determine if it is greater, less than, or equal to it.
*
* Granted, with UUID the notion of comparable is kind of stupid but were using
* these as backup compare key in Controllers so we must ensure the items are not
* reported as the same if just the primary compare keys are the same.
*/
public int compareTo(Object o) {
UUID other=(UUID)o;
int result=0;
// check mostSig bits
if (this.mostSig>other.mostSig) {
result=1;
}
else if (mostSig