001 /*
002 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.util;
027
028 import java.security.*;
029 import java.io.IOException;
030 import java.io.UnsupportedEncodingException;
031
032 /**
033 * A class that represents an immutable universally unique identifier (UUID).
034 * A UUID represents a 128-bit value.
035 *
036 * <p> There exist different variants of these global identifiers. The methods
037 * of this class are for manipulating the Leach-Salz variant, although the
038 * constructors allow the creation of any variant of UUID (described below).
039 *
040 * <p> The layout of a variant 2 (Leach-Salz) UUID is as follows:
041 *
042 * The most significant long consists of the following unsigned fields:
043 * <pre>
044 * 0xFFFFFFFF00000000 time_low
045 * 0x00000000FFFF0000 time_mid
046 * 0x000000000000F000 version
047 * 0x0000000000000FFF time_hi
048 * </pre>
049 * The least significant long consists of the following unsigned fields:
050 * <pre>
051 * 0xC000000000000000 variant
052 * 0x3FFF000000000000 clock_seq
053 * 0x0000FFFFFFFFFFFF node
054 * </pre>
055 *
056 * <p> The variant field contains a value which identifies the layout of the
057 * {@code UUID}. The bit layout described above is valid only for a {@code
058 * UUID} with a variant value of 2, which indicates the Leach-Salz variant.
059 *
060 * <p> The version field holds a value that describes the type of this {@code
061 * UUID}. There are four different basic types of UUIDs: time-based, DCE
062 * security, name-based, and randomly generated UUIDs. These types have a
063 * version value of 1, 2, 3 and 4, respectively.
064 *
065 * <p> For more information including algorithms used to create {@code UUID}s,
066 * see <a href="http://www.ietf.org/rfc/rfc4122.txt"> <i>RFC 4122: A
067 * Universally Unique IDentifier (UUID) URN Namespace</i></a>, section 4.2
068 * "Algorithms for Creating a Time-Based UUID".
069 *
070 * @since 1.5
071 */
072 public final class UUID implements java.io.Serializable,
073 Comparable<UUID> {
074
075 /**
076 * Explicit serialVersionUID for interoperability.
077 */
078 private static final long serialVersionUID = -4856846361193249489L;
079
080 /*
081 * The most significant 64 bits of this UUID.
082 *
083 * @serial
084 */
085 private final long mostSigBits;
086
087 /*
088 * The least significant 64 bits of this UUID.
089 *
090 * @serial
091 */
092 private final long leastSigBits;
093
094 /*
095 * The version number associated with this UUID. Computed on demand.
096 */
097 private transient int version = -1;
098
099 /*
100 * The variant number associated with this UUID. Computed on demand.
101 */
102 private transient int variant = -1;
103
104 /*
105 * The timestamp associated with this UUID. Computed on demand.
106 */
107 private transient volatile long timestamp = -1;
108
109 /*
110 * The clock sequence associated with this UUID. Computed on demand.
111 */
112 private transient int sequence = -1;
113
114 /*
115 * The node number associated with this UUID. Computed on demand.
116 */
117 private transient long node = -1;
118
119 /*
120 * The hashcode of this UUID. Computed on demand.
121 */
122 private transient int hashCode = -1;
123
124 /*
125 * The random number generator used by this class to create random
126 * based UUIDs.
127 */
128 private static volatile SecureRandom numberGenerator = null;
129
130 // Constructors and Factories
131
132 /*
133 * Private constructor which uses a byte array to construct the new UUID.
134 */
135 private UUID(byte[] data) {
136 long msb = 0;
137 long lsb = 0;
138 assert data.length == 16;
139 for (int i = 0; i < 8; i++)
140 msb = (msb << 8) | (data[i] & 0xff);
141 for (int i = 8; i < 16; i++)
142 lsb = (lsb << 8) | (data[i] & 0xff);
143 this .mostSigBits = msb;
144 this .leastSigBits = lsb;
145 }
146
147 /**
148 * Constructs a new {@code UUID} using the specified data. {@code
149 * mostSigBits} is used for the most significant 64 bits of the {@code
150 * UUID} and {@code leastSigBits} becomes the least significant 64 bits of
151 * the {@code UUID}.
152 *
153 * @param mostSigBits
154 * The most significant bits of the {@code UUID}
155 *
156 * @param leastSigBits
157 * The least significant bits of the {@code UUID}
158 */
159 public UUID(long mostSigBits, long leastSigBits) {
160 this .mostSigBits = mostSigBits;
161 this .leastSigBits = leastSigBits;
162 }
163
164 /**
165 * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
166 *
167 * The {@code UUID} is generated using a cryptographically strong pseudo
168 * random number generator.
169 *
170 * @return A randomly generated {@code UUID}
171 */
172 public static UUID randomUUID() {
173 SecureRandom ng = numberGenerator;
174 if (ng == null) {
175 numberGenerator = ng = new SecureRandom();
176 }
177
178 byte[] randomBytes = new byte[16];
179 ng.nextBytes(randomBytes);
180 randomBytes[6] &= 0x0f; /* clear version */
181 randomBytes[6] |= 0x40; /* set to version 4 */
182 randomBytes[8] &= 0x3f; /* clear variant */
183 randomBytes[8] |= 0x80; /* set to IETF variant */
184 return new UUID(randomBytes);
185 }
186
187 /**
188 * Static factory to retrieve a type 3 (name based) {@code UUID} based on
189 * the specified byte array.
190 *
191 * @param name
192 * A byte array to be used to construct a {@code UUID}
193 *
194 * @return A {@code UUID} generated from the specified array
195 */
196 public static UUID nameUUIDFromBytes(byte[] name) {
197 MessageDigest md;
198 try {
199 md = MessageDigest.getInstance("MD5");
200 } catch (NoSuchAlgorithmException nsae) {
201 throw new InternalError("MD5 not supported");
202 }
203 byte[] md5Bytes = md.digest(name);
204 md5Bytes[6] &= 0x0f; /* clear version */
205 md5Bytes[6] |= 0x30; /* set to version 3 */
206 md5Bytes[8] &= 0x3f; /* clear variant */
207 md5Bytes[8] |= 0x80; /* set to IETF variant */
208 return new UUID(md5Bytes);
209 }
210
211 /**
212 * Creates a {@code UUID} from the string standard representation as
213 * described in the {@link #toString} method.
214 *
215 * @param name
216 * A string that specifies a {@code UUID}
217 *
218 * @return A {@code UUID} with the specified value
219 *
220 * @throws IllegalArgumentException
221 * If name does not conform to the string representation as
222 * described in {@link #toString}
223 *
224 */
225 public static UUID fromString(String name) {
226 String[] components = name.split("-");
227 if (components.length != 5)
228 throw new IllegalArgumentException("Invalid UUID string: "
229 + name);
230 for (int i = 0; i < 5; i++)
231 components[i] = "0x" + components[i];
232
233 long mostSigBits = Long.decode(components[0]).longValue();
234 mostSigBits <<= 16;
235 mostSigBits |= Long.decode(components[1]).longValue();
236 mostSigBits <<= 16;
237 mostSigBits |= Long.decode(components[2]).longValue();
238
239 long leastSigBits = Long.decode(components[3]).longValue();
240 leastSigBits <<= 48;
241 leastSigBits |= Long.decode(components[4]).longValue();
242
243 return new UUID(mostSigBits, leastSigBits);
244 }
245
246 // Field Accessor Methods
247
248 /**
249 * Returns the least significant 64 bits of this UUID's 128 bit value.
250 *
251 * @return The least significant 64 bits of this UUID's 128 bit value
252 */
253 public long getLeastSignificantBits() {
254 return leastSigBits;
255 }
256
257 /**
258 * Returns the most significant 64 bits of this UUID's 128 bit value.
259 *
260 * @return The most significant 64 bits of this UUID's 128 bit value
261 */
262 public long getMostSignificantBits() {
263 return mostSigBits;
264 }
265
266 /**
267 * The version number associated with this {@code UUID}. The version
268 * number describes how this {@code UUID} was generated.
269 *
270 * The version number has the following meaning:
271 * <p><ul>
272 * <li>1 Time-based UUID
273 * <li>2 DCE security UUID
274 * <li>3 Name-based UUID
275 * <li>4 Randomly generated UUID
276 * </ul>
277 *
278 * @return The version number of this {@code UUID}
279 */
280 public int version() {
281 if (version < 0) {
282 // Version is bits masked by 0x000000000000F000 in MS long
283 version = (int) ((mostSigBits >> 12) & 0x0f);
284 }
285 return version;
286 }
287
288 /**
289 * The variant number associated with this {@code UUID}. The variant
290 * number describes the layout of the {@code UUID}.
291 *
292 * The variant number has the following meaning:
293 * <p><ul>
294 * <li>0 Reserved for NCS backward compatibility
295 * <li>2 The Leach-Salz variant (used by this class)
296 * <li>6 Reserved, Microsoft Corporation backward compatibility
297 * <li>7 Reserved for future definition
298 * </ul>
299 *
300 * @return The variant number of this {@code UUID}
301 */
302 public int variant() {
303 if (variant < 0) {
304 // This field is composed of a varying number of bits
305 if ((leastSigBits >>> 63) == 0) {
306 variant = 0;
307 } else if ((leastSigBits >>> 62) == 2) {
308 variant = 2;
309 } else {
310 variant = (int) (leastSigBits >>> 61);
311 }
312 }
313 return variant;
314 }
315
316 /**
317 * The timestamp value associated with this UUID.
318 *
319 * <p> The 60 bit timestamp value is constructed from the time_low,
320 * time_mid, and time_hi fields of this {@code UUID}. The resulting
321 * timestamp is measured in 100-nanosecond units since midnight,
322 * October 15, 1582 UTC.
323 *
324 * <p> The timestamp value is only meaningful in a time-based UUID, which
325 * has version type 1. If this {@code UUID} is not a time-based UUID then
326 * this method throws UnsupportedOperationException.
327 *
328 * @throws UnsupportedOperationException
329 * If this UUID is not a version 1 UUID
330 */
331 public long timestamp() {
332 if (version() != 1) {
333 throw new UnsupportedOperationException(
334 "Not a time-based UUID");
335 }
336 long result = timestamp;
337 if (result < 0) {
338 result = (mostSigBits & 0x0000000000000FFFL) << 48;
339 result |= ((mostSigBits >> 16) & 0xFFFFL) << 32;
340 result |= mostSigBits >>> 32;
341 timestamp = result;
342 }
343 return result;
344 }
345
346 /**
347 * The clock sequence value associated with this UUID.
348 *
349 * <p> The 14 bit clock sequence value is constructed from the clock
350 * sequence field of this UUID. The clock sequence field is used to
351 * guarantee temporal uniqueness in a time-based UUID.
352 *
353 * <p> The {@code clockSequence} value is only meaningful in a time-based
354 * UUID, which has version type 1. If this UUID is not a time-based UUID
355 * then this method throws UnsupportedOperationException.
356 *
357 * @return The clock sequence of this {@code UUID}
358 *
359 * @throws UnsupportedOperationException
360 * If this UUID is not a version 1 UUID
361 */
362 public int clockSequence() {
363 if (version() != 1) {
364 throw new UnsupportedOperationException(
365 "Not a time-based UUID");
366 }
367 if (sequence < 0) {
368 sequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
369 }
370 return sequence;
371 }
372
373 /**
374 * The node value associated with this UUID.
375 *
376 * <p> The 48 bit node value is constructed from the node field of this
377 * UUID. This field is intended to hold the IEEE 802 address of the machine
378 * that generated this UUID to guarantee spatial uniqueness.
379 *
380 * <p> The node value is only meaningful in a time-based UUID, which has
381 * version type 1. If this UUID is not a time-based UUID then this method
382 * throws UnsupportedOperationException.
383 *
384 * @return The node value of this {@code UUID}
385 *
386 * @throws UnsupportedOperationException
387 * If this UUID is not a version 1 UUID
388 */
389 public long node() {
390 if (version() != 1) {
391 throw new UnsupportedOperationException(
392 "Not a time-based UUID");
393 }
394 if (node < 0) {
395 node = leastSigBits & 0x0000FFFFFFFFFFFFL;
396 }
397 return node;
398 }
399
400 // Object Inherited Methods
401
402 /**
403 * Returns a {@code String} object representing this {@code UUID}.
404 *
405 * <p> The UUID string representation is as described by this BNF:
406 * <blockquote><pre>
407 * {@code
408 * UUID = <time_low> "-" <time_mid> "-"
409 * <time_high_and_version> "-"
410 * <variant_and_sequence> "-"
411 * <node>
412 * time_low = 4*<hexOctet>
413 * time_mid = 2*<hexOctet>
414 * time_high_and_version = 2*<hexOctet>
415 * variant_and_sequence = 2*<hexOctet>
416 * node = 6*<hexOctet>
417 * hexOctet = <hexDigit><hexDigit>
418 * hexDigit =
419 * "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
420 * | "a" | "b" | "c" | "d" | "e" | "f"
421 * | "A" | "B" | "C" | "D" | "E" | "F"
422 * }</pre></blockquote>
423 *
424 * @return A string representation of this {@code UUID}
425 */
426 public String toString() {
427 return (digits(mostSigBits >> 32, 8) + "-"
428 + digits(mostSigBits >> 16, 4) + "-"
429 + digits(mostSigBits, 4) + "-"
430 + digits(leastSigBits >> 48, 4) + "-" + digits(
431 leastSigBits, 12));
432 }
433
434 /** Returns val represented by the specified number of hex digits. */
435 private static String digits(long val, int digits) {
436 long hi = 1L << (digits * 4);
437 return Long.toHexString(hi | (val & (hi - 1))).substring(1);
438 }
439
440 /**
441 * Returns a hash code for this {@code UUID}.
442 *
443 * @return A hash code value for this {@code UUID}
444 */
445 public int hashCode() {
446 if (hashCode == -1) {
447 hashCode = (int) ((mostSigBits >> 32) ^ mostSigBits
448 ^ (leastSigBits >> 32) ^ leastSigBits);
449 }
450 return hashCode;
451 }
452
453 /**
454 * Compares this object to the specified object. The result is {@code
455 * true} if and only if the argument is not {@code null}, is a {@code UUID}
456 * object, has the same variant, and contains the same value, bit for bit,
457 * as this {@code UUID}.
458 *
459 * @param obj
460 * The object to be compared
461 *
462 * @return {@code true} if the objects are the same; {@code false}
463 * otherwise
464 */
465 public boolean equals(Object obj) {
466 if (!(obj instanceof UUID))
467 return false;
468 if (((UUID) obj).variant() != this .variant())
469 return false;
470 UUID id = (UUID) obj;
471 return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
472 }
473
474 // Comparison Operations
475
476 /**
477 * Compares this UUID with the specified UUID.
478 *
479 * <p> The first of two UUIDs is greater than the second if the most
480 * significant field in which the UUIDs differ is greater for the first
481 * UUID.
482 *
483 * @param val
484 * {@code UUID} to which this {@code UUID} is to be compared
485 *
486 * @return -1, 0 or 1 as this {@code UUID} is less than, equal to, or
487 * greater than {@code val}
488 *
489 */
490 public int compareTo(UUID val) {
491 // The ordering is intentionally set up so that the UUIDs
492 // can simply be numerically compared as two numbers
493 return (this .mostSigBits < val.mostSigBits ? -1
494 : (this .mostSigBits > val.mostSigBits ? 1
495 : (this .leastSigBits < val.leastSigBits ? -1
496 : (this .leastSigBits > val.leastSigBits ? 1
497 : 0))));
498 }
499
500 /**
501 * Reconstitute the {@code UUID} instance from a stream (that is,
502 * deserialize it). This is necessary to set the transient fields to their
503 * correct uninitialized value so they will be recomputed on demand.
504 */
505 private void readObject(java.io.ObjectInputStream in)
506 throws java.io.IOException, ClassNotFoundException {
507
508 in.defaultReadObject();
509
510 // Set "cached computation" fields to their initial values
511 version = -1;
512 variant = -1;
513 timestamp = -1;
514 sequence = -1;
515 node = -1;
516 hashCode = -1;
517 }
518 }
|