View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Intalio. For written permission, 18 * please contact info@exolab.org. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Intalio. Exolab is a registered 23 * trademark of Intalio. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY INTALIO AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * INTALIO OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 1999-2004 (C) Intalio Inc. All Rights Reserved. 42 * 43 * $Id: UUIDGenerator.java,v 1.4 2004/01/18 04:30:08 tanderson Exp $ 44 */ 45 46 package org.exolab.jms.util; 47 48 import java.security.SecureRandom; 49 import java.util.HashSet; 50 import java.util.Random; 51 52 53 /*** 54 * Universally Unique Identifier (UUID) generator. 55 * <p> 56 * A UUID is an identifier that is unique across both space and time, 57 * with respect to the space of all UUIDs. A UUID can be used for 58 * objects with an extremely short lifetime, and to reliably identifying 59 * very persistent objects across a network. UUIDs are 128 bit values 60 * and encoded as 36 character identifiers. 61 * <p> 62 * This generator produces time-based UUIDs based on the varient 63 * specified in a February 4, 1998 IETF draft. 64 * <p> 65 * Unprefixed identifiers are generated by calling {@link #create() 66 * create}. A method is also provided to create prefixed identifiers. 67 * Prefixed identifiers are useful for logging and associating 68 * identifiers to application objects. 69 * <p> 70 * To assure that identifiers can be presisted, identifiers must be 71 * kept within the limit of {@link #MAXIMUM_LENGTH} characters. 72 * This includes both prefixed identifiers and identifiers created 73 * by the application. The {@link #trim trim} method can be used to 74 * trim an identifier to the maximum allowed length. If an* identifier 75 * was generated with no prefix, or with the maximum supported prefix 76 * legnth, the identifier is guaranteed to be short enough and this 77 * method is not required. 78 * <p> 79 * Convenience methods are also provided for converting an identifier 80 * to and from an array of bytes. The conversion methods assume that 81 * the identifier is a prefixed or unprefixed encoding of the byte 82 * array as pairs of hexadecimal digits. 83 * <p> 84 * The UUID specification prescribes the following format for 85 * representing UUIDs. Four octets encode the low field of the time 86 * stamp, two octects encode the middle field of the timestamp, 87 * and two octets encode the high field of the timestamp with the 88 * version number. Two octets encode the clock sequence number and 89 * six octets encode the unique node identifier. 90 * <p> 91 * The timestamp is a 60 bit value holding UTC time as a count of 100 92 * nanosecond intervals since October 15, 1582. UUIDs generated in 93 * this manner are guaranteed not to roll over until 3400 AD. 94 * <p> 95 * The clock sequence is used to help avoid duplicates that could arise 96 * when the clock is set backward in time or if the node ID changes. 97 * Although the system clock is guaranteed to be monotonic, the system 98 * clock is not guaranteed to be monotonic across system failures. 99 * The UUID cannot be sure that no UUIDs were generated with timestamps 100 * larger than the current timestamp. 101 * <p> 102 * If the clock sequence can be determined at initialization, it is 103 * incremented by one, otherwise it is set to a random number. 104 * The clock sequence MUST be originally (i.e. once in the lifetime 105 * of a system) initialized to a random number to minimize the 106 * correlation across systems. The initial value must not be correlated 107 * to the node identifier. 108 * <p> 109 * The node identifier must be unique for each UUID generator. 110 * This is accomplished using the IEEE 802 network card address. 111 * For systems with multiple IEEE 802 addresses, any available address 112 * can be used. For systems with no IEEE address, a 47 bit random value 113 * is used and the multicast bit is set so it will never conflict with 114 * addresses obtained from network cards. 115 * <p> 116 * The UUID state consists of the node identifier and clock sequence. 117 * The state need only be read once when the generator is initialized, 118 * and the clock sequence must be incremented and stored back. If the 119 * UUID state cannot be read and updated, a random number is used. 120 * <p> 121 * The UUID generator is thread-safe. 122 * <p> 123 * This class originally came from Tyrex: http://tyrex.sourceforge.net 124 * 125 * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a> 126 * @version $Revision: 1.4 $ $Date: 2004/01/18 04:30:08 $ 127 */ 128 public final class UUIDGenerator { 129 130 /*** 131 /** 132 * The identifier resolution in bytes. Identifiers are 16-byte 133 * long, or 128 bits. Without a prefix, an identifier can be 134 * represented as 36 hexadecimal digits and hyphens. 135 * (4 hyphens are used in the UUID format) 136 */ 137 public static final int RESOLUTION_BYTES = 16; 138 139 140 /*** 141 * The maximum length of an identifier in textual form. 142 * Prefixed identifiers and application identifiers must be 143 * less or equal to the maximum length to allow persistence. 144 * This maximum length is 64 characters. 145 */ 146 public static final int MAXIMUM_LENGTH = 64; 147 148 149 /*** 150 * The maximum length of an identifier prefix. Identifiers 151 * created using {@link #create(String) create(String)} with 152 * a prefix that is no longer than the maximum prefix size 153 * are guaranteed to be within the maximum length allowed 154 * and need not be trimmed. 155 */ 156 public static final int MAXIMUM_PREFIX = 28; 157 158 159 /*** 160 * The variant value determines the layout of the UUID. This 161 * variant is specified in the IETF February 4, 1998 draft. 162 * Used for character octets. 163 */ 164 private static final int UUID_VARIANT_OCTET = 0x08; 165 166 167 /*** 168 * The variant value determines the layout of the UUID. This 169 * variant is specified in the IETF February 4, 1998 draft. 170 * Used for byte array. 171 */ 172 private static final int UUID_VARIANT_BYTE = 0x80; 173 174 175 /*** 176 * The version identifier for a time-based UUID. This version 177 * is specified in the IETF February 4, 1998 draft. Used for 178 * character octets. 179 */ 180 private static final int UUID_VERSION_CLOCK_OCTET = 0x01; 181 182 183 /*** 184 * The version identifier for a time-based UUID. This version 185 * is specified in the IETF February 4, 1998 draft. Used for 186 * byte array. 187 */ 188 private static final int UUID_VERSION_CLOCK_BYTE = 0x10; 189 190 191 /*** 192 * The version identifier for a name-based UUID. This version 193 * is specified in the IETF February 4, 1998 draft. Used for 194 * character octets. 195 */ 196 private static final int UUID_VERSION_NAME_OCTET = 0x03; 197 198 199 /*** 200 * The version identifier for a name-based UUID. This version 201 * is specified in the IETF February 4, 1998 draft. Used for 202 * byte array. 203 */ 204 private static final int UUID_VERSION_NAME_BYTE = 0x30; 205 206 207 /*** 208 * The version identifier for a random-based UUID. This version 209 * is specified in the IETF February 4, 1998 draft. Used for 210 * character octets. 211 */ 212 private static final int UUID_VERSION_RANDOM_CLOCK = 0x04; 213 214 215 /*** 216 * The version identifier for a random-based UUID. This version 217 * is specified in the IETF February 4, 1998 draft. Used for 218 * byte array. 219 */ 220 private static final int UUID_VERSION_RANDOM_BYTE = 0x40; 221 222 223 /*** 224 * The difference between Java clock and UUID clock. Java clock 225 * is base time is January 1, 1970. UUID clock base time is 226 * October 15, 1582. 227 */ 228 private static final long JAVA_UUID_CLOCK_DIFF = 0x0b1d069b5400L; 229 230 231 /*** 232 * Efficient mapping from 4 bit value to lower case hexadecimal digit. 233 */ 234 private final static char[] HEX_DIGITS = new char[]{ 235 '0', '1', '2', '3', '4', '5', '6', '7', 236 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 237 238 239 /*** 240 * The number of UUIDs that can be generated per clock tick. 241 * UUID assumes a clock tick every 100 nanoseconds. The actual 242 * clock ticks are measured in milliseconds and based on the 243 * sync-every property of the clock. The product of these two 244 * values is used to set this variable. 245 */ 246 private static int _uuidsPerTick; 247 248 249 /*** 250 * The number of UUIDs generated in this clock tick. This counter 251 * is reset each time the clock is advanced a tick. When it reaches 252 * the maximum number of UUIDs allowed per tick, we block until the 253 * clock advances. 254 */ 255 private static int _uuidsThisTick; 256 257 258 /*** 259 * The last clock. Whenever the clock changes, we record the last clock 260 * to identify when we get a new clock, or when we should increments 261 * the UUIDs per tick counter. 262 */ 263 private static long _lastClock; 264 265 266 /*** 267 * The clock sequence. This is randomly initialised, and is made of 268 * four hexadecimal digits. 269 */ 270 private static char[] _clockSeqOctet; 271 272 273 /*** 274 * The clock sequence. The clock sequence is obtained from the UUID 275 * properties and incremented by one each time we boot, or is 276 * generated randomaly if missing in the UUID properties. The clock 277 * sequence is made of two bytes. 278 */ 279 private static byte[] _clockSeqByte; 280 281 282 /*** 283 * The node identifier. The node identifier is obtained from the 284 * UUID properties, or is generated if missing in the UUID properties. 285 * The node identifier is made of twelve hexadecimal digits. 286 */ 287 private static char[] _nodeIdentifierOctet; 288 289 290 /*** 291 * The node identifier. The node identifier is obtained from the 292 * UUID properties, or is generated if missing in the UUID properties. 293 * The node identifier is made of six bytes. 294 */ 295 private static byte[] _nodeIdentifierByte; 296 297 298 /*** 299 * Creates and returns a new identifier. 300 * 301 * @return An identifier 302 */ 303 public static String create() { 304 return String.valueOf(createTimeUUIDChars()); 305 } 306 307 308 /*** 309 * Creates and returns a new prefixed identifier. 310 * <p> 311 * This method is equivalent to <code>prefix + create()</code>. 312 * 313 * @param prefix The prefix to use 314 * @return A prefixed identifier 315 */ 316 public static String create(String prefix) { 317 StringBuffer buffer; 318 319 if (prefix == null) { 320 throw new IllegalArgumentException("Argument 'prefix' is null"); 321 } 322 buffer = new StringBuffer(MAXIMUM_LENGTH - MAXIMUM_PREFIX + prefix.length()); 323 buffer.append(prefix); 324 buffer.append(createTimeUUIDChars()); 325 return buffer.toString(); 326 } 327 328 329 /*** 330 * Creates and returns a new identifier. 331 * 332 * @return An identifier 333 */ 334 public static byte[] createBinary() { 335 return createTimeUUIDBytes(); 336 } 337 338 339 /*** 340 * Converts a prefixed identifier into a byte array. An exception 341 * is thrown if the identifier does not match the excepted textual 342 * encoding. 343 * <p> 344 * The format for the identifier is <code>prefix{nn|-}*</code>: 345 * a prefix followed by a sequence of bytes, optionally separated 346 * by hyphens. Each byte is encoded as a pair of hexadecimal digits. 347 * 348 * @param prefix The identifier prefix 349 * @param identifier The prefixed identifier 350 * @return The identifier as an array of bytes 351 * @throws InvalidIDException The identifier does not begin with 352 * the prefix, or does not consist of a sequence of hexadecimal 353 * digit pairs, optionally separated by hyphens 354 */ 355 public static byte[] toBytes(String prefix, String identifier) 356 throws InvalidIDException { 357 358 int index; 359 char digit; 360 byte nibble; 361 byte[] bytes; 362 byte[] newBytes; 363 364 if (identifier == null) { 365 throw new IllegalArgumentException("Argument identifier is null"); 366 } 367 if (prefix == null) { 368 throw new IllegalArgumentException("Argument prefix is null"); 369 } 370 if (!identifier.startsWith(prefix)) { 371 throw new InvalidIDException( 372 "Invalid identifier: expected prefix " + prefix 373 + "in identifier " + identifier); 374 } 375 376 index = 0; 377 bytes = new byte[(identifier.length() - prefix.length()) / 2]; 378 for (int i = prefix.length(); i < identifier.length(); ++i) { 379 digit = identifier.charAt(i); 380 if (digit == '-') { 381 continue; 382 } 383 if (digit >= '0' && digit <= '9') { 384 nibble = (byte) ((digit - '0') << 4); 385 } else if (digit >= 'A' && digit <= 'F') { 386 nibble = (byte) ((digit - ('A' - 0x0A)) << 4); 387 } else if (digit >= 'a' && digit <= 'f') { 388 nibble = (byte) ((digit - ('a' - 0x0A)) << 4); 389 } else { 390 throw new InvalidIDException( 391 "character " + String.valueOf(digit) 392 + " encountered, expected hexadecimal digit in identifier " 393 + identifier); 394 } 395 ++i; 396 if (i == identifier.length()) { 397 throw new InvalidIDException( 398 "Invalid identifier: odd number of hexadecimal digits in " 399 + "identifier " + identifier); 400 } 401 digit = identifier.charAt(i); 402 if (digit >= '0' && digit <= '9') { 403 nibble = (byte) (nibble | (digit - '0')); 404 } else if (digit >= 'A' && digit <= 'F') { 405 nibble = (byte) (nibble | (digit - ('A' - 0x0A))); 406 } else if (digit >= 'a' && digit <= 'f') { 407 nibble = (byte) (nibble | (digit - ('a' - 0x0A))); 408 } else { 409 throw new InvalidIDException( 410 "character " + String.valueOf(digit) 411 + " encountered, expected hexadecimal digit in identifier " 412 + identifier); 413 } 414 bytes[index] = nibble; 415 ++index; 416 } 417 if (index == bytes.length) { 418 return bytes; 419 } 420 newBytes = new byte[index]; 421 while (index-- > 0) { 422 newBytes[index] = bytes[index]; 423 } 424 return newBytes; 425 } 426 427 428 /*** 429 * Converts an identifier into a byte array. An exception is 430 * thrown if the identifier does not match the excepted textual 431 * encoding. 432 * <p> 433 * The format for the identifier is <code>{nn|-}*</code>: 434 * a sequence of bytes, optionally separated by hyphens. 435 * Each byte is encoded as a pair of hexadecimal digits. 436 * 437 * @param identifier The identifier 438 * @return The identifier as an array of bytes 439 * @throws InvalidIDException The identifier does not consist 440 * of a sequence of hexadecimal digit pairs, optionally separated 441 * by hyphens 442 */ 443 public static byte[] toBytes(String identifier) throws InvalidIDException { 444 int index; 445 char digit; 446 byte nibble; 447 byte[] bytes; 448 byte[] newBytes; 449 450 if (identifier == null) { 451 throw new IllegalArgumentException("Argument identifier is null"); 452 } 453 index = 0; 454 bytes = new byte[identifier.length() / 2]; 455 for (int i = 0; i < identifier.length(); ++i) { 456 digit = identifier.charAt(i); 457 if (digit == '-') 458 continue; 459 if (digit >= '0' && digit <= '9') 460 nibble = (byte) ((digit - '0') << 4); 461 else if (digit >= 'A' && digit <= 'F') 462 nibble = (byte) ((digit - ('A' - 0x0A)) << 4); 463 else if (digit >= 'a' && digit <= 'f') 464 nibble = (byte) ((digit - ('a' - 0x0A)) << 4); 465 else { 466 throw new InvalidIDException( 467 "character " + String.valueOf(digit) 468 + " encountered, expected hexadecimal digit in identifier " 469 + identifier); 470 } 471 ++i; 472 if (i == identifier.length()) { 473 throw new InvalidIDException( 474 "Invalid identifier: odd number of hexadecimal digits in " 475 + "identifier " + identifier); 476 } 477 digit = identifier.charAt(i); 478 if (digit >= '0' && digit <= '9') 479 nibble = (byte) (nibble | (digit - '0')); 480 else if (digit >= 'A' && digit <= 'F') 481 nibble = (byte) (nibble | (digit - ('A' - 0x0A))); 482 else if (digit >= 'a' && digit <= 'f') 483 nibble = (byte) (nibble | (digit - ('a' - 0x0A))); 484 else { 485 throw new InvalidIDException( 486 "character " + String.valueOf(digit) 487 + " encountered, expected hexadecimal digit in identifier " 488 + identifier); 489 } 490 bytes[index] = nibble; 491 ++index; 492 } 493 if (index == bytes.length) 494 return bytes; 495 newBytes = new byte[index]; 496 while (index-- > 0) 497 newBytes[index] = bytes[index]; 498 return newBytes; 499 } 500 501 502 /*** 503 * Converts a byte array into a prefixed identifier. 504 * <p> 505 * The format for the identifier is <code>prefix{nn|-}*</code>: 506 * a prefix followed by a sequence of bytes, optionally separated 507 * by hyphens. Each byte is encoded as a pair of hexadecimal digits. 508 * 509 * @param prefix The identifier prefix 510 * @param byte An array of bytes 511 * @return A string representation of the identifier 512 */ 513 public static String fromBytes(String prefix, byte[] bytes) { 514 StringBuffer buffer; 515 516 if (prefix == null) 517 throw new IllegalArgumentException("Argument prefix is null"); 518 if (bytes == null || bytes.length == 0) 519 throw new IllegalArgumentException("Argument bytes is null or an empty array"); 520 buffer = new StringBuffer(prefix); 521 for (int i = 0; i < bytes.length; ++i) { 522 buffer.append(HEX_DIGITS[(bytes[i] & 0xF0) >> 4]); 523 buffer.append(HEX_DIGITS[(bytes[i] & 0x0F)]); 524 } 525 return buffer.toString(); 526 } 527 528 529 /*** 530 * Converts a byte array into an identifier. 531 * <p> 532 * The format for the identifier is <code>{nn|-}*</code>: a sequence 533 * of bytes, optionally separated by hyphens. Each byte is encoded as 534 * a pair of hexadecimal digits. 535 * 536 * @param byte An array of bytes 537 * @return A string representation of the identifier 538 */ 539 public static String fromBytes(byte[] bytes) { 540 StringBuffer buffer; 541 542 if (bytes == null || bytes.length == 0) 543 throw new IllegalArgumentException("Argument bytes is null or an empty array"); 544 buffer = new StringBuffer(); 545 for (int i = 0; i < bytes.length; ++i) { 546 buffer.append(HEX_DIGITS[(bytes[i] & 0xF0) >> 4]); 547 buffer.append(HEX_DIGITS[(bytes[i] & 0x0F)]); 548 } 549 return buffer.toString(); 550 } 551 552 553 /*** 554 * Truncates an identifier so that it does not extend beyond 555 * {@link #MAXIMUM_LENGTH} characters in length. 556 * 557 * @param identifier An identifier 558 * @return An identifier trimmed to {@link #MAXIMUM_LENGTH} characters 559 */ 560 public static String trim(String identifier) { 561 if (identifier == null) 562 throw new IllegalArgumentException("Argument identifier is null"); 563 if (identifier.length() > MAXIMUM_LENGTH) 564 return identifier.substring(0, MAXIMUM_LENGTH); 565 return identifier; 566 } 567 568 569 /*** 570 * Returns a time-based UUID as a character array. The UUID 571 * identifier is always 36 characters long. 572 * 573 * @return A time-based UUID 574 */ 575 public static char[] createTimeUUIDChars() { 576 long clock; 577 char[] chars; 578 long nextClock; 579 580 // Acquire lock to assure synchornized generation 581 synchronized (UUID.class) { 582 clock = Clock.clock(); 583 while (true) { 584 if (clock > _lastClock) { 585 // Since we are using the clock interval for the UUID space, 586 // we must make sure the next clock provides sufficient 587 // room so UUIDs do not roll over. 588 nextClock = _lastClock + (_uuidsThisTick / 100); 589 if (clock <= nextClock) 590 clock = Clock.synchronize(); 591 if (clock > nextClock) { 592 // Clock reading changed since last UUID generated, 593 // reset count of UUIDs generated with this clock. 594 _uuidsThisTick = 0; 595 _lastClock = clock; 596 // Adjust UUIDs per tick in case the clock sleep ticks 597 // have changed. 598 _uuidsPerTick = Clock.getUnsynchTicks() * 100; 599 break; 600 } 601 } 602 603 if (_uuidsThisTick + 1 < _uuidsPerTick) { 604 // Clock did not advance, but able to create more UUIDs 605 // for this clock, proceed. 606 ++_uuidsThisTick; 607 break; 608 } 609 610 // Running out of UUIDs for the current clock tick, must 611 // wait until clock advances. Possible that clock did not 612 // advance in background, so try to synchronize it first. 613 clock = Clock.synchronize(); 614 if (clock <= _lastClock) { 615 // if (Configuration.verbose) 616 //Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding")); 617 while (clock <= _lastClock) { 618 // UUIDs generated too fast, suspend for a while. 619 try { 620 Thread.currentThread().sleep(Clock.getUnsynchTicks()); 621 } catch (InterruptedException except) { 622 } 623 clock = Clock.synchronize(); 624 } 625 } 626 } 627 628 // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds). 629 // Add the count of uuids to low order bits of the clock reading, 630 // assuring we get a unique clock. 631 clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick; 632 633 chars = new char[36]; 634 // Add the low field of the clock (4 octets) 635 chars[0] = HEX_DIGITS[(int) ((clock >> 28) & 0x0F)]; 636 chars[1] = HEX_DIGITS[(int) ((clock >> 24) & 0x0F)]; 637 chars[2] = HEX_DIGITS[(int) ((clock >> 20) & 0x0F)]; 638 chars[3] = HEX_DIGITS[(int) ((clock >> 16) & 0x0F)]; 639 chars[4] = HEX_DIGITS[(int) ((clock >> 12) & 0x0F)]; 640 chars[5] = HEX_DIGITS[(int) ((clock >> 8) & 0x0F)]; 641 chars[6] = HEX_DIGITS[(int) ((clock >> 4) & 0x0F)]; 642 chars[7] = HEX_DIGITS[(int) (clock & 0x0F)]; 643 chars[8] = '-'; 644 // Add the medium field of the clock (2 octets) 645 chars[9] = HEX_DIGITS[(int) ((clock >> 44) & 0x0F)]; 646 chars[10] = HEX_DIGITS[(int) ((clock >> 40) & 0x0F)]; 647 chars[11] = HEX_DIGITS[(int) ((clock >> 36) & 0x0F)]; 648 chars[12] = HEX_DIGITS[(int) ((clock >> 32) & 0x0F)]; 649 chars[13] = '-'; 650 // Add the high field of the clock multiplexed with version number (2 octets) 651 chars[14] = HEX_DIGITS[(int) (((clock >> 60) & 0x0F) | UUID_VERSION_CLOCK_OCTET)]; 652 chars[15] = HEX_DIGITS[(int) ((clock >> 56) & 0x0F)]; 653 chars[16] = HEX_DIGITS[(int) ((clock >> 52) & 0x0F)]; 654 chars[17] = HEX_DIGITS[(int) ((clock >> 48) & 0x0F)]; 655 chars[18] = '-'; 656 // Add the clock sequence and version identifier (2 octets) 657 chars[19] = _clockSeqOctet[0]; 658 chars[20] = _clockSeqOctet[1]; 659 chars[21] = _clockSeqOctet[2]; 660 chars[22] = _clockSeqOctet[3]; 661 chars[23] = '-'; 662 // Add the node identifier (6 octets) 663 chars[24] = _nodeIdentifierOctet[0]; 664 chars[25] = _nodeIdentifierOctet[1]; 665 chars[26] = _nodeIdentifierOctet[2]; 666 chars[27] = _nodeIdentifierOctet[3]; 667 chars[28] = _nodeIdentifierOctet[4]; 668 chars[29] = _nodeIdentifierOctet[5]; 669 chars[30] = _nodeIdentifierOctet[6]; 670 chars[31] = _nodeIdentifierOctet[7]; 671 chars[32] = _nodeIdentifierOctet[8]; 672 chars[33] = _nodeIdentifierOctet[9]; 673 chars[34] = _nodeIdentifierOctet[10]; 674 chars[35] = _nodeIdentifierOctet[11]; 675 } 676 return chars; 677 } 678 679 680 /*** 681 * Returns a time-based UUID as a character array. The UUID 682 * identifier is always 16 bytes long. 683 * 684 * @return A time-based UUID 685 */ 686 public static byte[] createTimeUUIDBytes() { 687 long clock; 688 byte[] bytes; 689 long nextClock; 690 691 // Acquire lock to assure synchronized generation 692 synchronized (UUIDGenerator.class) { 693 clock = Clock.clock(); 694 while (true) { 695 if (clock > _lastClock) { 696 // Since we are using the clock interval for the UUID 697 // space, we must make sure the next clock provides 698 // sufficient room so UUIDs do not roll over. 699 nextClock = _lastClock + (_uuidsThisTick / 100); 700 if (clock <= nextClock) { 701 clock = Clock.synchronize(); 702 } 703 if (clock > nextClock) { 704 // Clock reading changed since last UUID generated, 705 // reset count of UUIDs generated with this clock. 706 _uuidsThisTick = 0; 707 _lastClock = clock; 708 // Adjust UUIDs per tick in case the clock sleep ticks 709 // have changed. 710 _uuidsPerTick = Clock.getUnsynchTicks() * 100; 711 break; 712 } 713 } 714 715 if (_uuidsThisTick + 1 < _uuidsPerTick) { 716 // Clock did not advance, but able to create more UUIDs 717 // for this clock, proceed. 718 ++_uuidsThisTick; 719 break; 720 } 721 722 // Running out of UUIDs for the current clock tick, must 723 // wait until clock advances. Possible that clock did not 724 // advance in background, so try to synchronize it first. 725 clock = Clock.synchronize(); 726 if (clock <= _lastClock) { 727 // if (Configuration.verbose) 728 // Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding")); 729 while (clock <= _lastClock) { 730 // UUIDs generated too fast, suspend for a while. 731 try { 732 Thread.currentThread().sleep(Clock.getUnsynchTicks()); 733 } catch (InterruptedException ignore) { 734 } 735 clock = Clock.synchronize(); 736 } 737 } 738 } 739 740 // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds). 741 // Add the count of uuids to low order bits of the clock reading, 742 // assuring we get a unique clock. 743 clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick; 744 745 bytes = new byte[16]; 746 // Add the low field of the clock (4 octets) 747 bytes[0] = (byte) ((clock >> 24) & 0xFF); 748 bytes[1] = (byte) ((clock >> 16) & 0xFF); 749 bytes[2] = (byte) ((clock >> 8) & 0xFF); 750 bytes[3] = (byte) (clock & 0xFF); 751 // Add the medium field of the clock (2 octets) 752 bytes[4] = (byte) ((clock >> 40) & 0xFF); 753 bytes[5] = (byte) ((clock >> 32) & 0xFF); 754 // Add the high field of the clock multiplexed with version 755 // number (2 octets) 756 bytes[6] = (byte) (((clock >> 60) & 0xFF) 757 | UUID_VERSION_CLOCK_BYTE); 758 bytes[7] = (byte) ((clock >> 48) & 0xFF); 759 // Add the clock sequence and version identifier (2 octets) 760 bytes[8] = _clockSeqByte[0]; 761 bytes[9] = _clockSeqByte[1]; 762 // Add the node identifier (6 octets) 763 bytes[10] = _nodeIdentifierByte[0]; 764 bytes[11] = _nodeIdentifierByte[1]; 765 bytes[12] = _nodeIdentifierByte[2]; 766 bytes[13] = _nodeIdentifierByte[3]; 767 bytes[14] = _nodeIdentifierByte[4]; 768 bytes[15] = _nodeIdentifierByte[5]; 769 } 770 return bytes; 771 } 772 773 774 /*** 775 * Returns true if the UUID was created on this machine. 776 * Determines the source of the UUID based on the node 777 * identifier. 778 * 779 * @param uuid The UUID as a byte array 780 * @return True if created on this machine 781 */ 782 public static boolean isLocal(byte[] uuid) { 783 if (uuid == null) 784 throw new IllegalArgumentException("Argument uuid is null"); 785 if (uuid.length != 16) 786 return false; 787 return (uuid[10] == _nodeIdentifierByte[0] && 788 uuid[11] == _nodeIdentifierByte[1] && 789 uuid[12] == _nodeIdentifierByte[2] && 790 uuid[13] == _nodeIdentifierByte[3] && 791 uuid[14] == _nodeIdentifierByte[4] && 792 uuid[15] == _nodeIdentifierByte[5]); 793 } 794 795 /*** 796 * Initialise the generator 797 * <p> 798 * This method generates the node identifier and clock sequence, and 799 * sets {@link #_uuidsPerTick} to the number of UUIDs allowed per clock 800 * tick. 801 */ 802 private static void initialize() { 803 Random random = new SecureRandom(); 804 String nodeIdString; 805 long nodeIdLong; 806 String seqString; 807 int seqInt; 808 809 // Generate the node identifier, as we can't determine the IEEE 802 810 // address of the local host. 811 // As a result, it must have bit 48 set. 812 nodeIdLong = random.nextLong(); 813 nodeIdLong = nodeIdLong | (1 << 47); 814 815 // Generate the clock sequence 816 seqInt = random.nextInt(1 << 12); 817 seqInt = seqInt & 0x1FFF; 818 819 // Convert clock sequence to 4 hexadecimal digits 820 _clockSeqOctet = new char[4]; 821 _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)]; 822 _clockSeqOctet[1] = HEX_DIGITS[(int) ((seqInt >> 8) & 0x0F)]; 823 _clockSeqOctet[2] = HEX_DIGITS[(int) ((seqInt >> 4) & 0x0F)]; 824 _clockSeqOctet[3] = HEX_DIGITS[(int) (seqInt & 0x0F)]; 825 826 _clockSeqByte = new byte[2]; 827 _clockSeqByte[0] = (byte) ((seqInt >> 8) & 0xFF); 828 _clockSeqByte[1] = (byte) (seqInt & 0xFF); 829 830 // Need to mask UUID variant on clock sequence 831 _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F) 832 | UUID_VARIANT_OCTET]; 833 _clockSeqByte[0] = (byte) (((seqInt >> 8) & 0xFF) 834 | UUID_VARIANT_BYTE); 835 836 // Convert node identifier to 12 hexadecimal digits 837 _nodeIdentifierOctet = new char[12]; 838 for (int i = 0; i < 12; ++i) { 839 _nodeIdentifierOctet[i] = 840 HEX_DIGITS[(int) ((nodeIdLong >> ((11 - i) * 4)) & 0x0F)]; 841 } 842 _nodeIdentifierByte = new byte[6]; 843 for (int i = 0; i < 6; ++i) { 844 _nodeIdentifierByte[i] = 845 (byte) ((nodeIdLong >> ((5 - i) * 8)) & 0xFF); 846 } 847 848 // The number of UUIDs allowed per tick depends on the number of 849 // ticks between each advance of the clock, adjusted for 100 850 // nanosecond precision. 851 _uuidsPerTick = Clock.getUnsynchTicks() * 100; 852 } 853 854 static { 855 initialize(); 856 // This makes sure we miss at least one clock tick, just to be safe. 857 _uuidsThisTick = _uuidsPerTick; 858 _lastClock = Clock.clock(); 859 } 860 861 862 public static void main(String[] args) { 863 long clock; 864 HashSet hash; 865 String id; 866 int count = 1000000; 867 868 for (int i = 0; i < 10; ++i) { 869 System.out.println(create()); 870 } 871 clock = System.currentTimeMillis(); 872 hash = new HashSet(count / 100, 100); 873 for (int i = 0; i < count; ++i) { 874 if ((i % 10000) == 0) 875 System.out.println("Checked " + i); 876 id = create(); 877 if (hash.contains(id)) 878 System.out.println("Duplicate id " + id); 879 else 880 hash.add(id); 881 } 882 clock = System.currentTimeMillis() - clock; 883 System.out.println("Generated " + count + " UUIDs in " + clock + "ms"); 884 } 885 886 /*** 887 * An exception indicating the identifier is invalid and 888 * cannot be converted into an array of bytes. 889 */ 890 public static class InvalidIDException extends Exception { 891 892 public InvalidIDException(String message) { 893 super(message); 894 } 895 } 896 897 }

This page was automatically generated by Maven