All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.util.UUID Maven / Gradle / Ivy

There is a newer version: 8.13.4
Show newest version
/*
 * Licensed to Elastic Search and Shay Banon under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. Elastic Search licenses this
 * file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * A UUID taken from java UUID that simply holds less data.
 *
 * @author kimchy (Shay Banon)
 */
public class UUID implements Comparable {

    /*
     * The most significant 64 bits of this UUID.
     *
     * @serial
     */
    private final long mostSigBits;

    /*
     * The least significant 64 bits of this UUID.
     *
     * @serial
     */
    private final long leastSigBits;

    /*
     * The random number generator used by this class to create random
     * based UUIDs.
     */
    private static volatile SecureRandom numberGenerator = null;

    // Constructors and Factories

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

    private UUID(byte[] data) {
        long msb = 0;
        long lsb = 0;
        assert data.length == 16;
        for (int i = 0; i < 8; i++)
            msb = (msb << 8) | (data[i] & 0xff);
        for (int i = 8; i < 16; i++)
            lsb = (lsb << 8) | (data[i] & 0xff);
        this.mostSigBits = msb;
        this.leastSigBits = lsb;
    }

    /**
     * Constructs a new UUID using the specified data.
     * mostSigBits is used for the most significant 64 bits
     * of the UUID and leastSigBits becomes the
     * least significant 64 bits of the UUID.
     *
     * @param mostSigBits
     * @param leastSigBits
     */
    public UUID(long mostSigBits, long leastSigBits) {
        this.mostSigBits = mostSigBits;
        this.leastSigBits = leastSigBits;
    }

    /**
     * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
     *
     * The UUID is generated using a cryptographically strong
     * pseudo random number generator.
     *
     * @return a randomly generated UUID.
     */
    public static UUID randomUUID() {
        SecureRandom ng = numberGenerator;
        if (ng == null) {
            numberGenerator = ng = new SecureRandom();
        }

        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6] &= 0x0f;  /* clear version        */
        randomBytes[6] |= 0x40;  /* set to version 4     */
        randomBytes[8] &= 0x3f;  /* clear variant        */
        randomBytes[8] |= 0x80;  /* set to IETF variant  */
        return new UUID(randomBytes);
    }

    /**
     * Static factory to retrieve a type 3 (name based) UUID based on
     * the specified byte array.
     *
     * @param name a byte array to be used to construct a UUID.
     * @return a UUID generated from the specified array.
     */
    public static UUID nameUUIDFromBytes(byte[] name) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException nsae) {
            throw new InternalError("MD5 not supported");
        }
        byte[] md5Bytes = md.digest(name);
        md5Bytes[6] &= 0x0f;  /* clear version        */
        md5Bytes[6] |= 0x30;  /* set to version 3     */
        md5Bytes[8] &= 0x3f;  /* clear variant        */
        md5Bytes[8] |= 0x80;  /* set to IETF variant  */
        return new UUID(md5Bytes);
    }

    /**
     * Creates a UUID from the string standard representation as
     * described in the {@link #toString} method.
     *
     * @param name a string that specifies a UUID.
     * @return a UUID with the specified value.
     * @throws IllegalArgumentException if name does not conform to the
     *                                  string representation as described in {@link #toString}.
     */
    public static UUID fromString(String name) {
        String[] components = name.split("-");
        if (components.length != 5)
            throw new IllegalArgumentException("Invalid UUID string: " + name);
        for (int i = 0; i < 5; i++)
            components[i] = "0x" + components[i];

        long mostSigBits = Long.decode(components[0]).longValue();
        mostSigBits <<= 16;
        mostSigBits |= Long.decode(components[1]).longValue();
        mostSigBits <<= 16;
        mostSigBits |= Long.decode(components[2]).longValue();

        long leastSigBits = Long.decode(components[3]).longValue();
        leastSigBits <<= 48;
        leastSigBits |= Long.decode(components[4]).longValue();

        return new UUID(mostSigBits, leastSigBits);
    }

    // Field Accessor Methods

    /**
     * Returns the least significant 64 bits of this UUID's 128 bit value.
     *
     * @return the least significant 64 bits of this UUID's 128 bit value.
     */
    public long getLeastSignificantBits() {
        return leastSigBits;
    }

    /**
     * Returns the most significant 64 bits of this UUID's 128 bit value.
     *
     * @return the most significant 64 bits of this UUID's 128 bit value.
     */
    public long getMostSignificantBits() {
        return mostSigBits;
    }

    // Object Inherited Methods

    /**
     * Returns a String object representing this
     * UUID.
     *
     * 

The UUID string representation is as described by this BNF : *

     * {@code
     * UUID                   =  "-"  "-"
     *                           "-"
     *                           "-"
     *                          
     * time_low               = 4*
     * time_mid               = 2*
     * time_high_and_version  = 2*
     * variant_and_sequence   = 2*
     * node                   = 6*
     * hexOctet               = 
     * hexDigit               =
     *       "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
     *       | "a" | "b" | "c" | "d" | "e" | "f"
     *       | "A" | "B" | "C" | "D" | "E" | "F"
     * }
* * @return a string representation of this UUID. */ public String toString() { return (digits(mostSigBits >> 32, 8) + "-" + digits(mostSigBits >> 16, 4) + "-" + digits(mostSigBits, 4) + "-" + digits(leastSigBits >> 48, 4) + "-" + digits(leastSigBits, 12)); } /** * Returns val represented by the specified number of hex digits. */ private static String digits(long val, int digits) { long hi = 1L << (digits * 4); return Long.toHexString(hi | (val & (hi - 1))).substring(1); } /** * Returns a hash code for this UUID. * * @return a hash code value for this UUID. */ public int hashCode() { return (int) ((mostSigBits >> 32) ^ mostSigBits ^ (leastSigBits >> 32) ^ leastSigBits); } /** * Compares this object to the specified object. The result is * true if and only if the argument is not * null, is a UUID object, has the same variant, * and contains the same value, bit for bit, as this UUID. * * @param obj the object to compare with. * @return true if the objects are the same; * false otherwise. */ public boolean equals(Object obj) { if (!(obj instanceof UUID)) return false; UUID id = (UUID) obj; return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); } // Comparison Operations /** * Compares this UUID with the specified UUID. * *

The first of two UUIDs follows the second if the most significant * field in which the UUIDs differ is greater for the first UUID. * * @param val UUID to which this UUID is to be compared. * @return -1, 0 or 1 as this UUID is less than, equal * to, or greater than val. */ public int compareTo(UUID val) { // The ordering is intentionally set up so that the UUIDs // can simply be numerically compared as two numbers return (this.mostSigBits < val.mostSigBits ? -1 : (this.mostSigBits > val.mostSigBits ? 1 : (this.leastSigBits < val.leastSigBits ? -1 : (this.leastSigBits > val.leastSigBits ? 1 : 0)))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy