    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}