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