KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > UUID


1 /*
2  * @(#)UUID.java 1.14 04/07/12
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util;
9
10 import java.security.*;
11 import java.io.IOException JavaDoc;
12 import java.io.UnsupportedEncodingException JavaDoc;
13
14 /**
15  *
16  * A class that represents an immutable universally unique identifier (UUID).
17  * A UUID represents a 128-bit value.
18  *
19  * <p>There exist different variants of these global identifiers. The methods
20  * of this class are for manipulating the Leach-Salz variant, although the
21  * constructors allow the creation of any variant of UUID (described below).
22  *
23  * <p>The layout of a variant 2 (Leach-Salz) UUID is as follows:
24  *
25  * The most significant long consists of the following unsigned fields:
26  * <pre>
27  * 0xFFFFFFFF00000000 time_low
28  * 0x00000000FFFF0000 time_mid
29  * 0x000000000000F000 version
30  * 0x0000000000000FFF time_hi
31  * </pre>
32  * The least significant long consists of the following unsigned fields:
33  * <pre>
34  * 0xC000000000000000 variant
35  * 0x3FFF000000000000 clock_seq
36  * 0x0000FFFFFFFFFFFF node
37  * </pre>
38  *
39  * <p>The variant field contains a value which identifies the layout of
40  * the <tt>UUID</tt>. The bit layout described above is valid only for
41  * a <tt>UUID</tt> with a variant value of 2, which indicates the
42  * Leach-Salz variant.
43  *
44  * <p>The version field holds a value that describes the type of this
45  * <tt>UUID</tt>. There are four different basic types of UUIDs: time-based,
46  * DCE security, name-based, and randomly generated UUIDs. These types
47  * have a version value of 1, 2, 3 and 4, respectively.
48  *
49  * <p>For more information including algorithms used to create <tt>UUID</tt>s,
50  * see the Internet-Draft <a HREF="http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-03.txt">UUIDs and GUIDs</a>
51  * or the standards body definition at
52  * <a HREF="http://www.iso.ch/cate/d2229.html">ISO/IEC 11578:1996</a>.
53  *
54  * @version 1.14, 07/12/04
55  * @since 1.5
56  */

57 public final class UUID
58 implements java.io.Serializable JavaDoc, Comparable JavaDoc<UUID JavaDoc> {
59
60     /**
61      * Explicit serialVersionUID for interoperability.
62      */

63      private static final long serialVersionUID = -4856846361193249489L;
64
65     /*
66      * The most significant 64 bits of this UUID.
67      *
68      * @serial
69      */

70     private final long mostSigBits;
71
72     /*
73      * The least significant 64 bits of this UUID.
74      *
75      * @serial
76      */

77     private final long leastSigBits;
78
79     /*
80      * The version number associated with this UUID. Computed on demand.
81      */

82     private transient int version = -1;
83
84     /*
85      * The variant number associated with this UUID. Computed on demand.
86      */

87     private transient int variant = -1;
88
89     /*
90      * The timestamp associated with this UUID. Computed on demand.
91      */

92     private transient volatile long timestamp = -1;
93
94     /*
95      * The clock sequence associated with this UUID. Computed on demand.
96      */

97     private transient int sequence = -1;
98
99     /*
100      * The node number associated with this UUID. Computed on demand.
101      */

102     private transient long node = -1;
103
104     /*
105      * The hashcode of this UUID. Computed on demand.
106      */

107     private transient int hashCode = -1;
108
109     /*
110      * The random number generator used by this class to create random
111      * based UUIDs.
112      */

113     private static volatile SecureRandom numberGenerator = null;
114
115     // Constructors and Factories
116

117     /*
118      * Private constructor which uses a byte array to construct the new UUID.
119      */

120     private UUID(byte[] data) {
121         long msb = 0;
122         long lsb = 0;
123         assert data.length == 16;
124         for (int i=0; i<8; i++)
125             msb = (msb << 8) | (data[i] & 0xff);
126         for (int i=8; i<16; i++)
127             lsb = (lsb << 8) | (data[i] & 0xff);
128         this.mostSigBits = msb;
129         this.leastSigBits = lsb;
130     }
131
132     /**
133      * Constructs a new <tt>UUID</tt> using the specified data.
134      * <tt>mostSigBits</tt> is used for the most significant 64 bits
135      * of the <tt>UUID</tt> and <tt>leastSigBits</tt> becomes the
136      * least significant 64 bits of the <tt>UUID</tt>.
137      *
138      * @param mostSigBits
139      * @param leastSigBits
140      */

141     public UUID(long mostSigBits, long leastSigBits) {
142         this.mostSigBits = mostSigBits;
143         this.leastSigBits = leastSigBits;
144     }
145
146     /**
147      * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
148      *
149      * The <code>UUID</code> is generated using a cryptographically strong
150      * pseudo random number generator.
151      *
152      * @return a randomly generated <tt>UUID</tt>.
153      */

154     public static UUID JavaDoc randomUUID() {
155         SecureRandom ng = numberGenerator;
156         if (ng == null) {
157             numberGenerator = ng = new SecureRandom();
158         }
159
160         byte[] randomBytes = new byte[16];
161         ng.nextBytes(randomBytes);
162         randomBytes[6] &= 0x0f; /* clear version */
163         randomBytes[6] |= 0x40; /* set to version 4 */
164         randomBytes[8] &= 0x3f; /* clear variant */
165         randomBytes[8] |= 0x80; /* set to IETF variant */
166         UUID JavaDoc result = new UUID JavaDoc(randomBytes);
167         return new UUID JavaDoc(randomBytes);
168     }
169
170     /**
171      * Static factory to retrieve a type 3 (name based) <tt>UUID</tt> based on
172      * the specified byte array.
173      *
174      * @param name a byte array to be used to construct a <tt>UUID</tt>.
175      * @return a <tt>UUID</tt> generated from the specified array.
176      */

177     public static UUID JavaDoc nameUUIDFromBytes(byte[] name) {
178         MessageDigest md;
179         try {
180             md = MessageDigest.getInstance("MD5");
181         } catch (NoSuchAlgorithmException nsae) {
182             throw new InternalError JavaDoc("MD5 not supported");
183         }
184         byte[] md5Bytes = md.digest(name);
185         md5Bytes[6] &= 0x0f; /* clear version */
186         md5Bytes[6] |= 0x30; /* set to version 3 */
187         md5Bytes[8] &= 0x3f; /* clear variant */
188         md5Bytes[8] |= 0x80; /* set to IETF variant */
189         return new UUID JavaDoc(md5Bytes);
190     }
191
192     /**
193      * Creates a <tt>UUID</tt> from the string standard representation as
194      * described in the {@link #toString} method.
195      *
196      * @param name a string that specifies a <tt>UUID</tt>.
197      * @return a <tt>UUID</tt> with the specified value.
198      * @throws IllegalArgumentException if name does not conform to the
199      * string representation as described in {@link #toString}.
200      */

201     public static UUID JavaDoc fromString(String JavaDoc name) {
202         String JavaDoc[] components = name.split("-");
203         if (components.length != 5)
204             throw new IllegalArgumentException JavaDoc("Invalid UUID string: "+name);
205         for (int i=0; i<5; i++)
206             components[i] = "0x"+components[i];
207
208         long mostSigBits = Long.decode(components[0]).longValue();
209         mostSigBits <<= 16;
210         mostSigBits |= Long.decode(components[1]).longValue();
211         mostSigBits <<= 16;
212         mostSigBits |= Long.decode(components[2]).longValue();
213
214         long leastSigBits = Long.decode(components[3]).longValue();
215         leastSigBits <<= 48;
216         leastSigBits |= Long.decode(components[4]).longValue();
217
218         return new UUID JavaDoc(mostSigBits, leastSigBits);
219     }
220
221     // Field Accessor Methods
222

223     /**
224      * Returns the least significant 64 bits of this UUID's 128 bit value.
225      *
226      * @return the least significant 64 bits of this UUID's 128 bit value.
227      */

228     public long getLeastSignificantBits() {
229         return leastSigBits;
230     }
231
232     /**
233      * Returns the most significant 64 bits of this UUID's 128 bit value.
234      *
235      * @return the most significant 64 bits of this UUID's 128 bit value.
236      */

237     public long getMostSignificantBits() {
238         return mostSigBits;
239     }
240
241     /**
242      * The version number associated with this <tt>UUID</tt>. The version
243      * number describes how this <tt>UUID</tt> was generated.
244      *
245      * The version number has the following meaning:<p>
246      * <ul>
247      * <li>1 Time-based UUID
248      * <li>2 DCE security UUID
249      * <li>3 Name-based UUID
250      * <li>4 Randomly generated UUID
251      * </ul>
252      *
253      * @return the version number of this <tt>UUID</tt>.
254      */

255     public int version() {
256         if (version < 0) {
257             // Version is bits masked by 0x000000000000F000 in MS long
258
version = (int)((mostSigBits >> 12) & 0x0f);
259         }
260         return version;
261     }
262
263     /**
264      * The variant number associated with this <tt>UUID</tt>. The variant
265      * number describes the layout of the <tt>UUID</tt>.
266      *
267      * The variant number has the following meaning:<p>
268      * <ul>
269      * <li>0 Reserved for NCS backward compatibility
270      * <li>2 The Leach-Salz variant (used by this class)
271      * <li>6 Reserved, Microsoft Corporation backward compatibility
272      * <li>7 Reserved for future definition
273      * </ul>
274      *
275      * @return the variant number of this <tt>UUID</tt>.
276      */

277     public int variant() {
278         if (variant < 0) {
279             // This field is composed of a varying number of bits
280
if ((leastSigBits >>> 63) == 0) {
281                 variant = 0;
282             } else if ((leastSigBits >>> 62) == 2) {
283                 variant = 2;
284             } else {
285                 variant = (int)(leastSigBits >>> 61);
286             }
287         }
288         return variant;
289     }
290
291     /**
292      * The timestamp value associated with this UUID.
293      *
294      * <p>The 60 bit timestamp value is constructed from the time_low,
295      * time_mid, and time_hi fields of this <tt>UUID</tt>. The resulting
296      * timestamp is measured in 100-nanosecond units since midnight,
297      * October 15, 1582 UTC.<p>
298      *
299      * The timestamp value is only meaningful in a time-based UUID, which
300      * has version type 1. If this <tt>UUID</tt> is not a time-based UUID then
301      * this method throws UnsupportedOperationException.
302      *
303      * @throws UnsupportedOperationException if this UUID is not a
304      * version 1 UUID.
305      */

306     public long timestamp() {
307         if (version() != 1) {
308             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
309         }
310         long result = timestamp;
311         if (result < 0) {
312             result = (mostSigBits & 0x0000000000000FFFL) << 48;
313             result |= ((mostSigBits >> 16) & 0xFFFFL) << 32;
314             result |= mostSigBits >>> 32;
315             timestamp = result;
316         }
317         return result;
318     }
319
320     /**
321      * The clock sequence value associated with this UUID.
322      *
323      * <p>The 14 bit clock sequence value is constructed from the clock
324      * sequence field of this UUID. The clock sequence field is used to
325      * guarantee temporal uniqueness in a time-based UUID.<p>
326      *
327      * The clockSequence value is only meaningful in a time-based UUID, which
328      * has version type 1. If this UUID is not a time-based UUID then
329      * this method throws UnsupportedOperationException.
330      *
331      * @return the clock sequence of this <tt>UUID</tt>.
332      * @throws UnsupportedOperationException if this UUID is not a
333      * version 1 UUID.
334      */

335     public int clockSequence() {
336         if (version() != 1) {
337             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
338         }
339         if (sequence < 0) {
340             sequence = (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
341         }
342         return sequence;
343     }
344
345     /**
346      * The node value associated with this UUID.
347      *
348      * <p>The 48 bit node value is constructed from the node field of
349      * this UUID. This field is intended to hold the IEEE 802 address
350      * of the machine that generated this UUID to guarantee spatial
351      * uniqueness.<p>
352      *
353      * The node value is only meaningful in a time-based UUID, which
354      * has version type 1. If this UUID is not a time-based UUID then
355      * this method throws UnsupportedOperationException.
356      *
357      * @return the node value of this <tt>UUID</tt>.
358      * @throws UnsupportedOperationException if this UUID is not a
359      * version 1 UUID.
360      */

361     public long node() {
362         if (version() != 1) {
363             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
364         }
365         if (node < 0) {
366             node = leastSigBits & 0x0000FFFFFFFFFFFFL;
367         }
368         return node;
369     }
370
371     // Object Inherited Methods
372

373     /**
374      * Returns a <code>String</code> object representing this
375      * <code>UUID</code>.
376      *
377      * <p>The UUID string representation is as described by this BNF :
378      * <pre>
379      * UUID = <time_low> "-" <time_mid> "-"
380      * <time_high_and_version> "-"
381      * <variant_and_sequence> "-"
382      * <node>
383      * time_low = 4*<hexOctet>
384      * time_mid = 2*<hexOctet>
385      * time_high_and_version = 2*<hexOctet>
386      * variant_and_sequence = 2*<hexOctet>
387      * node = 6*<hexOctet>
388      * hexOctet = <hexDigit><hexDigit>
389      * hexDigit =
390      * "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
391      * | "a" | "b" | "c" | "d" | "e" | "f"
392      * | "A" | "B" | "C" | "D" | "E" | "F"
393      * </pre>
394      *
395      * @return a string representation of this <tt>UUID</tt>.
396      */

397     public String JavaDoc toString() {
398     return (digits(mostSigBits >> 32, 8) + "-" +
399         digits(mostSigBits >> 16, 4) + "-" +
400         digits(mostSigBits, 4) + "-" +
401         digits(leastSigBits >> 48, 4) + "-" +
402         digits(leastSigBits, 12));
403     }
404
405     /** Returns val represented by the specified number of hex digits. */
406     private static String JavaDoc digits(long val, int digits) {
407     long hi = 1L << (digits * 4);
408     return Long.toHexString(hi | (val & (hi - 1))).substring(1);
409     }
410
411     /**
412      * Returns a hash code for this <code>UUID</code>.
413      *
414      * @return a hash code value for this <tt>UUID</tt>.
415      */

416     public int hashCode() {
417         if (hashCode == -1) {
418             hashCode = (int)((mostSigBits >> 32) ^
419                              mostSigBits ^
420                              (leastSigBits >> 32) ^
421                              leastSigBits);
422         }
423         return hashCode;
424     }
425
426     /**
427      * Compares this object to the specified object. The result is
428      * <tt>true</tt> if and only if the argument is not
429      * <tt>null</tt>, is a <tt>UUID</tt> object, has the same variant,
430      * and contains the same value, bit for bit, as this <tt>UUID</tt>.
431      *
432      * @param obj the object to compare with.
433      * @return <code>true</code> if the objects are the same;
434      * <code>false</code> otherwise.
435      */

436     public boolean equals(Object JavaDoc obj) {
437     if (!(obj instanceof UUID JavaDoc))
438         return false;
439         if (((UUID JavaDoc)obj).variant() != this.variant())
440             return false;
441         UUID JavaDoc id = (UUID JavaDoc)obj;
442     return (mostSigBits == id.mostSigBits &&
443                 leastSigBits == id.leastSigBits);
444     }
445
446     // Comparison Operations
447

448     /**
449      * Compares this UUID with the specified UUID.
450      *
451      * <p>The first of two UUIDs follows the second if the most significant
452      * field in which the UUIDs differ is greater for the first UUID.
453      *
454      * @param val <tt>UUID</tt> to which this <tt>UUID</tt> is to be compared.
455      * @return -1, 0 or 1 as this <tt>UUID</tt> is less than, equal
456      * to, or greater than <tt>val</tt>.
457      */

458     public int compareTo(UUID JavaDoc val) {
459         // The ordering is intentionally set up so that the UUIDs
460
// can simply be numerically compared as two numbers
461
return (this.mostSigBits < val.mostSigBits ? -1 :
462                 (this.mostSigBits > val.mostSigBits ? 1 :
463                  (this.leastSigBits < val.leastSigBits ? -1 :
464                   (this.leastSigBits > val.leastSigBits ? 1 :
465                    0))));
466     }
467
468     /**
469      * Reconstitute the <tt>UUID</tt> instance from a stream (that is,
470      * deserialize it). This is necessary to set the transient fields
471      * to their correct uninitialized value so they will be recomputed
472      * on demand.
473      */

474     private void readObject(java.io.ObjectInputStream JavaDoc in)
475         throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
476
477         in.defaultReadObject();
478
479         // Set "cached computation" fields to their initial values
480
version = -1;
481         variant = -1;
482         timestamp = -1;
483         sequence = -1;
484         node = -1;
485         hashCode = -1;
486     }
487 }
488
Popular Tags