1 11 package org.eclipse.core.internal.utils; 12 13 import java.io.*; 14 import java.math.BigInteger ; 15 import java.net.InetAddress ; 16 import java.net.UnknownHostException ; 17 import java.security.SecureRandom ; 18 import java.util.GregorianCalendar ; 19 import java.util.Random ; 20 import org.eclipse.core.runtime.Assert; 21 22 public class UniversalUniqueIdentifier implements java.io.Serializable { 23 24 27 private static final long serialVersionUID = 1L; 28 29 30 31 private byte[] fBits = new byte[BYTES_SIZE]; 32 33 34 35 private static BigInteger fgPreviousClockValue; 36 private static int fgClockAdjustment = 0; 37 private static int fgClockSequence = -1; 38 private static byte[] nodeAddress; 39 40 static { 41 nodeAddress = computeNodeAddress(); 42 } 43 44 45 46 private static Random fgRandomNumberGenerator = new Random (); 47 48 49 50 public static final int BYTES_SIZE = 16; 51 public static final byte[] UNDEFINED_UUID_BYTES = new byte[16]; 52 public static final int MAX_CLOCK_SEQUENCE = 0x4000; 53 public static final int MAX_CLOCK_ADJUSTMENT = 0x7FFF; 54 public static final int TIME_FIELD_START = 0; 55 public static final int TIME_FIELD_STOP = 6; 56 public static final int TIME_HIGH_AND_VERSION = 7; 57 public static final int CLOCK_SEQUENCE_HIGH_AND_RESERVED = 8; 58 public static final int CLOCK_SEQUENCE_LOW = 9; 59 public static final int NODE_ADDRESS_START = 10; 60 public static final int NODE_ADDRESS_BYTE_SIZE = 6; 61 62 public static final int BYTE_MASK = 0xFF; 63 64 public static final int HIGH_NIBBLE_MASK = 0xF0; 65 66 public static final int LOW_NIBBLE_MASK = 0x0F; 67 68 public static final int SHIFT_NIBBLE = 4; 69 70 public static final int ShiftByte = 8; 71 72 76 public UniversalUniqueIdentifier() { 77 this.setVersion(1); 78 this.setVariant(1); 79 this.setTimeValues(); 80 this.setNode(getNodeAddress()); 81 } 82 83 92 public UniversalUniqueIdentifier(byte[] byteValue) { 93 fBits = new byte[BYTES_SIZE]; 94 if (byteValue.length >= BYTES_SIZE) 95 System.arraycopy(byteValue, 0, fBits, 0, BYTES_SIZE); 96 } 97 98 private void appendByteString(StringBuffer buffer, byte value) { 99 String hexString; 100 101 if (value < 0) 102 hexString = Integer.toHexString(256 + value); 103 else 104 hexString = Integer.toHexString(value); 105 if (hexString.length() == 1) 106 buffer.append("0"); buffer.append(hexString); 108 } 109 110 private static BigInteger clockValueNow() { 111 GregorianCalendar now = new GregorianCalendar (); 112 BigInteger nowMillis = BigInteger.valueOf(now.getTime().getTime()); 113 BigInteger baseMillis = BigInteger.valueOf(now.getGregorianChange().getTime()); 114 115 return (nowMillis.subtract(baseMillis).multiply(BigInteger.valueOf(10000L))); 116 } 117 118 122 public Object clone() { 123 try { 124 return super.clone(); 125 } catch (CloneNotSupportedException e) { 126 Assert.isTrue(false, Messages.utils_clone); 127 return null; 128 } 129 } 130 131 public static int compareTime(byte[] fBits1, byte[] fBits2) { 132 for (int i = TIME_FIELD_STOP; i >= 0; i--) 133 if (fBits1[i] != fBits2[i]) 134 return (0xFF & fBits1[i]) - (0xFF & fBits2[i]); 135 return 0; 136 } 137 138 144 private static byte[] computeNodeAddress() { 145 146 byte[] address = new byte[NODE_ADDRESS_BYTE_SIZE]; 147 148 int thread = Thread.currentThread().hashCode(); 150 long time = System.currentTimeMillis(); 151 int objectId = System.identityHashCode(new String ()); 152 ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 153 DataOutputStream out = new DataOutputStream(byteOut); 154 byte[] ipAddress = getIPAddress(); 155 156 try { 157 if (ipAddress != null) 158 out.write(ipAddress); 159 out.write(thread); 160 out.writeLong(time); 161 out.write(objectId); 162 out.close(); 163 } catch (IOException exc) { 164 } 166 byte[] rand = byteOut.toByteArray(); 167 168 SecureRandom randomizer = new SecureRandom (rand); 169 randomizer.nextBytes(address); 170 171 address[0] = (byte) (address[0] | (byte) 0x80); 173 174 return address; 175 } 176 177 public boolean equals(Object obj) { 178 if (this == obj) 179 return true; 180 if (!(obj instanceof UniversalUniqueIdentifier)) 181 return false; 182 183 byte[] other = ((UniversalUniqueIdentifier) obj).fBits; 184 if (fBits == other) 185 return true; 186 if (fBits.length != other.length) 187 return false; 188 for (int i = 0; i < fBits.length; i++) { 189 if (fBits[i] != other[i]) 190 return false; 191 } 192 return true; 193 } 194 195 203 protected static byte[] getIPAddress() { 204 try { 205 return InetAddress.getLocalHost().getAddress(); 206 } catch (UnknownHostException e) { 207 return null; 210 } 211 } 212 213 private static byte[] getNodeAddress() { 214 return nodeAddress; 215 } 216 217 public int hashCode() { 218 return fBits[0] + fBits[3] + fBits[7] + fBits[11] + fBits[15]; 219 } 220 221 private static int nextClockSequence() { 222 223 if (fgClockSequence == -1) 224 fgClockSequence = (int) (fgRandomNumberGenerator.nextDouble() * MAX_CLOCK_SEQUENCE); 225 226 fgClockSequence = (fgClockSequence + 1) % MAX_CLOCK_SEQUENCE; 227 228 return fgClockSequence; 229 } 230 231 private static BigInteger nextTimestamp() { 232 233 BigInteger timestamp = clockValueNow(); 234 int timestampComparison; 235 236 timestampComparison = timestamp.compareTo(fgPreviousClockValue); 237 238 if (timestampComparison == 0) { 239 if (fgClockAdjustment == MAX_CLOCK_ADJUSTMENT) { 240 while (timestamp.compareTo(fgPreviousClockValue) == 0) 241 timestamp = clockValueNow(); 242 timestamp = nextTimestamp(); 243 } else 244 fgClockAdjustment++; 245 } else { 246 fgClockAdjustment = 0; 247 248 if (timestampComparison < 0) 249 nextClockSequence(); 250 } 251 252 return timestamp; 253 } 254 255 private void setClockSequence(int clockSeq) { 256 int clockSeqHigh = (clockSeq >>> ShiftByte) & LOW_NIBBLE_MASK; 257 int reserved = fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] & HIGH_NIBBLE_MASK; 258 259 fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] = (byte) (reserved | clockSeqHigh); 260 fBits[CLOCK_SEQUENCE_LOW] = (byte) (clockSeq & BYTE_MASK); 261 } 262 263 protected void setNode(byte[] bytes) { 264 265 for (int index = 0; index < NODE_ADDRESS_BYTE_SIZE; index++) 266 fBits[index + NODE_ADDRESS_START] = bytes[index]; 267 } 268 269 private void setTimestamp(BigInteger timestamp) { 270 BigInteger value = timestamp; 271 BigInteger bigByte = BigInteger.valueOf(256L); 272 BigInteger [] results; 273 int version; 274 int timeHigh; 275 276 for (int index = TIME_FIELD_START; index < TIME_FIELD_STOP; index++) { 277 results = value.divideAndRemainder(bigByte); 278 value = results[0]; 279 fBits[index] = (byte) results[1].intValue(); 280 } 281 version = fBits[TIME_HIGH_AND_VERSION] & HIGH_NIBBLE_MASK; 282 timeHigh = value.intValue() & LOW_NIBBLE_MASK; 283 fBits[TIME_HIGH_AND_VERSION] = (byte) (timeHigh | version); 284 } 285 286 protected synchronized void setTimeValues() { 287 this.setTimestamp(timestamp()); 288 this.setClockSequence(fgClockSequence); 289 } 290 291 protected int setVariant(int variantIdentifier) { 292 int clockSeqHigh = fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] & LOW_NIBBLE_MASK; 293 int variant = variantIdentifier & LOW_NIBBLE_MASK; 294 295 fBits[CLOCK_SEQUENCE_HIGH_AND_RESERVED] = (byte) ((variant << SHIFT_NIBBLE) | clockSeqHigh); 296 return (variant); 297 } 298 299 protected void setVersion(int versionIdentifier) { 300 int timeHigh = fBits[TIME_HIGH_AND_VERSION] & LOW_NIBBLE_MASK; 301 int version = versionIdentifier & LOW_NIBBLE_MASK; 302 303 fBits[TIME_HIGH_AND_VERSION] = (byte) (timeHigh | (version << SHIFT_NIBBLE)); 304 } 305 306 private static BigInteger timestamp() { 307 BigInteger timestamp; 308 309 if (fgPreviousClockValue == null) { 310 fgClockAdjustment = 0; 311 nextClockSequence(); 312 timestamp = clockValueNow(); 313 } else 314 timestamp = nextTimestamp(); 315 316 fgPreviousClockValue = timestamp; 317 return fgClockAdjustment == 0 ? timestamp : timestamp.add(BigInteger.valueOf(fgClockAdjustment)); 318 } 319 320 325 public byte[] toBytes() { 326 byte[] result = new byte[fBits.length]; 327 328 System.arraycopy(fBits, 0, result, 0, fBits.length); 329 return result; 330 } 331 332 public String toString() { 333 StringBuffer buffer = new StringBuffer (); 334 for (int i = 0; i < fBits.length; i++) 335 appendByteString(buffer, fBits[i]); 336 return buffer.toString(); 337 } 338 339 public String toStringAsBytes() { 340 String result = "{"; 342 for (int i = 0; i < fBits.length; i++) { 343 result += fBits[i]; 344 if (i < fBits.length + 1) 345 result += ","; } 347 return result + "}"; } 349 } 350 | Popular Tags |