    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.util.Random;
    020import java.util.concurrent.ThreadLocalRandom;
    021
    022/**
    023 * Generates random {@link String}s.
    024 *
    025 * <p><b>Caveat: Instances of {@link Random}, upon which the implementation of this
    026 * class relies, are not cryptographically secure.</b></p>
    027 *
    028 * <p>RandomStringUtils is intended for simple use cases. For more advanced
    029 * use cases consider using Apache Commons Text's
    030 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html">
    031 * RandomStringGenerator</a> instead.</p>
    032 *
    033 * <p>The Apache Commons project provides
    034 * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a> dedicated to pseudo-random number generation, that may be
    035 * a better choice for applications with more stringent requirements
    036 * (performance and/or correctness).</p>
    037 *
    038 * <p>Note that <em>private high surrogate</em> characters are ignored.
    039 * These are Unicode characters that fall between the values 56192 (db80)
    040 * and 56319 (dbff) as we don't know how to handle them.
    041 * High and low surrogates are correctly dealt with - that is if a
    042 * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
    043 * then it is followed by a low surrogate. If a low surrogate is chosen,
    044 * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
    045 * chosen high surrogate.</p>
    046 *
    047 * <p>#ThreadSafe#</p>
    048 * @since 1.0
    049 */
    050public class RandomStringUtils {
    051
    052    private static ThreadLocalRandom random() {
    053        return ThreadLocalRandom.current();
    054    }
    055
    056    // Random
    057    /**
    058     * Creates a random string whose length is the number of characters
    059     * specified.
    060     *
    061     * <p>Characters will be chosen from the set of all characters.</p>
    062     *
    063     * @param count  the length of random string to create
    064     * @return the random string
    065     * @throws IllegalArgumentException if {@code count} &lt; 0.
    066     */
    067    public static String random(final int count) {
    068        return random(count, false, false);
    069    }
    070
    071    /**
    072     * Creates a random string whose length is the number of characters
    073     * specified.
    074     *
    075     * <p>Characters will be chosen from the set of alpha-numeric
    076     * characters as indicated by the arguments.</p>
    077     *
    078     * @param count  the length of random string to create
    079     * @param letters  if {@code true}, generated string may include
    080     *  alphabetic characters
    081     * @param numbers  if {@code true}, generated string may include
    082     *  numeric characters
    083     * @return the random string
    084     * @throws IllegalArgumentException if {@code count} &lt; 0.
    085     */
    086    public static String random(final int count, final boolean letters, final boolean numbers) {
    087        return random(count, 0, 0, letters, numbers);
    088    }
    089
    090    /**
    091     * Creates a random string whose length is the number of characters
    092     * specified.
    093     *
    094     * <p>Characters will be chosen from the set of characters specified.</p>
    095     *
    096     * @param count  the length of random string to create
    097     * @param chars  the character array containing the set of characters to use,
    098     *  may be null
    099     * @return the random string
    100     * @throws IllegalArgumentException if {@code count} &lt; 0.
    101     */
    102    public static String random(final int count, final char... chars) {
    103        if (chars == null) {
    104            return random(count, 0, 0, false, false, null, random());
    105        }
    106        return random(count, 0, chars.length, false, false, chars, random());
    107    }
    108
    109    /**
    110     * Creates a random string whose length is the number of characters
    111     * specified.
    112     *
    113     * <p>Characters will be chosen from the set of alpha-numeric
    114     * characters as indicated by the arguments.</p>
    115     *
    116     * @param count  the length of random string to create
    117     * @param start  the position in set of chars to start at
    118     * @param end  the position in set of chars to end before
    119     * @param letters  if {@code true}, generated string may include
    120     *  alphabetic characters
    121     * @param numbers  if {@code true}, generated string may include
    122     *  numeric characters
    123     * @return the random string
    124     * @throws IllegalArgumentException if {@code count} &lt; 0.
    125     */
    126    public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
    127        return random(count, start, end, letters, numbers, null, random());
    128    }
    129
    130    /**
    131     * Creates a random string based on a variety of options, using
    132     * default source of randomness.
    133     *
    134     * <p>This method has exactly the same semantics as
    135     * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
    136     * instead of using an externally supplied source of randomness, it uses
    137     * the internal static {@link Random} instance.</p>
    138     *
    139     * @param count  the length of random string to create
    140     * @param start  the position in set of chars to start at
    141     * @param end  the position in set of chars to end before
    142     * @param letters  if {@code true}, generated string may include
    143     *  alphabetic characters
    144     * @param numbers  if {@code true}, generated string may include
    145     *  numeric characters
    146     * @param chars  the set of chars to choose randoms from.
    147     *  If {@code null}, then it will use the set of all chars.
    148     * @return the random string
    149     * @throws ArrayIndexOutOfBoundsException if there are not
    150     *  {@code (end - start) + 1} characters in the set array.
    151     * @throws IllegalArgumentException if {@code count} &lt; 0.
    152     */
    153    public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers, final char... chars) {
    154        return random(count, start, end, letters, numbers, chars, random());
    155    }
    156
    157    /**
    158     * Creates a random string based on a variety of options, using
    159     * supplied source of randomness.
    160     *
    161     * <p>If start and end are both {@code 0}, start and end are set
    162     * to {@code ' '} and {@code 'z'}, the ASCII printable
    163     * characters, will be used, unless letters and numbers are both
    164     * {@code false}, in which case, start and end are set to
    165     * {@code 0} and {@link Character#MAX_CODE_POINT}.
    166     *
    167     * <p>If set is not {@code null}, characters between start and
    168     * end are chosen.</p>
    169     *
    170     * <p>This method accepts a user-supplied {@link Random}
    171     * instance to use as a source of randomness. By seeding a single
    172     * {@link Random} instance with a fixed seed and using it for each call,
    173     * the same random sequence of strings can be generated repeatedly
    174     * and predictably.</p>
    175     *
    176     * @param count  the length of random string to create
    177     * @param start  the position in set of chars to start at (inclusive)
    178     * @param end  the position in set of chars to end before (exclusive)
    179     * @param letters  if {@code true}, generated string may include
    180     *  alphabetic characters
    181     * @param numbers  if {@code true}, generated string may include
    182     *  numeric characters
    183     * @param chars  the set of chars to choose randoms from, must not be empty.
    184     *  If {@code null}, then it will use the set of all chars.
    185     * @param random  a source of randomness.
    186     * @return the random string
    187     * @throws ArrayIndexOutOfBoundsException if there are not
    188     *  {@code (end - start) + 1} characters in the set array.
    189     * @throws IllegalArgumentException if {@code count} &lt; 0 or the provided chars array is empty.
    190     * @since 2.0
    191     */
    192    public static String random(int count, int start, int end, final boolean letters, final boolean numbers,
    193                                final char[] chars, final Random random) {
    194        if (count == 0) {
    195            return StringUtils.EMPTY;
    196        }
    197        if (count < 0) {
    198            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
    199        }
    200        if (chars != null && chars.length == 0) {
    201            throw new IllegalArgumentException("The chars array must not be empty");
    202        }
    203
    204        if (start == 0 && end == 0) {
    205            if (chars != null) {
    206                end = chars.length;
    207            } else if (!letters && !numbers) {
    208                end = Character.MAX_CODE_POINT;
    209            } else {
    210                end = 'z' + 1;
    211                start = ' ';
    212            }
    213        } else if (end <= start) {
    214            throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")");
    215        }
    216
    217        final int zeroDigitAscii = 48;
    218        final int firstLetterAscii = 65;
    219
    220        if (chars == null && (numbers && end <= zeroDigitAscii
    221                || letters && end <= firstLetterAscii)) {
    222            throw new IllegalArgumentException("Parameter end (" + end + ") must be greater then (" + zeroDigitAscii + ") for generating digits " +
    223                    "or greater then (" + firstLetterAscii + ") for generating letters.");
    224        }
    225
    226        final StringBuilder builder = new StringBuilder(count);
    227        final int gap = end - start;
    228
    229        while (count-- != 0) {
    230            final int codePoint;
    231            if (chars == null) {
    232                codePoint = random.nextInt(gap) + start;
    233
    234                switch (Character.getType(codePoint)) {
    235                case Character.UNASSIGNED:
    236                case Character.PRIVATE_USE:
    237                case Character.SURROGATE:
    238                    count++;
    239                    continue;
    240                }
    241
    242            } else {
    243                codePoint = chars[random.nextInt(gap) + start];
    244            }
    245
    246            final int numberOfChars = Character.charCount(codePoint);
    247            if (count == 0 && numberOfChars > 1) {
    248                count++;
    249                continue;
    250            }
    251
    252            if (letters && Character.isLetter(codePoint)
    253                    || numbers && Character.isDigit(codePoint)
    254                    || !letters && !numbers) {
    255                builder.appendCodePoint(codePoint);
    256
    257                if (numberOfChars == 2) {
    258                    count--;
    259                }
    260
    261            } else {
    262                count++;
    263            }
    264        }
    265        return builder.toString();
    266    }
    267
    268    /**
    269     * Creates a random string whose length is the number of characters
    270     * specified.
    271     *
    272     * <p>Characters will be chosen from the set of characters
    273     * specified by the string, must not be empty.
    274     * If null, the set of all characters is used.</p>
    275     *
    276     * @param count  the length of random string to create
    277     * @param chars  the String containing the set of characters to use,
    278     *  may be null, but must not be empty
    279     * @return the random string
    280     * @throws IllegalArgumentException if {@code count} &lt; 0 or the string is empty.
    281     */
    282    public static String random(final int count, final String chars) {
    283        if (chars == null) {
    284            return random(count, 0, 0, false, false, null, random());
    285        }
    286        return random(count, chars.toCharArray());
    287    }
    288
    289    /**
    290     * Creates a random string whose length is the number of characters
    291     * specified.
    292     *
    293     * <p>Characters will be chosen from the set of Latin alphabetic
    294     * characters (a-z, A-Z).</p>
    295     *
    296     * @param count  the length of random string to create
    297     * @return the random string
    298     * @throws IllegalArgumentException if {@code count} &lt; 0.
    299     */
    300    public static String randomAlphabetic(final int count) {
    301        return random(count, true, false);
    302    }
    303
    304    /**
    305     * Creates a random string whose length is between the inclusive minimum and
    306     * the exclusive maximum.
    307     *
    308     * <p>Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).</p>
    309     *
    310     * @param minLengthInclusive the inclusive minimum length of the string to generate
    311     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    312     * @return the random string
    313     * @since 3.5
    314     */
    315    public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
    316        return randomAlphabetic(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    317    }
    318
    319    /**
    320     * Creates a random string whose length is the number of characters
    321     * specified.
    322     *
    323     * <p>Characters will be chosen from the set of Latin alphabetic
    324     * characters (a-z, A-Z) and the digits 0-9.</p>
    325     *
    326     * @param count  the length of random string to create
    327     * @return the random string
    328     * @throws IllegalArgumentException if {@code count} &lt; 0.
    329     */
    330    public static String randomAlphanumeric(final int count) {
    331        return random(count, true, true);
    332    }
    333
    334    /**
    335     * Creates a random string whose length is between the inclusive minimum and
    336     * the exclusive maximum.
    337     *
    338     * <p>Characters will be chosen from the set of Latin alphabetic
    339     * characters (a-z, A-Z) and the digits 0-9.</p>
    340     *
    341     * @param minLengthInclusive the inclusive minimum length of the string to generate
    342     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    343     * @return the random string
    344     * @since 3.5
    345     */
    346    public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
    347        return randomAlphanumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    348    }
    349
    350    /**
    351     * Creates a random string whose length is the number of characters
    352     * specified.
    353     *
    354     * <p>Characters will be chosen from the set of characters whose
    355     * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
    356     *
    357     * @param count  the length of random string to create
    358     * @return the random string
    359     * @throws IllegalArgumentException if {@code count} &lt; 0.
    360     */
    361    public static String randomAscii(final int count) {
    362        return random(count, 32, 127, false, false);
    363    }
    364
    365    /**
    366     * Creates a random string whose length is between the inclusive minimum and
    367     * the exclusive maximum.
    368     *
    369     * <p>Characters will be chosen from the set of characters whose
    370     * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
    371     *
    372     * @param minLengthInclusive the inclusive minimum length of the string to generate
    373     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    374     * @return the random string
    375     * @since 3.5
    376     */
    377    public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
    378        return randomAscii(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    379    }
    380
    381    /**
    382     * Creates a random string whose length is the number of characters specified.
    383     *
    384     * <p>Characters will be chosen from the set of characters which match the POSIX [:graph:]
    385     * regular expression character class. This class contains all visible ASCII characters
    386     * (i.e. anything except spaces and control characters).</p>
    387     *
    388     * @param count  the length of random string to create
    389     * @return the random string
    390     * @throws IllegalArgumentException if {@code count} &lt; 0.
    391     * @since 3.5
    392     */
    393    public static String randomGraph(final int count) {
    394        return random(count, 33, 126, false, false);
    395    }
    396
    397    /**
    398     * Creates a random string whose length is between the inclusive minimum and
    399     * the exclusive maximum.
    400     *
    401     * <p>Characters will be chosen from the set of \p{Graph} characters.</p>
    402     *
    403     * @param minLengthInclusive the inclusive minimum length of the string to generate
    404     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    405     * @return the random string
    406     * @since 3.5
    407     */
    408    public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
    409        return randomGraph(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    410    }
    411
    412    /**
    413     * Creates a random string whose length is the number of characters
    414     * specified.
    415     *
    416     * <p>Characters will be chosen from the set of numeric
    417     * characters.</p>
    418     *
    419     * @param count  the length of random string to create
    420     * @return the random string
    421     * @throws IllegalArgumentException if {@code count} &lt; 0.
    422     */
    423    public static String randomNumeric(final int count) {
    424        return random(count, false, true);
    425    }
    426
    427    /**
    428     * Creates a random string whose length is between the inclusive minimum and
    429     * the exclusive maximum.
    430     *
    431     * <p>Characters will be chosen from the set of \p{Digit} characters.</p>
    432     *
    433     * @param minLengthInclusive the inclusive minimum length of the string to generate
    434     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    435     * @return the random string
    436     * @since 3.5
    437     */
    438    public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
    439        return randomNumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    440    }
    441
    442    /**
    443     * Creates a random string whose length is the number of characters specified.
    444     *
    445     * <p>Characters will be chosen from the set of characters which match the POSIX [:print:]
    446     * regular expression character class. This class includes all visible ASCII characters and spaces
    447     * (i.e. anything except control characters).</p>
    448     *
    449     * @param count  the length of random string to create
    450     * @return the random string
    451     * @throws IllegalArgumentException if {@code count} &lt; 0.
    452     * @since 3.5
    453     */
    454    public static String randomPrint(final int count) {
    455        return random(count, 32, 126, false, false);
    456    }
    457
    458
    459    /**
    460     * Creates a random string whose length is between the inclusive minimum and
    461     * the exclusive maximum.
    462     *
    463     * <p>Characters will be chosen from the set of \p{Print} characters.</p>
    464     *
    465     * @param minLengthInclusive the inclusive minimum length of the string to generate
    466     * @param maxLengthExclusive the exclusive maximum length of the string to generate
    467     * @return the random string
    468     * @since 3.5
    469     */
    470    public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
    471        return randomPrint(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
    472    }
    473
    474    /**
    475     * {@link RandomStringUtils} instances should NOT be constructed in
    476     * standard programming. Instead, the class should be used as
    477     * {@code RandomStringUtils.random(5);}.
    478     *
    479     * <p>This constructor is public to permit tools that require a JavaBean instance
    480     * to operate.</p>
    481     */
    482    public RandomStringUtils() {
    483    }
    484
    485}