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