KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > common > uuid > UUIDGenerator


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.1 2004/11/26 01:50:35 tanderson Exp $
44  */

45
46 package org.exolab.jms.common.uuid;
47
48 import java.security.SecureRandom JavaDoc;
49 import java.util.HashSet JavaDoc;
50 import java.util.Random JavaDoc;
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.1 $ $Date: 2004/11/26 01:50:35 $
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 JavaDoc 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 JavaDoc create(String JavaDoc prefix) {
317         StringBuffer JavaDoc buffer;
318
319         if (prefix == null) {
320             throw new IllegalArgumentException JavaDoc("Argument 'prefix' is null");
321         }
322         buffer = new StringBuffer JavaDoc(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 JavaDoc prefix, String JavaDoc 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 JavaDoc("Argument identifier is null");
366         }
367         if (prefix == null) {
368             throw new IllegalArgumentException JavaDoc("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 JavaDoc 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 JavaDoc("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 JavaDoc fromBytes(String JavaDoc prefix, byte[] bytes) {
514         StringBuffer JavaDoc buffer;
515
516         if (prefix == null)
517             throw new IllegalArgumentException JavaDoc("Argument prefix is null");
518         if (bytes == null || bytes.length == 0)
519             throw new IllegalArgumentException JavaDoc("Argument bytes is null or an empty array");
520         buffer = new StringBuffer JavaDoc(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 bytes An array of bytes
537      * @return A string representation of the identifier
538      */

539     public static String JavaDoc fromBytes(byte[] bytes) {
540         StringBuffer JavaDoc buffer;
541
542         if (bytes == null || bytes.length == 0)
543             throw new IllegalArgumentException JavaDoc("Argument bytes is null or an empty array");
544         buffer = new StringBuffer JavaDoc();
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 JavaDoc trim(String JavaDoc identifier) {
561         if (identifier == null)
562             throw new IllegalArgumentException JavaDoc("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 JavaDoc 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 JavaDoc 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 JavaDoc("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
Random JavaDoc random = new Random JavaDoc();
805         String JavaDoc nodeIdString;
806         long nodeIdLong;
807         String JavaDoc seqString;
808         int seqInt;
809
810         // Generate the node identifier, as we can't determine the IEEE 802
811
// address of the local host.
812
// As a result, it must have bit 48 set.
813
nodeIdLong = random.nextLong();
814         nodeIdLong = nodeIdLong | (1 << 47);
815
816         // Generate the clock sequence
817
seqInt = random.nextInt(1 << 12);
818         seqInt = seqInt & 0x1FFF;
819
820         // Convert clock sequence to 4 hexadecimal digits
821
_clockSeqOctet = new char[4];
822         _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)];
823         _clockSeqOctet[1] = HEX_DIGITS[(int) ((seqInt >> 8) & 0x0F)];
824         _clockSeqOctet[2] = HEX_DIGITS[(int) ((seqInt >> 4) & 0x0F)];
825         _clockSeqOctet[3] = HEX_DIGITS[(int) (seqInt & 0x0F)];
826
827         _clockSeqByte = new byte[2];
828         _clockSeqByte[0] = (byte) ((seqInt >> 8) & 0xFF);
829         _clockSeqByte[1] = (byte) (seqInt & 0xFF);
830
831         // Need to mask UUID variant on clock sequence
832
_clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)
833             | UUID_VARIANT_OCTET];
834         _clockSeqByte[0] = (byte) (((seqInt >> 8) & 0xFF)
835             | UUID_VARIANT_BYTE);
836
837         // Convert node identifier to 12 hexadecimal digits
838
_nodeIdentifierOctet = new char[12];
839         for (int i = 0; i < 12; ++i) {
840             _nodeIdentifierOctet[i] =
841                 HEX_DIGITS[(int) ((nodeIdLong >> ((11 - i) * 4)) & 0x0F)];
842         }
843         _nodeIdentifierByte = new byte[6];
844         for (int i = 0; i < 6; ++i) {
845             _nodeIdentifierByte[i] =
846                 (byte) ((nodeIdLong >> ((5 - i) * 8)) & 0xFF);
847         }
848
849         // The number of UUIDs allowed per tick depends on the number of
850
// ticks between each advance of the clock, adjusted for 100
851
// nanosecond precision.
852
_uuidsPerTick = Clock.getUnsynchTicks() * 100;
853     }
854
855     static {
856         initialize();
857         // This makes sure we miss at least one clock tick, just to be safe.
858
_uuidsThisTick = _uuidsPerTick;
859         _lastClock = Clock.clock();
860     }
861
862
863     public static void main(String JavaDoc[] args) {
864         long clock;
865         HashSet JavaDoc hash;
866         String JavaDoc id;
867         int count = 1000000;
868
869         for (int i = 0; i < 10; ++i) {
870             System.out.println(create());
871         }
872         clock = System.currentTimeMillis();
873         hash = new HashSet JavaDoc(count / 100, 100);
874         for (int i = 0; i < count; ++i) {
875             if ((i % 10000) == 0)
876                 System.out.println("Checked " + i);
877             id = create();
878             if (hash.contains(id))
879                 System.out.println("Duplicate id " + id);
880             else
881                 hash.add(id);
882         }
883         clock = System.currentTimeMillis() - clock;
884         System.out.println("Generated " + count + " UUIDs in " + clock + "ms");
885     }
886
887     /**
888      * An exception indicating the identifier is invalid and
889      * cannot be converted into an array of bytes.
890      */

891     public static class InvalidIDException extends Exception JavaDoc {
892
893         public InvalidIDException(String JavaDoc message) {
894             super(message);
895         }
896     }
897
898 }
899
Popular Tags