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