org.apache.commons.id.uuid.VersionFourGenerator Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.commons.id.uuid;
import org.apache.commons.id.IdentifierGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.Random;
/**
* Class is responsible for generating version 4 UUID's per RFC 4122.
* This class attempts to use a java.security.SecureRandom with
* the following instantiation
* SecureRandom.getInstance("SHA1PRNG", "SUN")
. If neither secure
* random implementation is avialable or an Exception is raised a java.util.Random
* is used.
* Note: Instantiation of SecureRandom is an expensive operation. The
* constructor therefore creates a static member to hold the SecureRandom.
* The first call to getInstance may take time; subsequent calls should return
* quickly.
*
* @author Commons-Id team
* @version $Revision: 480488 $ $Date: 2006-11-29 00:57:26 -0800 (Wed, 29 Nov 2006) $
*
*/
public final class VersionFourGenerator implements IdentifierGenerator, Constants {
/** Random used to generate UUID's */
private static final Random regularRandom = new Random();
/** SecureRandom used to generate UUID's */
private static Random secureRandom;
/** The pseudo-random number generator to use */
private static String usePRNG = "SHA1PRNG";
/** The pseudo-random number generator package name to use */
private static String usePRNGPackage = "SUN";
private static VersionFourGenerator generator;
/**
* Constructs a new VersionFourGenerator.
*/
public VersionFourGenerator() {
super();
}
/**
* Returns a singleton instance of the version four UUID generator.
*
* @return the singleton instance of the version four UUID generator.
*/
public static VersionFourGenerator getInstance() {
if (generator == null) {
generator = new VersionFourGenerator();
}
return generator;
}
/**
* Returns a new version four UUID.
*
* @return Object a new version 4 UUID.
*/
public Object nextIdentifier() {
return nextUUID(false);
}
/**
* Returns a new version four UUID.
* This overloaded method may produce both UUID's using a SecureRandom
as well as using normal
* Random
*
*
* @param secure indicates whether or not to use SecureRandom
in generating the random bits.
* @return a new version four UUID that was generated by either a Random
or SecureRandom
.
*/
public Object nextIdentifier(boolean secure) {
return nextUUID(secure);
}
/**
* Returns a new version four UUID.
*
* @return Object a new version 4 UUID.
*/
public UUID nextUUID() {
//Call nextUUID with secure = false
return nextUUID(false);
}
/**
* Returns a new version four UUID using either SecureRandom
or Random
.
*
* @param secure boolean flag indicating whether to use SecureRandom
or Random
.
* @return a new version four UUID using either SecureRandom
or Random
.
*/
private UUID nextUUID(boolean secure) {
byte[] raw = new byte[UUID_BYTE_LENGTH];
if (secure) {
//Initialize the secure random if null.
if (secureRandom == null) {
try {
if (usePRNGPackage != null) {
secureRandom = SecureRandom.getInstance(usePRNG, usePRNGPackage);
} else {
secureRandom = SecureRandom.getInstance(usePRNG);
}
} catch (NoSuchAlgorithmException nsae) {
secure = false; //Fail back to default PRNG/Random
} catch (NoSuchProviderException nspe) {
secure = false; //Fail back to default PRNG/Random
}
}
if (secureRandom != null) {
secureRandom.nextBytes(raw);
}
} else {
regularRandom.nextBytes(raw);
}
raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F;
raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_FOUR << 4);
raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111
raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000
return new UUID(raw);
}
/**
* Allows clients to set the pseudo-random number generator implementation used when generating a version four uuid with
* the secure option. The secure option uses a SecureRandom
. The packageName string may be null to specify
* no preferred package.
*
* @param prngName the pseudo-random number generator implementation name. For example "SHA1PRNG".
* @param packageName the package name for the PRNG provider. For example "SUN".
*/
public static void setPRNGProvider(String prngName, String packageName) {
VersionFourGenerator.usePRNG = prngName;
VersionFourGenerator.usePRNGPackage = packageName;
VersionFourGenerator.secureRandom = null;
}
}