001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.security.NoSuchAlgorithmException; 020import java.security.SecureRandom; 021import java.security.Security; 022import java.util.Random; 023import java.util.concurrent.ThreadLocalRandom; 024import java.util.function.Supplier; 025 026import org.apache.commons.lang3.exception.UncheckedException; 027 028/** 029 * Supplements the standard {@link Random} class. 030 * <p> 031 * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an 032 * algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 033 * </p> 034 * <p> 035 * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not 036 * cryptographically secure</b>. 037 * </p> 038 * <p> 039 * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods. 040 * </p> 041 * <p> 042 * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}. 043 * </p> 044 * <p> 045 * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not 046 * cryptographically secure. 047 * </p> 048 * <p> 049 * Please note that the Apache Commons project provides a component dedicated to pseudo-random number generation, namely 050 * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a>, that may be a better choice for 051 * applications with more stringent requirements (performance and/or correctness). 052 * </p> 053 * 054 * @see RandomStringUtils 055 * @since 3.3 056 */ 057public class RandomUtils { 058 059 private static RandomUtils INSECURE = new RandomUtils(ThreadLocalRandom::current); 060 061 private static final Supplier<Random> SECURE_SUPPLIER = () -> RandomUtils.SECURE_RANDOM.get(); 062 063 private static RandomUtils SECURE = new RandomUtils(SECURE_SUPPLIER); 064 065 private static final ThreadLocal<SecureRandom> SECURE_RANDOM = ThreadLocal.withInitial(() -> { 066 try { 067 return SecureRandom.getInstanceStrong(); 068 } catch (final NoSuchAlgorithmException e) { 069 throw new UncheckedException(e); 070 } 071 }); 072 073 /** 074 * Gets the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not cryptographically 075 * secure</b>; use {@link #secure()} to use an algorithms/providers specified in the 076 * {@code securerandom.strongAlgorithms} {@link Security} property. 077 * </p> 078 * <p> 079 * The method {@link ThreadLocalRandom#current()} is called on-demand. 080 * </p> 081 * 082 * @return the singleton instance based on {@link ThreadLocalRandom#current()}. 083 * @see ThreadLocalRandom#current() 084 * @see #secure() 085 * @since 3.16.0 086 */ 087 static RandomUtils insecure() { 088 return INSECURE; 089 } 090 091 /** 092 * Generates a random boolean value. 093 * 094 * @return the random boolean 095 * @since 3.5 096 */ 097 public static boolean nextBoolean() { 098 return secure().randomBoolean(); 099 } 100 101 /** 102 * Generates an array of random bytes. 103 * 104 * @param count the size of the returned array 105 * @return the random byte array 106 * @throws IllegalArgumentException if {@code count} is negative 107 */ 108 public static byte[] nextBytes(final int count) { 109 return secure().randomBytes(count); 110 } 111 112 /** 113 * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive). 114 * 115 * @return the random double 116 * @see #nextDouble(double, double) 117 * @since 3.5 118 */ 119 public static double nextDouble() { 120 return secure().randomDouble(); 121 } 122 123 /** 124 * Generates a random double within the specified range. 125 * 126 * @param startInclusive the smallest value that can be returned, must be non-negative 127 * @param endExclusive the upper bound (not included) 128 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 129 * negative 130 * @return the random double 131 */ 132 public static double nextDouble(final double startInclusive, final double endExclusive) { 133 return secure().randomDouble(startInclusive, endExclusive); 134 } 135 136 /** 137 * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive). 138 * 139 * @return the random float 140 * @see #nextFloat(float, float) 141 * @since 3.5 142 */ 143 public static float nextFloat() { 144 return secure().randomFloat(); 145 } 146 147 /** 148 * Generates a random float within the specified range. 149 * 150 * @param startInclusive the smallest value that can be returned, must be non-negative 151 * @param endExclusive the upper bound (not included) 152 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 153 * negative 154 * @return the random float 155 */ 156 public static float nextFloat(final float startInclusive, final float endExclusive) { 157 return secure().randomFloat(startInclusive, endExclusive); 158 } 159 160 /** 161 * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive). 162 * 163 * @return the random integer 164 * @see #nextInt(int, int) 165 * @since 3.5 166 */ 167 public static int nextInt() { 168 return secure().randomInt(); 169 } 170 171 /** 172 * Generates a random integer within the specified range. 173 * 174 * @param startInclusive the smallest value that can be returned, must be non-negative 175 * @param endExclusive the upper bound (not included) 176 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 177 * negative 178 * @return the random integer 179 */ 180 public static int nextInt(final int startInclusive, final int endExclusive) { 181 return secure().randomInt(startInclusive, endExclusive); 182 } 183 184 /** 185 * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive). 186 * 187 * @return the random long 188 * @see #nextLong(long, long) 189 * @since 3.5 190 */ 191 public static long nextLong() { 192 return secure().randomLong(); 193 } 194 195 /** 196 * Generates a {@code long} value between 0 (inclusive) and the specified value (exclusive). 197 * 198 * @param n Bound on the random number to be returned. Must be positive. 199 * @return a random {@code long} value between 0 (inclusive) and {@code n} (exclusive). 200 */ 201 private static long nextLong(final long n) { 202 return secure().randomLong(n); 203 } 204 205 /** 206 * Generates a random long within the specified range. 207 * 208 * @param startInclusive the smallest value that can be returned, must be non-negative 209 * @param endExclusive the upper bound (not included) 210 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 211 * negative 212 * @return the random long 213 */ 214 public static long nextLong(final long startInclusive, final long endExclusive) { 215 return secure().randomLong(startInclusive, endExclusive); 216 } 217 218 /** 219 * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers 220 * specified in the {@code securerandom.strongAlgorithms} {@link Security} property. 221 * <p> 222 * The method {@link SecureRandom#getInstanceStrong()} is called on-demand. 223 * </p> 224 * 225 * @return the singleton instance based on {@link SecureRandom#getInstanceStrong()}. 226 * @see SecureRandom#getInstanceStrong() 227 * @since 3.16.0 228 */ 229 public static RandomUtils secure() { 230 return SECURE; 231 } 232 233 static SecureRandom secureRandom() { 234 return SECURE_RANDOM.get(); 235 } 236 237 private final Supplier<Random> random; 238 239 /** 240 * {@link RandomUtils} instances should NOT be constructed in standard programming. Instead, the class should be 241 * used as {@code RandomUtils.nextBytes(5);}. 242 * <p> 243 * This constructor is public to permit tools that require a JavaBean instance to operate. 244 * </p> 245 * 246 * @deprecated TODO Make private in 4.0. 247 */ 248 @Deprecated 249 public RandomUtils() { 250 this(SECURE_SUPPLIER); 251 } 252 253 private RandomUtils(final Supplier<Random> random) { 254 this.random = random; 255 } 256 257 Random random() { 258 return random.get(); 259 } 260 261 /** 262 * Generates a random boolean value. 263 * 264 * @return the random boolean 265 * @since 3.16.0 266 */ 267 public boolean randomBoolean() { 268 return random().nextBoolean(); 269 } 270 271 /** 272 * Generates an array of random bytes. 273 * 274 * @param count the size of the returned array 275 * @return the random byte array 276 * @throws IllegalArgumentException if {@code count} is negative 277 * @since 3.16.0 278 */ 279 public byte[] randomBytes(final int count) { 280 Validate.isTrue(count >= 0, "Count cannot be negative."); 281 final byte[] result = new byte[count]; 282 random().nextBytes(result); 283 return result; 284 } 285 286 /** 287 * Generates a random double between 0 (inclusive) and Double.MAX_VALUE (exclusive). 288 * 289 * @return the random double 290 * @see #nextDouble(double, double) 291 * @since 3.16.0 292 */ 293 public double randomDouble() { 294 return nextDouble(0, Double.MAX_VALUE); 295 } 296 297 /** 298 * Generates a random double within the specified range. 299 * 300 * @param startInclusive the smallest value that can be returned, must be non-negative 301 * @param endExclusive the upper bound (not included) 302 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 303 * negative 304 * @return the random double 305 * @since 3.16.0 306 */ 307 public double randomDouble(final double startInclusive, final double endExclusive) { 308 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 309 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 310 if (startInclusive == endExclusive) { 311 return startInclusive; 312 } 313 return startInclusive + (endExclusive - startInclusive) * random().nextDouble(); 314 } 315 316 /** 317 * Generates a random float between 0 (inclusive) and Float.MAX_VALUE (exclusive). 318 * 319 * @return the random float 320 * @see #nextFloat(float, float) 321 * @since 3.16.0 322 */ 323 public float randomFloat() { 324 return nextFloat(0, Float.MAX_VALUE); 325 } 326 327 /** 328 * Generates a random float within the specified range. 329 * 330 * @param startInclusive the smallest value that can be returned, must be non-negative 331 * @param endExclusive the upper bound (not included) 332 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 333 * negative 334 * @return the random float 335 */ 336 public float randomFloat(final float startInclusive, final float endExclusive) { 337 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 338 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 339 if (startInclusive == endExclusive) { 340 return startInclusive; 341 } 342 return startInclusive + (endExclusive - startInclusive) * random().nextFloat(); 343 } 344 345 /** 346 * Generates a random int between 0 (inclusive) and Integer.MAX_VALUE (exclusive). 347 * 348 * @return the random integer 349 * @see #nextInt(int, int) 350 * @since 3.16.0 351 */ 352 public int randomInt() { 353 return nextInt(0, Integer.MAX_VALUE); 354 } 355 356 /** 357 * Generates a random integer within the specified range. 358 * 359 * @param startInclusive the smallest value that can be returned, must be non-negative 360 * @param endExclusive the upper bound (not included) 361 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 362 * negative 363 * @return the random integer 364 * @since 3.16.0 365 */ 366 public int randomInt(final int startInclusive, final int endExclusive) { 367 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 368 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 369 if (startInclusive == endExclusive) { 370 return startInclusive; 371 } 372 return startInclusive + random().nextInt(endExclusive - startInclusive); 373 } 374 375 /** 376 * Generates a random long between 0 (inclusive) and Long.MAX_VALUE (exclusive). 377 * 378 * @return the random long 379 * @see #nextLong(long, long) 380 * @since 3.16.0 381 */ 382 public long randomLong() { 383 return nextLong(Long.MAX_VALUE); 384 } 385 386 /** 387 * Generates a {@code long} value between 0 (inclusive) and the specified value (exclusive). 388 * 389 * @param n Bound on the random number to be returned. Must be positive. 390 * @return a random {@code long} value between 0 (inclusive) and {@code n} (exclusive). 391 */ 392 private long randomLong(final long n) { 393 // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long) 394 long bits; 395 long val; 396 do { 397 bits = random().nextLong() >>> 1; 398 val = bits % n; 399 } while (bits - val + n - 1 < 0); 400 return val; 401 } 402 403 /** 404 * Generates a random long within the specified range. 405 * 406 * @param startInclusive the smallest value that can be returned, must be non-negative 407 * @param endExclusive the upper bound (not included) 408 * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is 409 * negative 410 * @return the random long 411 * @since 3.16.0 412 */ 413 public long randomLong(final long startInclusive, final long endExclusive) { 414 Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value."); 415 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 416 if (startInclusive == endExclusive) { 417 return startInclusive; 418 } 419 return startInclusive + nextLong(endExclusive - startInclusive); 420 } 421 422 @Override 423 public String toString() { 424 return "RandomUtils [random=" + random() + "]"; 425 } 426 427}