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