UUID.java 9.09 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.util;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;

public class UUID
implements Serializable {
    private final byte[] bytes;
    private int hashCode;
    private final int version;
    public static final char[] hexDigits = "0123456789abcdef".toCharArray();
    private static byte[] internetAddress = null;
    private static File uuidFile = null;
    private static final int UUIDsPerTick = 128;
    private static long lastTime = new Date().getTime();
    private static final long gregorianOffset = - new GregorianCalendar(1582, 9, 15).getTime().getTime();
    private static int uuidsThisTick = 128;
    private static short prevClock = 0;
    private static long prevTime = 0;
    private static byte[] prevNode = null;
    private static long nextSave = new Date().getTime();
    private static Random randomGenerator = new Random(new Date().getTime());

    public UUID(String string) {
        if (string.length() > 36) {
            string = string.substring(0, 36);
        }
        this.bytes = new byte[16];
        int j = 0;
        for (int i = 0; i < 36; i += 2) {
            this.bytes[j++] = (byte)Integer.parseInt(string.substring(i, i + 2), 16);
            if (i != 6 && i != 11 && i != 16 && i != 21) continue;
            ++i;
        }
        this.version = this.bytes[7] >> 4 & 15;
    }

    public UUID(byte[] bytes) {
        this.bytes = new byte[16];
        System.arraycopy(bytes, 0, this.bytes, 0, Math.min(16, bytes.length));
        this.version = bytes[7] >> 4 & 15;
    }

    public UUID(long[] longs) {
        int i;
        long hi = longs[0];
        long lo = longs[1];
        this.bytes = new byte[16];
        for (i = 7; i >= 0; --i) {
            this.bytes[i] = (byte)(hi & 255);
            hi >>= 8;
        }
        for (i = 7; i >= 0; --i) {
            this.bytes[8 + i] = (byte)(lo & 255);
            lo >>= 8;
        }
        this.version = this.bytes[7] >> 4 & 15;
    }

    public UUID(String name, String namespace) {
        this.version = 3;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(namespace.getBytes());
            md5.update(name.getBytes());
            this.bytes = md5.digest();
            this.bytes[7] = (byte)(this.bytes[7] & 15 | (byte)(this.version << 4));
            this.bytes[8] = (byte)(this.bytes[8] & 63 | 128);
            return;
        }
        catch (Exception exc) {
            throw new InternalError("MD5 not available");
        }
    }

    public UUID() {
        this.version = 4;
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            DataOutputStream out = new DataOutputStream(byteOut);
            out.writeLong(System.currentTimeMillis());
            out.writeInt(Thread.currentThread().hashCode());
            out.write(internetAddress);
            out.writeInt(UUID.random());
            out.flush();
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(byteOut.toByteArray());
            this.bytes = md5.digest();
            this.bytes[7] = (byte)(this.bytes[7] & 15 | (byte)(this.version << 4));
            this.bytes[8] = (byte)(this.bytes[8] & 63 | 128);
            return;
        }
        catch (Exception exc) {
            throw new InternalError("MD5 not available");
        }
    }

    public UUID(byte[] node, long time, short clock) {
        int i;
        this.version = 1;
        this.bytes = new byte[16];
        long t = time;
        for (i = 0; i < 8; ++i) {
            this.bytes[i] = (byte)(t & 255);
            t >>= 8;
        }
        byte[] arrby = this.bytes;
        arrby[7] = (byte)(arrby[7] | (byte)(this.version << 4));
        this.bytes[8] = (byte)(clock >> 8 & 63 | 128);
        this.bytes[9] = (byte)(clock & 255);
        for (i = 0; i < 6; ++i) {
            this.bytes[10 + i] = node[i];
        }
    }

    public int getVersion() {
        return this.version;
    }

    public boolean equals(Object toUUID) {
        if (this == toUUID) {
            return true;
        }
        if (toUUID instanceof UUID) {
            UUID uuid = (UUID)toUUID;
            if (this.bytes == uuid.bytes) {
                return true;
            }
            for (int i = 0; i < 16; ++i) {
                if (this.bytes[i] == uuid.bytes[i]) continue;
                return false;
            }
            return true;
        }
        return false;
    }

    public String toString() {
        char[] chars = new char[36];
        int j = 0;
        for (int i = 0; i < 16; ++i) {
            chars[j++] = hexDigits[this.bytes[i] >> 4 & 15];
            chars[j++] = hexDigits[this.bytes[i] & 15];
            if (i != 3 && i != 5 && i != 7 && i != 9) continue;
            chars[j++] = 45;
        }
        return new String(chars);
    }

    public byte[] getBytes() {
        return this.bytes;
    }

    public int hashCode() {
        int h = this.hashCode;
        if (h == 0) {
            for (int i = 0; i < this.bytes.length; ++i) {
                h = 31 * h + this.bytes[i];
            }
            this.hashCode = h;
        }
        return this.hashCode;
    }

    public static void init(File uuidStateFile) {
        try {
            internetAddress = InetAddress.getLocalHost().getAddress();
        }
        catch (Exception exc) {
            throw new InternalError("Unable to get host address: " + exc);
        }
        uuidFile = uuidStateFile;
        UUID.loadState();
    }

    public static synchronized UUID create() {
        long time = UUID.getCurrentTime();
        short clock = prevClock;
        byte[] node = prevNode;
        if (prevTime > time) {
            clock = (short)(clock + 1);
        }
        UUID uuid = new UUID(node, time, clock);
        UUID.saveState(time, clock, node);
        return uuid;
    }

    private static byte[] computeNodeAddress() {
        MessageDigest md5;
        byte[] address = new byte[6];
        int thread = Thread.currentThread().hashCode();
        long time = System.currentTimeMillis();
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(byteOut);
        try {
            if (internetAddress != null) {
                out.write(internetAddress);
            }
            out.write(thread);
            out.writeLong(time);
            out.close();
        }
        catch (IOException exc) {
            // empty catch block
        }
        byte[] rand = byteOut.toByteArray();
        try {
            md5 = MessageDigest.getInstance("MD5");
        }
        catch (Exception exc) {
            throw new InternalError(exc.toString());
        }
        md5.update(rand);
        byte[] temp = md5.digest();
        for (int i = 0; i < 6; ++i) {
            address[i] = temp[i + 5];
        }
        address[0] = (byte)(address[0] | -128);
        return address;
    }

    private static synchronized long getCurrentTime() {
        long now = 0;
        boolean waitForTick = true;
        while (waitForTick) {
            now = (new Date().getTime() + gregorianOffset) * 10;
            if (lastTime < now) {
                uuidsThisTick = 0;
                waitForTick = false;
                continue;
            }
            if (uuidsThisTick >= 128) continue;
            ++uuidsThisTick;
            waitForTick = false;
        }
        lastTime = now += (long)uuidsThisTick;
        return now;
    }

    private static byte[] getIEEEAddress() {
        byte[] address = new byte[6];
        return address;
    }

    private static int random() {
        return randomGenerator.nextInt();
    }

    private static void loadState() {
        try {
            ObjectInputStream s = new ObjectInputStream(new FileInputStream(uuidFile));
            prevTime = s.readLong();
            prevClock = s.readShort();
            prevNode = new byte[6];
            s.readFully(prevNode);
            s.close();
        }
        catch (Exception exc) {
            prevNode = UUID.computeNodeAddress();
            prevTime = 0;
            prevClock = (short)UUID.random();
        }
    }

    private static void saveState(long time, short clock, byte[] node) {
        prevTime = time;
        prevClock = clock;
        prevNode = node;
        if (prevTime > nextSave) {
            try {
                ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream(uuidFile));
                s.writeLong(prevTime);
                s.writeShort(prevClock);
                s.write(prevNode);
                s.close();
                nextSave = prevTime + 100000;
            }
            catch (Exception exc) {
                // empty catch block
            }
        }
    }
}