Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
VersionFourGenerator |
|
| 2.0;2 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | package org.apache.commons.id.uuid; | |
18 | ||
19 | import org.apache.commons.id.IdentifierGenerator; | |
20 | ||
21 | import java.security.NoSuchAlgorithmException; | |
22 | import java.security.NoSuchProviderException; | |
23 | import java.security.SecureRandom; | |
24 | import java.util.Random; | |
25 | ||
26 | /** | |
27 | * <p>Class is responsible for generating version 4 UUID's per RFC 4122. | |
28 | * This class attempts to use a java.security.SecureRandom with | |
29 | * the following instantiation | |
30 | * <code>SecureRandom.getInstance("SHA1PRNG", "SUN")</code>. If neither secure | |
31 | * random implementation is avialable or an Exception is raised a java.util.Random | |
32 | * is used.</p> | |
33 | * <p>Note: Instantiation of SecureRandom is an expensive operation. The | |
34 | * constructor therefore creates a static member to hold the SecureRandom. | |
35 | * The first call to getInstance may take time; subsequent calls should return | |
36 | * quickly.</p> | |
37 | * | |
38 | * @author Commons-Id team | |
39 | * @version $Revision: 480488 $ $Date: 2006-11-29 08:57:26 +0000 (Wed, 29 Nov 2006) $ | |
40 | * | |
41 | */ | |
42 | public final class VersionFourGenerator implements IdentifierGenerator, Constants { | |
43 | ||
44 | /** Random used to generate UUID's */ | |
45 | 1 | private static final Random regularRandom = new Random(); |
46 | ||
47 | /** SecureRandom used to generate UUID's */ | |
48 | private static Random secureRandom; | |
49 | ||
50 | /** The pseudo-random number generator to use */ | |
51 | 1 | private static String usePRNG = "SHA1PRNG"; |
52 | ||
53 | /** The pseudo-random number generator package name to use */ | |
54 | 1 | private static String usePRNGPackage = "SUN"; |
55 | ||
56 | private static VersionFourGenerator generator; | |
57 | ||
58 | /** | |
59 | * <p>Constructs a new VersionFourGenerator.</p> | |
60 | */ | |
61 | public VersionFourGenerator() { | |
62 | 3 | super(); |
63 | 3 | } |
64 | ||
65 | /** | |
66 | * <p>Returns a singleton instance of the version four UUID generator.</p> | |
67 | * | |
68 | * @return the singleton instance of the version four UUID generator. | |
69 | */ | |
70 | public static VersionFourGenerator getInstance() { | |
71 | 1 | if (generator == null) { |
72 | 1 | generator = new VersionFourGenerator(); |
73 | } | |
74 | 1 | return generator; |
75 | } | |
76 | ||
77 | /** | |
78 | * <p>Returns a new version four UUID.</p> | |
79 | * | |
80 | * @return Object a new version 4 UUID. | |
81 | */ | |
82 | public Object nextIdentifier() { | |
83 | 5 | return nextUUID(false); |
84 | } | |
85 | ||
86 | /** | |
87 | * <p>Returns a new version four UUID.</p> | |
88 | * <p>This overloaded method may produce both UUID's using a <code>SecureRandom</code> as well as using normal | |
89 | * <code>Random</code> | |
90 | * </p> | |
91 | * | |
92 | * @param secure indicates whether or not to use <code>SecureRandom</code> in generating the random bits. | |
93 | * @return a new version four UUID that was generated by either a <code>Random</code> or <code>SecureRandom</code>. | |
94 | */ | |
95 | public Object nextIdentifier(boolean secure) { | |
96 | 5 | return nextUUID(secure); |
97 | } | |
98 | ||
99 | /** | |
100 | * <p>Returns a new version four UUID.</p> | |
101 | * | |
102 | * @return Object a new version 4 UUID. | |
103 | */ | |
104 | public UUID nextUUID() { | |
105 | //Call nextUUID with secure = false | |
106 | 1 | return nextUUID(false); |
107 | } | |
108 | ||
109 | /** | |
110 | * <p>Returns a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>.</p> | |
111 | * | |
112 | * @param secure boolean flag indicating whether to use <code>SecureRandom</code> or <code>Random</code>. | |
113 | * @return a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>. | |
114 | */ | |
115 | private UUID nextUUID(boolean secure) { | |
116 | 11 | byte[] raw = new byte[UUID_BYTE_LENGTH]; |
117 | 11 | if (secure) { |
118 | //Initialize the secure random if null. | |
119 | 5 | if (secureRandom == null) { |
120 | try { | |
121 | 1 | if (usePRNGPackage != null) { |
122 | 1 | secureRandom = SecureRandom.getInstance(usePRNG, usePRNGPackage); |
123 | 1 | } else { |
124 | 0 | secureRandom = SecureRandom.getInstance(usePRNG); |
125 | } | |
126 | 0 | } catch (NoSuchAlgorithmException nsae) { |
127 | 0 | secure = false; //Fail back to default PRNG/Random |
128 | 0 | } catch (NoSuchProviderException nspe) { |
129 | 0 | secure = false; //Fail back to default PRNG/Random |
130 | 1 | } |
131 | } | |
132 | 5 | if (secureRandom != null) { |
133 | 5 | secureRandom.nextBytes(raw); |
134 | 5 | } |
135 | } else { | |
136 | 6 | regularRandom.nextBytes(raw); |
137 | } | |
138 | ||
139 | 11 | raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F; |
140 | 11 | raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_FOUR << 4); |
141 | ||
142 | 11 | raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111 |
143 | 11 | raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000 |
144 | ||
145 | 11 | return new UUID(raw); |
146 | } | |
147 | ||
148 | /** | |
149 | * <p>Allows clients to set the pseudo-random number generator implementation used when generating a version four uuid with | |
150 | * the secure option. The secure option uses a <code>SecureRandom</code>. The packageName string may be null to specify | |
151 | * no preferred package.</p> | |
152 | * | |
153 | * @param prngName the pseudo-random number generator implementation name. For example "SHA1PRNG". | |
154 | * @param packageName the package name for the PRNG provider. For example "SUN". | |
155 | */ | |
156 | public static void setPRNGProvider(String prngName, String packageName) { | |
157 | 0 | VersionFourGenerator.usePRNG = prngName; |
158 | 0 | VersionFourGenerator.usePRNGPackage = packageName; |
159 | 0 | VersionFourGenerator.secureRandom = null; |
160 | 0 | } |
161 | } |