001: /* JUG Java Uuid Generator
002: *
003: * Copyright (c) 2002- Tatu Saloranta, tatu.saloranta@iki.fi
004: *
005: * Licensed under the License specified in the file LICENSE which is
006: * included with the source code.
007: * You may not use this file except in compliance with the License.
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.drools.util;
017:
018: import java.security.MessageDigest;
019: import java.security.NoSuchAlgorithmException;
020: import java.security.SecureRandom;
021: import java.util.Random;
022:
023: /**
024: * Ripped from JUG
025: *
026: * @see org.safehaus.jug
027: */
028: public final class UUIDGenerator {
029: private final static UUIDGenerator sSingleton = new UUIDGenerator();
030:
031: /**
032: * Random-generator, used by various UUID-generation methods:
033: */
034: private Random mRnd = null;
035:
036: /**
037: * MD5 hasher for name-based digests:
038: */
039: private MessageDigest mHasher = null;
040:
041: /*
042: /////////////////////////////////////////////////////
043: // Life-cycle
044: /////////////////////////////////////////////////////
045: */
046:
047: /**
048: * Constructor is private to enforce singleton access.
049: */
050: private UUIDGenerator() {
051: }
052:
053: /**
054: * Method used for accessing the singleton generator instance.
055: */
056: public static UUIDGenerator getInstance() {
057: return UUIDGenerator.sSingleton;
058: }
059:
060: /*
061: /////////////////////////////////////////////////////
062: // Configuration
063: /////////////////////////////////////////////////////
064: */
065:
066: /**
067: * Method for getting the shared random number generator used for
068: * generating the UUIDs. This way the initialization cost is only
069: * taken once; access need not be synchronized (or in cases where
070: * it has to, SecureRandom takes care of it); it might even be good
071: * for getting really 'random' stuff to get shared access...
072: */
073: public Random getRandomNumberGenerator() {
074: /* Could be synchronized, but since side effects are trivial
075: * (ie. possibility of generating more than one SecureRandom,
076: * of which all but one are dumped) let's not add synchronization
077: * overhead:
078: */
079: if (this .mRnd == null) {
080: this .mRnd = new SecureRandom();
081: }
082: return this .mRnd;
083: }
084:
085: /**
086: * Method that can be called to specify alternative random
087: * number generator to use. This is usually done to use
088: * implementation that is faster than
089: * {@link SecureRandom} that is used by default.
090: *<p>
091: * Note that to avoid first-time initialization penalty
092: * of using {@link SecureRandom}, this method has to be called
093: * before generating the first random-number based UUID.
094: */
095: public void setRandomNumberGenerator(final Random r) {
096: this .mRnd = r;
097: }
098:
099: /* Method for getting the shared message digest (hash) algorithm.
100: * Whether to use the shared one or not depends; using shared instance
101: * adds synchronization overhead (access has to be sync'ed), but
102: * using multiple separate digests wastes memory.
103: */
104: public MessageDigest getHashAlgorithm() {
105: /* Similar to the shared random number generator, it's not necessary
106: * to synchronize initialization. However, use of the hash instance
107: * HAS to be synchronized by the caller to prevent problems with
108: * multiple threads updating digest etc.
109: */
110: if (this .mHasher == null) {
111: try {
112: this .mHasher = MessageDigest.getInstance("MD5");
113: } catch (final NoSuchAlgorithmException nex) {
114: throw new Error(
115: "Couldn't instantiate an MD5 MessageDigest instance: "
116: + nex.toString());
117: }
118: }
119: return this .mHasher;
120: }
121:
122: /*
123: /////////////////////////////////////////////////////
124: // UUID generation methods
125: /////////////////////////////////////////////////////
126: */
127:
128: /**
129: * Method for generating (pseudo-)random based UUIDs, using the
130: * default (shared) SecureRandom object.
131: *
132: * Note that the first time
133: * SecureRandom object is used, there is noticeable delay between
134: * calling the method and getting the reply. This is because SecureRandom
135: * has to initialize itself to reasonably random state. Thus, if you
136: * want to lessen delay, it may be be a good idea to either get the
137: * first random UUID asynchronously from a separate thread, or to
138: * use the other generateRandomBasedUUID passing a previously initialized
139: * SecureRandom instance.
140: *
141: * @return UUID generated using (pseudo-)random based method
142: */
143: public UUID generateRandomBasedUUID() {
144: return generateRandomBasedUUID(getRandomNumberGenerator());
145: }
146:
147: /**
148: * Method for generating (pseudo-)random based UUIDs, using the
149: * specified SecureRandom object. To prevent/avoid delay JDK's
150: * default SecureRandom object causes when first random number
151: * is generated, it may be a good idea to initialize the SecureRandom
152: * instance (on a separate thread for example) when app starts.
153: *
154: * @param randomGenerator Random number generator to use for getting the
155: * random number from which UUID will be composed.
156: *
157: * @return UUID generated using (pseudo-)random based method
158: */
159: public UUID generateRandomBasedUUID(final Random randomGenerator) {
160: final byte[] rnd = new byte[16];
161:
162: randomGenerator.nextBytes(rnd);
163:
164: return new UUID(UUID.TYPE_RANDOM_BASED, rnd);
165: }
166: }
|