1 6 7 package org.jfox.ioc.util; 8 9 import java.io.UnsupportedEncodingException ; 10 import java.security.MessageDigest ; 11 import java.security.NoSuchAlgorithmException ; 12 import java.security.SecureRandom ; 13 14 58 public final class UUID implements java.io.Serializable , Comparable { 59 60 63 private static final long serialVersionUID = -4856846361193249489L; 64 65 70 private final long mostSigBits; 71 72 77 private final long leastSigBits; 78 79 82 private transient int version = -1; 83 84 87 private transient int variant = -1; 88 89 92 private transient volatile long timestamp = -1; 93 94 97 private transient int sequence = -1; 98 99 102 private transient long node = -1; 103 104 107 private transient int hashCode = -1; 108 109 113 private static volatile SecureRandom numberGenerator = null; 114 115 117 120 private UUID(byte[] data) { 121 long msb = 0; 122 long lsb = 0; 123 if(data.length != 16) { 124 throw new IllegalArgumentException ("data length must be 16."); 125 } 126 for(int i = 0; i < 8; i++) 127 msb = (msb << 8) | (data[i] & 0xff); 128 for(int i = 8; i < 16; i++) 129 lsb = (lsb << 8) | (data[i] & 0xff); 130 this.mostSigBits = msb; 131 this.leastSigBits = lsb; 132 } 133 134 143 public UUID(long mostSigBits, long leastSigBits) { 144 this.mostSigBits = mostSigBits; 145 this.leastSigBits = leastSigBits; 146 } 147 148 156 public static UUID randomUUID() { 157 SecureRandom ng = numberGenerator; 158 if(ng == null) { 159 numberGenerator = ng = new SecureRandom (); 160 } 161 162 byte[] randomBytes = new byte[16]; 163 ng.nextBytes(randomBytes); 164 randomBytes[6] &= 0x0f; 165 randomBytes[6] |= 0x40; 166 randomBytes[8] &= 0x3f; 167 randomBytes[8] |= 0x80; 168 return new UUID(randomBytes); 169 } 170 171 178 public static UUID nameUUIDFromString(String name) { 179 MessageDigest md; 180 try { 181 md = MessageDigest.getInstance("MD5"); 182 } 183 catch(NoSuchAlgorithmException nsae) { 184 throw new InternalError ("MD5 not supported"); 185 } 186 byte[] md5Bytes; 187 try { 188 md5Bytes = md.digest(name.getBytes("8859_1")); 189 } 190 catch(UnsupportedEncodingException uee) { 191 throw new InternalError ("8859_1 not supported"); 192 } 193 md5Bytes[6] &= 0x0f; 194 md5Bytes[6] |= 0x30; 195 md5Bytes[8] &= 0x3f; 196 md5Bytes[8] |= 0x80; 197 return new UUID(md5Bytes); 198 } 199 200 207 public static UUID nameUUIDFromBytes(byte[] name) { 208 MessageDigest md; 209 try { 210 md = MessageDigest.getInstance("MD5"); 211 } 212 catch(NoSuchAlgorithmException nsae) { 213 throw new InternalError ("MD5 not supported"); 214 } 215 byte[] md5Bytes = md.digest(name); 216 md5Bytes[6] &= 0x0f; 217 md5Bytes[6] |= 0x30; 218 md5Bytes[8] &= 0x3f; 219 md5Bytes[8] |= 0x80; 220 return new UUID(md5Bytes); 221 } 222 223 230 public static UUID fromString(String name) { 231 String [] components = name.split("-"); 232 if(components.length != 5) 233 throw new IllegalArgumentException ("Invalid UUID string: " + name); 234 for(int i = 0; i < 5; i++) 235 components[i] = "0x" + components[i]; 236 237 long mostSigBits = Long.decode(components[0]).longValue(); 238 mostSigBits <<= 16; 239 mostSigBits |= Long.decode(components[1]).longValue(); 240 mostSigBits <<= 16; 241 mostSigBits |= Long.decode(components[2]).longValue(); 242 243 long leastSigBits = Long.decode(components[3]).longValue(); 244 leastSigBits <<= 48; 245 leastSigBits |= Long.decode(components[4]).longValue(); 246 247 return new UUID(mostSigBits, leastSigBits); 248 } 249 250 252 257 public long getLeastSignificantBits() { 258 return leastSigBits; 259 } 260 261 266 public long getMostSignificantBits() { 267 return mostSigBits; 268 } 269 270 284 public int version() { 285 if(version < 0) { 286 version = (int) ((mostSigBits >> 12) & 0x0f); 288 } 289 return version; 290 } 291 292 306 public int variant() { 307 if(variant < 0) { 308 if((leastSigBits >>> 63) == 0) { 310 variant = 0; 311 } 312 else if((leastSigBits >>> 62) == 2) { 313 variant = 2; 314 } 315 else { 316 variant = (int) (leastSigBits >>> 61); 317 } 318 } 319 return variant; 320 } 321 322 337 public long timestamp() { 338 if(version() != 1) { 339 throw new UnsupportedOperationException ("Not a time-based UUID"); 340 } 341 long result = timestamp; 342 if(result < 0) { 343 result = (mostSigBits & 0x0000000000000FFFL) << 48; 344 result |= ((mostSigBits >> 16) & 0xFFFFL) << 32; 345 result |= mostSigBits >>> 32; 346 timestamp = result; 347 } 348 return result; 349 } 350 351 366 public int clockSequence() { 367 if(version() != 1) { 368 throw new UnsupportedOperationException ("Not a time-based UUID"); 369 } 370 if(sequence < 0) { 371 sequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); 372 } 373 return sequence; 374 } 375 376 392 public long node() { 393 if(version() != 1) { 394 throw new UnsupportedOperationException ("Not a time-based UUID"); 395 } 396 if(node < 0) { 397 node = leastSigBits & 0x0000FFFFFFFFFFFFL; 398 } 399 return node; 400 } 401 402 404 428 public String toString() { 429 return (digits(mostSigBits >> 32, 8) + "-" + 430 digits(mostSigBits >> 16, 4) + "-" + 431 digits(mostSigBits, 4) + "-" + 432 digits(leastSigBits >> 48, 4) + "-" + 433 digits(leastSigBits, 12)); 434 } 435 436 439 private static String digits(long val, int digits) { 440 long hi = 1L << (digits * 4); 441 return Long.toHexString(hi | (val & (hi - 1))).substring(1); 442 } 443 444 449 public int hashCode() { 450 if(hashCode == -1) { 451 hashCode = (int) ((mostSigBits >> 32) ^ 452 mostSigBits ^ 453 (leastSigBits >> 32) ^ 454 leastSigBits); 455 } 456 return hashCode; 457 } 458 459 469 public boolean equals(Object obj) { 470 if(!(obj instanceof UUID)) 471 return false; 472 if(((UUID) obj).variant() != this.variant()) 473 return false; 474 UUID id = (UUID) obj; 475 return (mostSigBits == id.mostSigBits && 476 leastSigBits == id.leastSigBits); 477 } 478 479 481 491 public int compareTo(Object val) { 492 if(val.getClass() != UUID.class) { 493 return -1; 494 } 495 return (this.mostSigBits < ((UUID) val).mostSigBits ? -1 : 498 (this.mostSigBits > ((UUID) val).mostSigBits ? 1 : 499 (this.leastSigBits < ((UUID) val).leastSigBits ? -1 : 500 (this.leastSigBits > ((UUID) val).leastSigBits ? 1 : 501 0)))); 502 } 503 504 510 private void readObject(java.io.ObjectInputStream in) 511 throws java.io.IOException , ClassNotFoundException { 512 513 in.defaultReadObject(); 514 515 version = -1; 517 variant = -1; 518 timestamp = -1; 519 sequence = -1; 520 node = -1; 521 hashCode = -1; 522 } 523 } 524 | Popular Tags |