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