• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.util;
27 
28 import android.compat.Compatibility;
29 import android.compat.annotation.ChangeId;
30 import android.compat.annotation.EnabledSince;
31 
32 import dalvik.annotation.compat.VersionCodes;
33 import dalvik.system.VMRuntime;
34 
35 import java.security.*;
36 
37 // Android-removed: not using JavaLangAccess.fastUUID.
38 // import jdk.internal.misc.JavaLangAccess;
39 // import jdk.internal.misc.SharedSecrets;
40 
41 /**
42  * A class that represents an immutable universally unique identifier (UUID).
43  * A UUID represents a 128-bit value.
44  *
45  * <p> There exist different variants of these global identifiers.  The methods
46  * of this class are for manipulating the Leach-Salz variant, although the
47  * constructors allow the creation of any variant of UUID (described below).
48  *
49  * <p> The layout of a variant 2 (Leach-Salz) UUID is as follows:
50  *
51  * The most significant long consists of the following unsigned fields:
52  * <pre>
53  * 0xFFFFFFFF00000000 time_low
54  * 0x00000000FFFF0000 time_mid
55  * 0x000000000000F000 version
56  * 0x0000000000000FFF time_hi
57  * </pre>
58  * The least significant long consists of the following unsigned fields:
59  * <pre>
60  * 0xC000000000000000 variant
61  * 0x3FFF000000000000 clock_seq
62  * 0x0000FFFFFFFFFFFF node
63  * </pre>
64  *
65  * <p> The variant field contains a value which identifies the layout of the
66  * {@code UUID}.  The bit layout described above is valid only for a {@code
67  * UUID} with a variant value of 2, which indicates the Leach-Salz variant.
68  *
69  * <p> The version field holds a value that describes the type of this {@code
70  * UUID}.  There are four different basic types of UUIDs: time-based, DCE
71  * security, name-based, and randomly generated UUIDs.  These types have a
72  * version value of 1, 2, 3 and 4, respectively.
73  *
74  * <p> For more information including algorithms used to create {@code UUID}s,
75  * see <a href="http://www.ietf.org/rfc/rfc4122.txt"> <i>RFC&nbsp;4122: A
76  * Universally Unique IDentifier (UUID) URN Namespace</i></a>, section 4.2
77  * &quot;Algorithms for Creating a Time-Based UUID&quot;.
78  *
79  * @since   1.5
80  */
81 public final class UUID implements java.io.Serializable, Comparable<UUID> {
82 
83     /**
84      * Explicit serialVersionUID for interoperability.
85      */
86     private static final long serialVersionUID = -4856846361193249489L;
87 
88     /*
89      * The most significant 64 bits of this UUID.
90      *
91      * @serial
92      */
93     private final long mostSigBits;
94 
95     /*
96      * The least significant 64 bits of this UUID.
97      *
98      * @serial
99      */
100     private final long leastSigBits;
101 
102     // Android-removed: not using JavaLangAccess.fastUUID.
103     // private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
104 
105     /*
106      * The random number generator used by this class to create random
107      * based UUIDs. In a holder class to defer initialization until needed.
108      */
109     private static class Holder {
110         static final SecureRandom numberGenerator = new SecureRandom();
111     }
112 
113     // Constructors and Factories
114 
115     /*
116      * Private constructor which uses a byte array to construct the new UUID.
117      */
UUID(byte[] data)118     private UUID(byte[] data) {
119         long msb = 0;
120         long lsb = 0;
121         assert data.length == 16 : "data must be 16 bytes in length";
122         for (int i=0; i<8; i++)
123             msb = (msb << 8) | (data[i] & 0xff);
124         for (int i=8; i<16; i++)
125             lsb = (lsb << 8) | (data[i] & 0xff);
126         this.mostSigBits = msb;
127         this.leastSigBits = lsb;
128     }
129 
130     /**
131      * Constructs a new {@code UUID} using the specified data.  {@code
132      * mostSigBits} is used for the most significant 64 bits of the {@code
133      * UUID} and {@code leastSigBits} becomes the least significant 64 bits of
134      * the {@code UUID}.
135      *
136      * @param  mostSigBits
137      *         The most significant bits of the {@code UUID}
138      *
139      * @param  leastSigBits
140      *         The least significant bits of the {@code UUID}
141      */
UUID(long mostSigBits, long leastSigBits)142     public UUID(long mostSigBits, long leastSigBits) {
143         this.mostSigBits = mostSigBits;
144         this.leastSigBits = leastSigBits;
145     }
146 
147     /**
148      * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
149      *
150      * The {@code UUID} is generated using a cryptographically strong pseudo
151      * random number generator.
152      *
153      * @return  A randomly generated {@code UUID}
154      */
randomUUID()155     public static UUID randomUUID() {
156         SecureRandom ng = Holder.numberGenerator;
157 
158         byte[] randomBytes = new byte[16];
159         ng.nextBytes(randomBytes);
160         randomBytes[6]  &= 0x0f;  /* clear version        */
161         randomBytes[6]  |= 0x40;  /* set to version 4     */
162         randomBytes[8]  &= 0x3f;  /* clear variant        */
163         randomBytes[8]  |= 0x80;  /* set to IETF variant  */
164         return new UUID(randomBytes);
165     }
166 
167     /**
168      * Static factory to retrieve a type 3 (name based) {@code UUID} based on
169      * the specified byte array.
170      *
171      * @param  name
172      *         A byte array to be used to construct a {@code UUID}
173      *
174      * @return  A {@code UUID} generated from the specified array
175      */
nameUUIDFromBytes(byte[] name)176     public static UUID nameUUIDFromBytes(byte[] name) {
177         MessageDigest md;
178         try {
179             md = MessageDigest.getInstance("MD5");
180         } catch (NoSuchAlgorithmException nsae) {
181             throw new InternalError("MD5 not supported", nsae);
182         }
183         byte[] md5Bytes = md.digest(name);
184         md5Bytes[6]  &= 0x0f;  /* clear version        */
185         md5Bytes[6]  |= 0x30;  /* set to version 3     */
186         md5Bytes[8]  &= 0x3f;  /* clear variant        */
187         md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
188         return new UUID(md5Bytes);
189     }
190 
191     /**
192      * Since Android 14 {@link #fromString} does more strict input argument
193      * validation.
194      *
195      * This flag is enabled for apps targeting Android 14+.
196      *
197      * @hide
198      */
199     @ChangeId
200     @EnabledSince(targetSdkVersion = VersionCodes.UPSIDE_DOWN_CAKE)
201     public static final long ENABLE_STRICT_VALIDATION = 263076149L;
202 
203     /**
204      * Creates a {@code UUID} from the string standard representation as
205      * described in the {@link #toString} method.
206      *
207      * @param  name
208      *         A string that specifies a {@code UUID}
209      *
210      * @return  A {@code UUID} with the specified value
211      *
212      * @throws  IllegalArgumentException
213      *          If name does not conform to the string representation as
214      *          described in {@link #toString}
215      *
216      */
fromString(String name)217     public static UUID fromString(String name) {
218         // BEGIN Android-changed: Java 8 behaviour is more lenient and the new implementation
219         // might break apps (b/254278943).
220         // Using old implementation for apps targeting Android older than U.
221         if (!(VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE
222                 && Compatibility.isChangeEnabled(ENABLE_STRICT_VALIDATION))) {
223             return fromStringJava8(name);
224         }
225 
226         return fromStringJava11(name);
227         // END Android-changed: Java 8 behaviour is more lenient and the new implementation
228         // might break apps (b/254278943).
229     }
230 
231     /**
232      * Extracted for testing purposes only.
233      * @hide
234      */
fromStringJava11(String name)235     public static UUID fromStringJava11(String name) {
236         int len = name.length();
237         if (len > 36) {
238             throw new IllegalArgumentException("UUID string too large");
239         }
240 
241         int dash1 = name.indexOf('-', 0);
242         int dash2 = name.indexOf('-', dash1 + 1);
243         int dash3 = name.indexOf('-', dash2 + 1);
244         int dash4 = name.indexOf('-', dash3 + 1);
245         int dash5 = name.indexOf('-', dash4 + 1);
246 
247         // For any valid input, dash1 through dash4 will be positive and dash5
248         // negative, but it's enough to check dash4 and dash5:
249         // - if dash1 is -1, dash4 will be -1
250         // - if dash1 is positive but dash2 is -1, dash4 will be -1
251         // - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
252         //   positive, but so will dash5
253         if (dash4 < 0 || dash5 >= 0) {
254             throw new IllegalArgumentException("Invalid UUID string: " + name);
255         }
256 
257         long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL;
258         mostSigBits <<= 16;
259         mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL;
260         mostSigBits <<= 16;
261         mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL;
262         long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL;
263         leastSigBits <<= 48;
264         leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL;
265 
266         return new UUID(mostSigBits, leastSigBits);
267     }
268 
269     /**
270      * Extracted for testing purposes only.
271      * @hide
272      */
fromStringJava8(String name)273     public static UUID fromStringJava8(String name) {
274         String[] components = name.split("-");
275         if (components.length != 5)
276             throw new IllegalArgumentException("Invalid UUID string: "+ name);
277         for (int i=0; i<5; i++)
278             components[i] = "0x"+components[i];
279 
280         long mostSigBits = Long.decode(components[0]).longValue();
281         mostSigBits <<= 16;
282         mostSigBits |= Long.decode(components[1]).longValue();
283         mostSigBits <<= 16;
284         mostSigBits |= Long.decode(components[2]).longValue();
285 
286         long leastSigBits = Long.decode(components[3]).longValue();
287         leastSigBits <<= 48;
288         leastSigBits |= Long.decode(components[4]).longValue();
289 
290         return new UUID(mostSigBits, leastSigBits);
291     }
292 
293     // Field Accessor Methods
294 
295     /**
296      * Returns the least significant 64 bits of this UUID's 128 bit value.
297      *
298      * @return  The least significant 64 bits of this UUID's 128 bit value
299      */
getLeastSignificantBits()300     public long getLeastSignificantBits() {
301         return leastSigBits;
302     }
303 
304     /**
305      * Returns the most significant 64 bits of this UUID's 128 bit value.
306      *
307      * @return  The most significant 64 bits of this UUID's 128 bit value
308      */
getMostSignificantBits()309     public long getMostSignificantBits() {
310         return mostSigBits;
311     }
312 
313     /**
314      * The version number associated with this {@code UUID}.  The version
315      * number describes how this {@code UUID} was generated.
316      *
317      * The version number has the following meaning:
318      * <ul>
319      * <li>1    Time-based UUID
320      * <li>2    DCE security UUID
321      * <li>3    Name-based UUID
322      * <li>4    Randomly generated UUID
323      * </ul>
324      *
325      * @return  The version number of this {@code UUID}
326      */
version()327     public int version() {
328         // Version is bits masked by 0x000000000000F000 in MS long
329         return (int)((mostSigBits >> 12) & 0x0f);
330     }
331 
332     /**
333      * The variant number associated with this {@code UUID}.  The variant
334      * number describes the layout of the {@code UUID}.
335      *
336      * The variant number has the following meaning:
337      * <ul>
338      * <li>0    Reserved for NCS backward compatibility
339      * <li>2    <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>
340      * (Leach-Salz), used by this class
341      * <li>6    Reserved, Microsoft Corporation backward compatibility
342      * <li>7    Reserved for future definition
343      * </ul>
344      *
345      * @return  The variant number of this {@code UUID}
346      */
variant()347     public int variant() {
348         // This field is composed of a varying number of bits.
349         // 0    -    -    Reserved for NCS backward compatibility
350         // 1    0    -    The IETF aka Leach-Salz variant (used by this class)
351         // 1    1    0    Reserved, Microsoft backward compatibility
352         // 1    1    1    Reserved for future definition.
353         return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
354                       & (leastSigBits >> 63));
355     }
356 
357     /**
358      * The timestamp value associated with this UUID.
359      *
360      * <p> The 60 bit timestamp value is constructed from the time_low,
361      * time_mid, and time_hi fields of this {@code UUID}.  The resulting
362      * timestamp is measured in 100-nanosecond units since midnight,
363      * October 15, 1582 UTC.
364      *
365      * <p> The timestamp value is only meaningful in a time-based UUID, which
366      * has version type 1.  If this {@code UUID} is not a time-based UUID then
367      * this method throws UnsupportedOperationException.
368      *
369      * @throws UnsupportedOperationException
370      *         If this UUID is not a version 1 UUID
371      * @return The timestamp of this {@code UUID}.
372      */
timestamp()373     public long timestamp() {
374         if (version() != 1) {
375             throw new UnsupportedOperationException("Not a time-based UUID");
376         }
377 
378         return (mostSigBits & 0x0FFFL) << 48
379              | ((mostSigBits >> 16) & 0x0FFFFL) << 32
380              | mostSigBits >>> 32;
381     }
382 
383     /**
384      * The clock sequence value associated with this UUID.
385      *
386      * <p> The 14 bit clock sequence value is constructed from the clock
387      * sequence field of this UUID.  The clock sequence field is used to
388      * guarantee temporal uniqueness in a time-based UUID.
389      *
390      * <p> The {@code clockSequence} value is only meaningful in a time-based
391      * UUID, which has version type 1.  If this UUID is not a time-based UUID
392      * then this method throws UnsupportedOperationException.
393      *
394      * @return  The clock sequence of this {@code UUID}
395      *
396      * @throws  UnsupportedOperationException
397      *          If this UUID is not a version 1 UUID
398      */
clockSequence()399     public int clockSequence() {
400         if (version() != 1) {
401             throw new UnsupportedOperationException("Not a time-based UUID");
402         }
403 
404         return (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
405     }
406 
407     /**
408      * The node value associated with this UUID.
409      *
410      * <p> The 48 bit node value is constructed from the node field of this
411      * UUID.  This field is intended to hold the IEEE 802 address of the machine
412      * that generated this UUID to guarantee spatial uniqueness.
413      *
414      * <p> The node value is only meaningful in a time-based UUID, which has
415      * version type 1.  If this UUID is not a time-based UUID then this method
416      * throws UnsupportedOperationException.
417      *
418      * @return  The node value of this {@code UUID}
419      *
420      * @throws  UnsupportedOperationException
421      *          If this UUID is not a version 1 UUID
422      */
node()423     public long node() {
424         if (version() != 1) {
425             throw new UnsupportedOperationException("Not a time-based UUID");
426         }
427 
428         return leastSigBits & 0x0000FFFFFFFFFFFFL;
429     }
430 
431     // Object Inherited Methods
432 
433     /**
434      * Returns a {@code String} object representing this {@code UUID}.
435      *
436      * <p> The UUID string representation is as described by this BNF:
437      * <blockquote><pre>
438      * {@code
439      * UUID                   = <time_low> "-" <time_mid> "-"
440      *                          <time_high_and_version> "-"
441      *                          <variant_and_sequence> "-"
442      *                          <node>
443      * time_low               = 4*<hexOctet>
444      * time_mid               = 2*<hexOctet>
445      * time_high_and_version  = 2*<hexOctet>
446      * variant_and_sequence   = 2*<hexOctet>
447      * node                   = 6*<hexOctet>
448      * hexOctet               = <hexDigit><hexDigit>
449      * hexDigit               =
450      *       "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
451      *       | "a" | "b" | "c" | "d" | "e" | "f"
452      *       | "A" | "B" | "C" | "D" | "E" | "F"
453      * }</pre></blockquote>
454      *
455      * @return  A string representation of this {@code UUID}
456      */
toString()457     public String toString() {
458         // Android-changed: using old implementation.
459         // return jla.fastUUID(leastSigBits, mostSigBits);
460         return (digits(mostSigBits >> 32, 8) + "-" +
461                 digits(mostSigBits >> 16, 4) + "-" +
462                 digits(mostSigBits, 4) + "-" +
463                 digits(leastSigBits >> 48, 4) + "-" +
464                 digits(leastSigBits, 12));
465     }
466 
467     /** Returns val represented by the specified number of hex digits. */
digits(long val, int digits)468     private static String digits(long val, int digits) {
469         long hi = 1L << (digits * 4);
470         return Long.toHexString(hi | (val & (hi - 1))).substring(1);
471     }
472 
473     /**
474      * Returns a hash code for this {@code UUID}.
475      *
476      * @return  A hash code value for this {@code UUID}
477      */
hashCode()478     public int hashCode() {
479         long hilo = mostSigBits ^ leastSigBits;
480         return ((int)(hilo >> 32)) ^ (int) hilo;
481     }
482 
483     /**
484      * Compares this object to the specified object.  The result is {@code
485      * true} if and only if the argument is not {@code null}, is a {@code UUID}
486      * object, has the same variant, and contains the same value, bit for bit,
487      * as this {@code UUID}.
488      *
489      * @param  obj
490      *         The object to be compared
491      *
492      * @return  {@code true} if the objects are the same; {@code false}
493      *          otherwise
494      */
equals(Object obj)495     public boolean equals(Object obj) {
496         if ((null == obj) || (obj.getClass() != UUID.class))
497             return false;
498         UUID id = (UUID)obj;
499         return (mostSigBits == id.mostSigBits &&
500                 leastSigBits == id.leastSigBits);
501     }
502 
503     // Comparison Operations
504 
505     /**
506      * Compares this UUID with the specified UUID.
507      *
508      * <p> The first of two UUIDs is greater than the second if the most
509      * significant field in which the UUIDs differ is greater for the first
510      * UUID.
511      *
512      * @param  val
513      *         {@code UUID} to which this {@code UUID} is to be compared
514      *
515      * @return  -1, 0 or 1 as this {@code UUID} is less than, equal to, or
516      *          greater than {@code val}
517      *
518      */
compareTo(UUID val)519     public int compareTo(UUID val) {
520         // The ordering is intentionally set up so that the UUIDs
521         // can simply be numerically compared as two numbers
522         return (this.mostSigBits < val.mostSigBits ? -1 :
523                 (this.mostSigBits > val.mostSigBits ? 1 :
524                  (this.leastSigBits < val.leastSigBits ? -1 :
525                   (this.leastSigBits > val.leastSigBits ? 1 :
526                    0))));
527     }
528 }
529