1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.util;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.Serializable;
23import java.nio.ByteOrder;
24import java.security.MessageDigest;
25import java.security.NoSuchAlgorithmException;
26import java.security.SecureRandom;
27import libcore.io.Memory;
28
29/**
30 * UUID is an immutable representation of a 128-bit universally unique
31 * identifier (UUID).
32 * <p>
33 * There are multiple, variant layouts of UUIDs, but this class is based upon
34 * variant 2 of <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>, the
35 * Leach-Salz variant. This class can be used to model alternate variants, but
36 * most of the methods will be unsupported in those cases; see each method for
37 * details.
38 *
39 * @since 1.5
40 */
41public final class UUID implements Serializable, Comparable<UUID> {
42
43    private static final long serialVersionUID = -4856846361193249489L;
44
45    private static SecureRandom rng;
46
47    private long mostSigBits;
48    private long leastSigBits;
49
50    private transient int variant;
51    private transient int version;
52    private transient long timestamp;
53    private transient int clockSequence;
54    private transient long node;
55    private transient int hash;
56
57    /**
58     * <p>
59     * Constructs an instance with the specified bits.
60     *
61     * @param mostSigBits
62     *            The 64 most significant bits of the UUID.
63     * @param leastSigBits
64     *            The 64 least significant bits of the UUID.
65     */
66    public UUID(long mostSigBits, long leastSigBits) {
67        this.mostSigBits = mostSigBits;
68        this.leastSigBits = leastSigBits;
69        init();
70    }
71
72    /**
73     * <p>
74     * Sets up the transient fields of this instance based on the current values
75     * of the {@code mostSigBits} and {@code leastSigBits} fields.
76     */
77    private void init() {
78        // setup hash field
79        int msbHash = (int) (mostSigBits ^ (mostSigBits >>> 32));
80        int lsbHash = (int) (leastSigBits ^ (leastSigBits >>> 32));
81        hash = msbHash ^ lsbHash;
82
83        // setup variant field
84        if ((leastSigBits & 0x8000000000000000L) == 0) {
85            // MSB0 not set, NCS backwards compatibility variant
86            variant = 0;
87        } else if ((leastSigBits & 0x4000000000000000L) != 0) {
88            // MSB1 set, either MS reserved or future reserved
89            variant = (int) ((leastSigBits & 0xE000000000000000L) >>> 61);
90        } else {
91            // MSB1 not set, RFC 4122 variant
92            variant = 2;
93        }
94
95        // setup version field
96        version = (int) ((mostSigBits & 0x000000000000F000) >>> 12);
97
98        if (variant != 2 && version != 1) {
99            return;
100        }
101
102        // setup timestamp field
103        long timeLow = (mostSigBits & 0xFFFFFFFF00000000L) >>> 32;
104        long timeMid = (mostSigBits & 0x00000000FFFF0000L) << 16;
105        long timeHigh = (mostSigBits & 0x0000000000000FFFL) << 48;
106        timestamp = timeLow | timeMid | timeHigh;
107
108        // setup clock sequence field
109        clockSequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
110
111        // setup node field
112        node = (leastSigBits & 0x0000FFFFFFFFFFFFL);
113    }
114
115    /**
116     * <p>
117     * Generates a variant 2, version 4 (randomly generated number) UUID as per
118     * <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
119     *
120     * @return an UUID instance.
121     */
122    public static UUID randomUUID() {
123        byte[] data = new byte[16];
124        // lock on the class to protect lazy init
125        synchronized (UUID.class) {
126            if (rng == null) {
127                rng = new SecureRandom();
128            }
129        }
130        rng.nextBytes(data);
131        return makeUuid(data, 4);
132    }
133
134    /**
135     * <p>
136     * Generates a variant 2, version 3 (name-based, MD5-hashed) UUID as per <a
137     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
138     *
139     * @param name
140     *            the name used as byte array to create an UUID.
141     * @return an UUID instance.
142     */
143    public static UUID nameUUIDFromBytes(byte[] name) {
144        if (name == null) {
145            throw new NullPointerException("name == null");
146        }
147        try {
148            MessageDigest md = MessageDigest.getInstance("MD5");
149            return makeUuid(md.digest(name), 3);
150        } catch (NoSuchAlgorithmException e) {
151            throw new AssertionError(e);
152        }
153    }
154
155    private static UUID makeUuid(byte[] hash, int version) {
156        long msb = Memory.peekLong(hash, 0, ByteOrder.BIG_ENDIAN);
157        long lsb = Memory.peekLong(hash, 8, ByteOrder.BIG_ENDIAN);
158        // Set the version field.
159        msb &= ~(0xfL << 12);
160        msb |= ((long) version) << 12;
161        // Set the variant field to 2. Note that the variant field is variable-width,
162        // so supporting other variants is not just a matter of changing the constant 2 below!
163        lsb &= ~(0x3L << 62);
164        lsb |= 2L << 62;
165        return new UUID(msb, lsb);
166    }
167
168    /**
169     * <p>
170     * Parses a UUID string with the format defined by {@link #toString()}.
171     *
172     * @param uuid
173     *            the UUID string to parse.
174     * @return an UUID instance.
175     * @throws NullPointerException
176     *             if {@code uuid} is {@code null}.
177     * @throws IllegalArgumentException
178     *             if {@code uuid} is not formatted correctly.
179     */
180    public static UUID fromString(String uuid) {
181        if (uuid == null) {
182            throw new NullPointerException("uuid == null");
183        }
184
185        int[] position = new int[5];
186        int lastPosition = 1;
187        int startPosition = 0;
188
189        int i = 0;
190        for (; i < position.length && lastPosition > 0; i++) {
191            position[i] = uuid.indexOf("-", startPosition);
192            lastPosition = position[i];
193            startPosition = position[i] + 1;
194        }
195
196        // should have and only can have four "-" in UUID
197        if (i != position.length || lastPosition != -1) {
198            throw new IllegalArgumentException("Invalid UUID: " + uuid);
199        }
200
201        long m1 = Long.parseLong(uuid.substring(0, position[0]), 16);
202        long m2 = Long.parseLong(uuid.substring(position[0] + 1, position[1]), 16);
203        long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]), 16);
204
205        long lsb1 = Long.parseLong(uuid.substring(position[2] + 1, position[3]), 16);
206        long lsb2 = Long.parseLong(uuid.substring(position[3] + 1), 16);
207
208        long msb = (m1 << 32) | (m2 << 16) | m3;
209        long lsb = (lsb1 << 48) | lsb2;
210
211        return new UUID(msb, lsb);
212    }
213
214    /**
215     * <p>
216     * The 64 least significant bits of the UUID.
217     *
218     * @return the 64 least significant bits.
219     */
220    public long getLeastSignificantBits() {
221        return leastSigBits;
222    }
223
224    /**
225     * <p>
226     * The 64 most significant bits of the UUID.
227     *
228     * @return the 64 most significant bits.
229     */
230    public long getMostSignificantBits() {
231        return mostSigBits;
232    }
233
234    /**
235     * <p>
236     * The version of the variant 2 UUID as per <a
237     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. If the variant
238     * is not 2, then the version will be 0.
239     * <ul>
240     * <li>1 - Time-based UUID</li>
241     * <li>2 - DCE Security UUID</li>
242     * <li>3 - Name-based with MD5 hashing UUID ({@link #nameUUIDFromBytes(byte[])})</li>
243     * <li>4 - Randomly generated UUID ({@link #randomUUID()})</li>
244     * <li>5 - Name-based with SHA-1 hashing UUID</li>
245     * </ul>
246     *
247     * @return an {@code int} value.
248     */
249    public int version() {
250        return version;
251    }
252
253    /**
254     * <p>
255     * The variant of the UUID as per <a
256     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
257     * <ul>
258     * <li>0 - Reserved for NCS compatibility</li>
259     * <li>2 - RFC 4122/Leach-Salz</li>
260     * <li>6 - Reserved for Microsoft Corporation compatibility</li>
261     * <li>7 - Reserved for future use</li>
262     * </ul>
263     *
264     * @return an {@code int} value.
265     */
266    public int variant() {
267        return variant;
268    }
269
270    /**
271     * <p>
272     * The timestamp value of the version 1, variant 2 UUID as per <a
273     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
274     *
275     * @return a {@code long} value.
276     * @throws UnsupportedOperationException
277     *             if {@link #version()} is not 1.
278     */
279    public long timestamp() {
280        if (version != 1) {
281            throw new UnsupportedOperationException();
282        }
283        return timestamp;
284    }
285
286    /**
287     * <p>
288     * The clock sequence value of the version 1, variant 2 UUID as per <a
289     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
290     *
291     * @return a {@code long} value.
292     * @throws UnsupportedOperationException
293     *             if {@link #version()} is not 1.
294     */
295    public int clockSequence() {
296        if (version != 1) {
297            throw new UnsupportedOperationException();
298        }
299        return clockSequence;
300    }
301
302    /**
303     * <p>
304     * The node value of the version 1, variant 2 UUID as per <a
305     * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
306     *
307     * @return a {@code long} value.
308     * @throws UnsupportedOperationException
309     *             if {@link #version()} is not 1.
310     */
311    public long node() {
312        if (version != 1) {
313            throw new UnsupportedOperationException();
314        }
315        return node;
316    }
317
318    /**
319     * <p>
320     * Compares this UUID to the specified UUID. The natural ordering of UUIDs
321     * is based upon the value of the bits from most significant to least
322     * significant.
323     *
324     * @param uuid
325     *            the UUID to compare to.
326     * @return a value of -1, 0 or 1 if this UUID is less than, equal to or
327     *         greater than {@code uuid}.
328     */
329    public int compareTo(UUID uuid) {
330        if (uuid == this) {
331            return 0;
332        }
333
334        if (this.mostSigBits != uuid.mostSigBits) {
335            return this.mostSigBits < uuid.mostSigBits ? -1 : 1;
336        }
337
338        assert this.mostSigBits == uuid.mostSigBits;
339
340        if (this.leastSigBits != uuid.leastSigBits) {
341            return this.leastSigBits < uuid.leastSigBits ? -1 : 1;
342        }
343
344        assert this.leastSigBits == uuid.leastSigBits;
345
346        return 0;
347    }
348
349    /**
350     * <p>
351     * Compares this UUID to another object for equality. If {@code object}
352     * is not {@code null}, is a UUID instance, and all bits are equal, then
353     * {@code true} is returned.
354     *
355     * @param object
356     *            the {@code Object} to compare to.
357     * @return {@code true} if this UUID is equal to {@code object}
358     *         or {@code false} if not.
359     */
360    @Override
361    public boolean equals(Object object) {
362        if (object == null) {
363            return false;
364        }
365
366        if (this == object) {
367            return true;
368        }
369
370        if (!(object instanceof UUID)) {
371            return false;
372        }
373
374        UUID that = (UUID) object;
375
376        return (this.leastSigBits == that.leastSigBits)
377                && (this.mostSigBits == that.mostSigBits);
378    }
379
380    /**
381     * <p>
382     * Returns a hash value for this UUID that is consistent with the
383     * {@link #equals(Object)} method.
384     *
385     * @return an {@code int} value.
386     */
387    @Override
388    public int hashCode() {
389        return hash;
390    }
391
392    /**
393     * <p>
394     * Returns a string representation of this UUID in the following format, as
395     * per <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
396     *
397     * <pre>
398     *            UUID                   = time-low &quot;-&quot; time-mid &quot;-&quot;
399     *                                     time-high-and-version &quot;-&quot;
400     *                                     clock-seq-and-reserved
401     *                                     clock-seq-low &quot;-&quot; node
402     *            time-low               = 4hexOctet
403     *            time-mid               = 2hexOctet
404     *            time-high-and-version  = 2hexOctet
405     *            clock-seq-and-reserved = hexOctet
406     *            clock-seq-low          = hexOctet
407     *            node                   = 6hexOctet
408     *            hexOctet               = hexDigit hexDigit
409     *            hexDigit =
410     *                &quot;0&quot; / &quot;1&quot; / &quot;2&quot; / &quot;3&quot; / &quot;4&quot; / &quot;5&quot; / &quot;6&quot; / &quot;7&quot; / &quot;8&quot; / &quot;9&quot; /
411     *                &quot;a&quot; / &quot;b&quot; / &quot;c&quot; / &quot;d&quot; / &quot;e&quot; / &quot;f&quot; /
412     *                &quot;A&quot; / &quot;B&quot; / &quot;C&quot; / &quot;D&quot; / &quot;E&quot; / &quot;F&quot;
413     * </pre>
414     *
415     * @return a String instance.
416     */
417    @Override
418    public String toString() {
419        StringBuilder builder = new StringBuilder(36);
420        String msbStr = Long.toHexString(mostSigBits);
421        if (msbStr.length() < 16) {
422            int diff = 16 - msbStr.length();
423            for (int i = 0; i < diff; i++) {
424                builder.append('0');
425            }
426        }
427        builder.append(msbStr);
428        builder.insert(8, '-');
429        builder.insert(13, '-');
430        builder.append('-');
431        String lsbStr = Long.toHexString(leastSigBits);
432        if (lsbStr.length() < 16) {
433            int diff = 16 - lsbStr.length();
434            for (int i = 0; i < diff; i++) {
435                builder.append('0');
436            }
437        }
438        builder.append(lsbStr);
439        builder.insert(23, '-');
440        return builder.toString();
441    }
442
443    /**
444     * <p>
445     * Resets the transient fields to match the behavior of the constructor.
446     *
447     * @param in
448     *            the {@code InputStream} to read from.
449     * @throws IOException
450     *             if {@code in} throws it.
451     * @throws ClassNotFoundException
452     *             if {@code in} throws it.
453     */
454    private void readObject(ObjectInputStream in) throws IOException,
455            ClassNotFoundException {
456        // read in non-transient fields
457        in.defaultReadObject();
458        // setup transient fields
459        init();
460    }
461}
462