FileDocCategorySizeDatePackage
SimpleUUIDGen.javaAPI DocApache Axis 1.48211Sat Apr 22 18:57:28 BST 2006org.apache.axis.components.uuid

SimpleUUIDGen

public class SimpleUUIDGen extends Object implements UUIDGen
Used to create new universally unique identifiers or UUID's (sometimes called GUID's). UDDI UUID's are allways formmated according to DCE UUID conventions.
author
Maarten Coene
author
Steve Viens
version
0.3.2 3/25/2001
since
JDK1.2.2

Fields Summary
private static final BigInteger
countStart
private static final int
clock_sequence
private static final byte
ZERO
private static final byte
ONE
private static Random
secureRandom
Constructors Summary
Methods Summary
private static final java.lang.StringleftZeroPadString(java.lang.String bitString, int len)
utility method which returns a bitString with left zero padding for as many places as necessary to reach len; otherwise returns bitString unaltered.

return
a left zero padded string of at least len chars
param
bitString a String to pad
param
len the length under which bitString needs padding


     
        // problem: the node should be the IEEE 802 ethernet address, but can not
        // be retrieved in Java yet.
        // see bug ID 4173528
        // workaround (also suggested in bug ID 4173528)
        // If a system wants to generate UUIDs but has no IEE 802 compliant
        // network card or other source of IEEE 802 addresses, then this section
        // describes how to generate one.
        // The ideal solution is to obtain a 47 bit cryptographic quality random
        // number, and use it as the low 47 bits of the node ID, with the most
        // significant bit of the first octet of the node ID set to 1. This bit
        // is the unicast/multicast bit, which will never be set in IEEE 802
        // addresses obtained from network cards; hence, there can never be a
        // conflict between UUIDs generated by machines with and without network
        // cards.
        try {
            secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
        } catch (Exception e) {
            secureRandom = new Random();
        }
    
        if (bitString.length() < len) {
            int nbExtraZeros = len - bitString.length();
            StringBuffer extraZeros = new StringBuffer();
            for (int i = 0; i < nbExtraZeros; i++) {
                extraZeros.append("0");
            }
            extraZeros.append(bitString);
            bitString = extraZeros.toString();
        }
        return bitString;
    
public java.lang.StringnextUUID()
Creates a new UUID. The algorithm used is described by The Open Group. See Universal Unique Identifier for more details.

Due to a lack of functionality in Java, a part of the UUID is a secure random. This results in a long processing time when this method is called for the first time.

        // TODO: this method has to be checked for it's correctness. I'm not sure the standard is
        // implemented correctly.

        // the count of 100-nanosecond intervals since 00:00:00.00 15 October 1582
        BigInteger count;

        // the number of milliseconds since 1 January 1970
        BigInteger current = BigInteger.valueOf(System.currentTimeMillis());

        // the number of milliseconds since 15 October 1582
        BigInteger countMillis = current.subtract(countStart);

        // the result
        count = countMillis.multiply(BigInteger.valueOf(10000));
        byte[] bits = leftZeroPadString(count.toString(2), 60).getBytes();

        // the time_low field
        byte[] time_low = new byte[32];
        for (int i = 0; i < 32; i++)
            time_low[i] = bits[bits.length - i - 1];

        // the time_mid field
        byte[] time_mid = new byte[16];
        for (int i = 0; i < 16; i++)
            time_mid[i] = bits[bits.length - 32 - i - 1];

        // the time_hi_and_version field
        byte[] time_hi_and_version = new byte[16];
        for (int i = 0; i < 12; i++)
            time_hi_and_version[i] = bits[bits.length - 48 - i - 1];

        time_hi_and_version[12] = ONE;
        time_hi_and_version[13] = ZERO;
        time_hi_and_version[14] = ZERO;
        time_hi_and_version[15] = ZERO;

        // the clock_seq_low field
        BigInteger clockSequence = BigInteger.valueOf(clock_sequence);
        byte[] clock_bits = leftZeroPadString(clockSequence.toString(2), 14).getBytes();
        byte[] clock_seq_low = new byte[8];
        for (int i = 0; i < 8; i++) {
            clock_seq_low[i] = clock_bits[clock_bits.length - i - 1];
        }

        // the clock_seq_hi_and_reserved
        byte[] clock_seq_hi_and_reserved = new byte[8];
        for (int i = 0; i < 6; i++)
            clock_seq_hi_and_reserved[i] = clock_bits[clock_bits.length - 8 - i - 1];

        clock_seq_hi_and_reserved[6] = ZERO;
        clock_seq_hi_and_reserved[7] = ONE;

        String timeLow = Long.toHexString((new BigInteger(new String(reverseArray(time_low)), 2)).longValue());
        timeLow = leftZeroPadString(timeLow, 8);

        String timeMid = Long.toHexString((new BigInteger(new String(reverseArray(time_mid)), 2)).longValue());
        timeMid = leftZeroPadString(timeMid, 4);

        String timeHiAndVersion = Long.toHexString((new BigInteger(new String(reverseArray(time_hi_and_version)), 2)).longValue());
        timeHiAndVersion = leftZeroPadString(timeHiAndVersion, 4);

        String clockSeqHiAndReserved = Long.toHexString((new BigInteger(new String(reverseArray(clock_seq_hi_and_reserved)), 2)).longValue());
        clockSeqHiAndReserved = leftZeroPadString(clockSeqHiAndReserved, 2);

        String clockSeqLow = Long.toHexString((new BigInteger(new String(reverseArray(clock_seq_low)), 2)).longValue());
        clockSeqLow = leftZeroPadString(clockSeqLow, 2);

        long nodeValue = secureRandom.nextLong();
        nodeValue = Math.abs(nodeValue);
        while (nodeValue > 140737488355328L) {
            nodeValue = secureRandom.nextLong();
            nodeValue = Math.abs(nodeValue);
        }

        BigInteger nodeInt = BigInteger.valueOf(nodeValue);

        byte[] node_bits = leftZeroPadString(nodeInt.toString(2), 47).getBytes();
        byte[] node = new byte[48];
        for (int i = 0; i < 47; i++)
            node[i] = node_bits[node_bits.length - i - 1];

        node[47] = ONE;
        String theNode = Long.toHexString((new BigInteger(new String(reverseArray(node)), 2)).longValue());
        theNode = leftZeroPadString(theNode, 12);

        StringBuffer result = new StringBuffer(timeLow);
        result.append("-");
        result.append(timeMid);
        result.append("-");
        result.append(timeHiAndVersion);
        result.append("-");
        result.append(clockSeqHiAndReserved);
        result.append(clockSeqLow);
        result.append("-");
        result.append(theNode);
        return result.toString().toUpperCase();
    
private static byte[]reverseArray(byte[] bits)

        byte[] result = new byte[bits.length];
        for (int i = 0; i < result.length; i++)
            result[i] = bits[result.length - 1 - i];

        return result;