RandomBasedGenerator.java

package com.fasterxml.uuid.impl;

import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;

import com.fasterxml.uuid.NoArgGenerator;
import com.fasterxml.uuid.UUIDType;

/**
 * Implementation of UUID generator that uses generation method 4.
 *<p>
 * Note on random number generation when using {@link SecureRandom} for random number
 * generation: the first time {@link SecureRandom} object is used, there is noticeable delay between
 * calling the method and getting the reply. This is because SecureRandom
 * has to initialize itself to reasonably random state. Thus, if you
 * want to lessen delay, it may be be a good idea to either get the
 * first random UUID asynchronously from a separate thread, or to
 * use the other generateRandomBasedUUID passing a previously initialized
 * SecureRandom instance.
 *
 * @since 3.0
 */
public class RandomBasedGenerator extends NoArgGenerator
{
    /**
     * Random number generator that this generator uses.
     */
    protected final Random _random;

    /**
     * Looks like {@link SecureRandom} implementation is more efficient
     * using single call access (compared to basic {@link java.util.Random}),
     * so let's use that knowledge to our benefit.
     */
    protected final boolean _secureRandom;

    /**
     * @param rnd Random number generator to use for generating UUIDs; if null,
     *   shared default generator is used. Note that it is strongly recommend to
     *   use a <b>good</b> (pseudo) random number generator; for example, JDK's
     *   {@link SecureRandom}.
     */
    public RandomBasedGenerator(Random rnd)
    {
        if (rnd == null) {
            rnd = LazyRandom.sharedSecureRandom();
        }
        _secureRandom = (rnd instanceof SecureRandom);
        _random = rnd;
    }

    /*
    /**********************************************************************
    /* Access to config
    /**********************************************************************
     */

    @Override
    public UUIDType getType() { return UUIDType.RANDOM_BASED; }

    /*
    /**********************************************************************
    /* UUID generation
    /**********************************************************************
     */
    
    @Override
    public UUID generate()
    {
        // 14-Oct-2010, tatu: Surprisingly, variant for reading byte array is
        //   tad faster for SecureRandom... so let's use that then

        long r1, r2;

        if (_secureRandom) {
            final byte[] buffer = new byte[16];
            _random.nextBytes(buffer);
            r1 = _toLong(buffer, 0);
            r2 = _toLong(buffer, 1);
        } else {
            r1 = _random.nextLong();
            r2 = _random.nextLong();
        }
        return UUIDUtil.constructUUID(UUIDType.RANDOM_BASED, r1, r2);
    }
}