KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfox > ioc > util > UUID


1 /* JFox, the OpenSource J2EE Application Server
2  *
3  * Distributable under GNU LGPL license by gun.org
4  * more details please visit http://www.huihoo.org/jfox
5  */

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

58 public final class UUID implements java.io.Serializable JavaDoc, Comparable 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 JavaDoc 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         if(data.length != 16) {
124             throw new IllegalArgumentException JavaDoc("data length must be 16.");
125         }
126         for(int i = 0; i < 8; i++)
127             msb = (msb << 8) | (data[i] & 0xff);
128         for(int i = 8; i < 16; i++)
129             lsb = (lsb << 8) | (data[i] & 0xff);
130         this.mostSigBits = msb;
131         this.leastSigBits = lsb;
132     }
133
134     /**
135      * Constructs a new <tt>UUID</tt> using the specified data.
136      * <tt>mostSigBits</tt> is used for the most significant 64 bits
137      * of the <tt>UUID</tt> and <tt>leastSigBits</tt> becomes the
138      * least significant 64 bits of the <tt>UUID</tt>.
139      *
140      * @param mostSigBits
141      * @param leastSigBits
142      */

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

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

178     public static UUID nameUUIDFromString(String JavaDoc name) {
179         MessageDigest JavaDoc md;
180         try {
181             md = MessageDigest.getInstance("MD5");
182         }
183         catch(NoSuchAlgorithmException JavaDoc nsae) {
184             throw new InternalError JavaDoc("MD5 not supported");
185         }
186         byte[] md5Bytes;
187         try {
188             md5Bytes = md.digest(name.getBytes("8859_1"));
189         }
190         catch(UnsupportedEncodingException JavaDoc uee) {
191             throw new InternalError JavaDoc("8859_1 not supported");
192         }
193         md5Bytes[6] &= 0x0f; /* clear version */
194         md5Bytes[6] |= 0x30; /* set to version 3 */
195         md5Bytes[8] &= 0x3f; /* clear variant */
196         md5Bytes[8] |= 0x80; /* set to IETF variant */
197         return new UUID(md5Bytes);
198     }
199
200     /**
201      * Static factory to retrieve a type 3 (name based) <tt>UUID</tt> based on
202      * the specified byte array.
203      *
204      * @param name a byte array to be used to construct a <tt>UUID</tt>.
205      * @return a <tt>UUID</tt> generated from the specified array.
206      */

207     public static UUID nameUUIDFromBytes(byte[] name) {
208         MessageDigest JavaDoc md;
209         try {
210             md = MessageDigest.getInstance("MD5");
211         }
212         catch(NoSuchAlgorithmException JavaDoc nsae) {
213             throw new InternalError JavaDoc("MD5 not supported");
214         }
215         byte[] md5Bytes = md.digest(name);
216         md5Bytes[6] &= 0x0f; /* clear version */
217         md5Bytes[6] |= 0x30; /* set to version 3 */
218         md5Bytes[8] &= 0x3f; /* clear variant */
219         md5Bytes[8] |= 0x80; /* set to IETF variant */
220         return new UUID(md5Bytes);
221     }
222
223     /**
224      * Creates a <tt>UUID</tt> from the string standard representation as
225      * described in the toString() method.
226      *
227      * @param name a string that specifies a <tt>UUID</tt>.
228      * @return a <tt>UUID</tt> with the specified value.
229      */

230     public static UUID fromString(String JavaDoc name) {
231         String JavaDoc[] components = name.split("-");
232         if(components.length != 5)
233             throw new IllegalArgumentException JavaDoc("Invalid UUID string: " + name);
234         for(int i = 0; i < 5; i++)
235             components[i] = "0x" + components[i];
236
237         long mostSigBits = Long.decode(components[0]).longValue();
238         mostSigBits <<= 16;
239         mostSigBits |= Long.decode(components[1]).longValue();
240         mostSigBits <<= 16;
241         mostSigBits |= Long.decode(components[2]).longValue();
242
243         long leastSigBits = Long.decode(components[3]).longValue();
244         leastSigBits <<= 48;
245         leastSigBits |= Long.decode(components[4]).longValue();
246
247         return new UUID(mostSigBits, leastSigBits);
248     }
249
250     // Field Accessor Methods
251

252     /**
253      * Returns the least significant 64 bits of this UUID's 128 bit value.
254      *
255      * @return the least significant 64 bits of this UUID's 128 bit value.
256      */

257     public long getLeastSignificantBits() {
258         return leastSigBits;
259     }
260
261     /**
262      * Returns the most significant 64 bits of this UUID's 128 bit value.
263      *
264      * @return the most significant 64 bits of this UUID's 128 bit value.
265      */

266     public long getMostSignificantBits() {
267         return mostSigBits;
268     }
269
270     /**
271      * The version number associated with this <tt>UUID</tt>. The version
272      * number describes how this <tt>UUID</tt> was generated.
273      * <p/>
274      * The version number has the following meaning:<p>
275      * <ul>
276      * <li>1 Time-based UUID
277      * <li>2 DCE security UUID
278      * <li>3 Name-based UUID
279      * <li>4 Randomly generated UUID
280      * </ul>
281      *
282      * @return the version number of this <tt>UUID</tt>.
283      */

284     public int version() {
285         if(version < 0) {
286             // Version is bits masked by 0x000000000000F000 in MS long
287
version = (int) ((mostSigBits >> 12) & 0x0f);
288         }
289         return version;
290     }
291
292     /**
293      * The variant number associated with this <tt>UUID</tt>. The variant
294      * number describes the layout of the <tt>UUID</tt>.
295      * <p/>
296      * The variant number has the following meaning:<p>
297      * <ul>
298      * <li>0 Reserved for NCS backward compatibility
299      * <li>2 The Leach-Salz variant (used by this class)
300      * <li>6 Reserved, Microsoft Corporation backward compatibility
301      * <li>7 Reserved for future definition
302      * </ul>
303      *
304      * @return the variant number of this <tt>UUID</tt>.
305      */

306     public int variant() {
307         if(variant < 0) {
308             // This field is composed of a varying number of bits
309
if((leastSigBits >>> 63) == 0) {
310                 variant = 0;
311             }
312             else if((leastSigBits >>> 62) == 2) {
313                 variant = 2;
314             }
315             else {
316                 variant = (int) (leastSigBits >>> 61);
317             }
318         }
319         return variant;
320     }
321
322     /**
323      * The timestamp value associated with this UUID.
324      * <p/>
325      * <p>The 60 bit timestamp value is constructed from the time_low,
326      * time_mid, and time_hi fields of this <tt>UUID</tt>. The resulting
327      * timestamp is measured in 100-nanosecond units since midnight,
328      * October 15, 1582 UTC.<p>
329      * <p/>
330      * The timestamp value is only meaningful in a time-based UUID, which
331      * has version type 1. If this <tt>UUID</tt> is not a time-based UUID then
332      * this method throws UnsupportedOperationException.
333      *
334      * @throws UnsupportedOperationException if this UUID is not a
335      * version 1 UUID.
336      */

337     public long timestamp() {
338         if(version() != 1) {
339             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
340         }
341         long result = timestamp;
342         if(result < 0) {
343             result = (mostSigBits & 0x0000000000000FFFL) << 48;
344             result |= ((mostSigBits >> 16) & 0xFFFFL) << 32;
345             result |= mostSigBits >>> 32;
346             timestamp = result;
347         }
348         return result;
349     }
350
351     /**
352      * The clock sequence value associated with this UUID.
353      * <p/>
354      * <p>The 14 bit clock sequence value is constructed from the clock
355      * sequence field of this UUID. The clock sequence field is used to
356      * guarantee temporal uniqueness in a time-based UUID.<p>
357      * <p/>
358      * The clockSequence value is only meaningful in a time-based UUID, which
359      * has version type 1. If this UUID is not a time-based UUID then
360      * this method throws UnsupportedOperationException.
361      *
362      * @return the clock sequence of this <tt>UUID</tt>.
363      * @throws UnsupportedOperationException if this UUID is not a
364      * version 1 UUID.
365      */

366     public int clockSequence() {
367         if(version() != 1) {
368             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
369         }
370         if(sequence < 0) {
371             sequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
372         }
373         return sequence;
374     }
375
376     /**
377      * The node value associated with this UUID.
378      * <p/>
379      * <p>The 48 bit node value is constructed from the node field of
380      * this UUID. This field is intended to hold the IEEE 802 address
381      * of the machine that generated this UUID to guarantee spatial
382      * uniqueness.<p>
383      * <p/>
384      * The node value is only meaningful in a time-based UUID, which
385      * has version type 1. If this UUID is not a time-based UUID then
386      * this method throws UnsupportedOperationException.
387      *
388      * @return the node value of this <tt>UUID</tt>.
389      * @throws UnsupportedOperationException if this UUID is not a
390      * version 1 UUID.
391      */

392     public long node() {
393         if(version() != 1) {
394             throw new UnsupportedOperationException JavaDoc("Not a time-based UUID");
395         }
396         if(node < 0) {
397             node = leastSigBits & 0x0000FFFFFFFFFFFFL;
398         }
399         return node;
400     }
401
402     // Object Inherited Methods
403

404     /**
405      * Returns a <code>String</code> object representing this
406      * <code>UUID</code>.
407      * <p/>
408      * <p>The UUID string representation is as described by this BNF :
409      * <pre>
410      * UUID = <time_low> "-" <time_mid> "-"
411      * <time_high_and_version> "-"
412      * <variant_and_sequence> "-"
413      * <node>
414      * time_low = 4*<hexOctet>
415      * time_mid = 2*<hexOctet>
416      * time_high_and_version = 2*<hexOctet>
417      * variant_and_sequence = 2*<hexOctet>
418      * node = 6*<hexOctet>
419      * hexOctet = <hexDigit><hexDigit>
420      * hexDigit =
421      * "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
422      * | "a" | "b" | "c" | "d" | "e" | "f"
423      * | "A" | "B" | "C" | "D" | "E" | "F"
424      * </pre>
425      *
426      * @return a string representation of this <tt>UUID</tt>.
427      */

428     public String JavaDoc toString() {
429         return (digits(mostSigBits >> 32, 8) + "-" +
430                 digits(mostSigBits >> 16, 4) + "-" +
431                 digits(mostSigBits, 4) + "-" +
432                 digits(leastSigBits >> 48, 4) + "-" +
433                 digits(leastSigBits, 12));
434     }
435
436     /**
437      * Returns val represented by the specified number of hex digits.
438      */

439     private static String JavaDoc digits(long val, int digits) {
440         long hi = 1L << (digits * 4);
441         return Long.toHexString(hi | (val & (hi - 1))).substring(1);
442     }
443
444     /**
445      * Returns a hash code for this <code>UUID</code>.
446      *
447      * @return a hash code value for this <tt>UUID</tt>.
448      */

449     public int hashCode() {
450         if(hashCode == -1) {
451             hashCode = (int) ((mostSigBits >> 32) ^
452                     mostSigBits ^
453                     (leastSigBits >> 32) ^
454                     leastSigBits);
455         }
456         return hashCode;
457     }
458
459     /**
460      * Compares this object to the specified object. The result is
461      * <tt>true</tt> if and only if the argument is not
462      * <tt>null</tt>, is a <tt>UUID</tt> object, has the same variant,
463      * and contains the same value, bit for bit, as this <tt>UUID</tt>.
464      *
465      * @param obj the object to compare with.
466      * @return <code>true</code> if the objects are the same;
467      * <code>false</code> otherwise.
468      */

469     public boolean equals(Object JavaDoc obj) {
470         if(!(obj instanceof UUID))
471             return false;
472         if(((UUID) obj).variant() != this.variant())
473             return false;
474         UUID id = (UUID) obj;
475         return (mostSigBits == id.mostSigBits &&
476                 leastSigBits == id.leastSigBits);
477     }
478
479     // Comparison Operations
480

481     /**
482      * Compares this UUID with the specified UUID.
483      * <p/>
484      * <p>The first of two UUIDs follows the second if the most significant
485      * field in which the UUIDs differ is greater for the first UUID.
486      *
487      * @param val <tt>UUID</tt> to which this <tt>UUID</tt> is to be compared.
488      * @return -1, 0 or 1 as this <tt>UUID</tt> is less than, equal
489      * to, or greater than <tt>val</tt>.
490      */

491     public int compareTo(Object JavaDoc val) {
492         if(val.getClass() != UUID.class) {
493             return -1;
494         }
495         // The ordering is intentionally set up so that the UUIDs
496
// can simply be numerically compared as two numbers
497
return (this.mostSigBits < ((UUID) val).mostSigBits ? -1 :
498                 (this.mostSigBits > ((UUID) val).mostSigBits ? 1 :
499                 (this.leastSigBits < ((UUID) val).leastSigBits ? -1 :
500                 (this.leastSigBits > ((UUID) val).leastSigBits ? 1 :
501                 0))));
502     }
503
504     /**
505      * Reconstitute the <tt>UUID</tt> instance from a stream (that is,
506      * deserialize it). This is necessary to set the transient fields
507      * to their correct uninitialized value so they will be recomputed
508      * on demand.
509      */

510     private void readObject(java.io.ObjectInputStream JavaDoc in)
511             throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
512
513         in.defaultReadObject();
514
515         // Set "cached computation" fields to their initial values
516
version = -1;
517         variant = -1;
518         timestamp = -1;
519         sequence = -1;
520         node = -1;
521         hashCode = -1;
522     }
523 }
524
Popular Tags