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 *      https://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.SecureRandom;
020import java.security.Security;
021import java.util.Random;
022import java.util.concurrent.ThreadLocalRandom;
023import java.util.function.Supplier;
024
025/**
026 * Generates random {@link String}s.
027 * <p>
028 * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator implementing the
029 * default random number algorithm.
030 * </p>
031 * <p>
032 * Use {@link #secureStrong()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an instance that was selected by using
033 * the algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
034 * </p>
035 * <p>
036 * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()} <strong>which is not cryptographically secure</strong>. In addition,
037 * instances do not use a cryptographically random seed unless the {@linkplain System#getProperty system property} {@code java.util.secureRandomSeed} is set to
038 * {@code true}.
039 * </p>
040 * <p>
041 * Starting in version 3.17.0, the method {@link #secure()} uses {@link SecureRandom#SecureRandom()} instead of {@link SecureRandom#getInstanceStrong()}, and
042 * adds {@link #secureStrong()}.
043 * </p>
044 * <p>
045 * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}.
046 * </p>
047 * <p>
048 * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods.
049 * </p>
050 * <p>
051 * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not cryptographically secure.
052 * </p>
053 * <p>
054 * RandomStringUtils is intended for simple use cases. For more advanced use cases consider using Apache Commons Text's
055 * <a href= "https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html"> RandomStringGenerator</a>
056 * instead.
057 * </p>
058 * <p>
059 * The Apache Commons project provides <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a> dedicated to pseudo-random number generation,
060 * that may be a better choice for applications with more stringent requirements (performance and/or correctness).
061 * </p>
062 * <p>
063 * Note that <em>private high surrogate</em> characters are ignored. These are Unicode characters that fall between the values 56192 (db80) and 56319 (dbff) as
064 * we don't know how to handle them. High and low surrogates are correctly dealt with - that is if a high surrogate is randomly chosen, 55296 (d800) to 56191
065 * (db7f) then it is followed by a low surrogate. If a low surrogate is chosen, 56320 (dc00) to 57343 (dfff) then it is placed after a randomly chosen high
066 * surrogate.
067 * </p>
068 * <p>
069 * #ThreadSafe#
070 * </p>
071 *
072 * @see #secure()
073 * @see #secureStrong()
074 * @see #insecure()
075 * @see SecureRandom#SecureRandom()
076 * @see SecureRandom#getInstanceStrong()
077 * @see ThreadLocalRandom#current()
078 * @see RandomUtils
079 * @since 1.0
080 */
081public class RandomStringUtils {
082
083    private static final Supplier<RandomUtils> SECURE_SUPPLIER = RandomUtils::secure;
084
085    private static final RandomStringUtils INSECURE = new RandomStringUtils(RandomUtils::insecure);
086
087    private static final RandomStringUtils SECURE = new RandomStringUtils(SECURE_SUPPLIER);
088
089    private static final RandomStringUtils SECURE_STRONG = new RandomStringUtils(RandomUtils::secureStrong);
090
091    private static final char[] ALPHANUMERICAL_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
092            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
093            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1',
094            '2', '3', '4', '5', '6', '7', '8', '9' };
095
096    private static final int ASCII_0 = '0';
097    private static final int ASCII_9 = '9';
098    private static final int ASCII_A = 'A';
099    private static final int ASCII_z = 'z';
100
101    private static final int CACHE_PADDING_BITS = 3;
102    private static final int BITS_TO_BYTES_DIVISOR = 5;
103    private static final int BASE_CACHE_SIZE_PADDING = 10;
104
105    /**
106     * Gets the singleton instance based on {@link ThreadLocalRandom#current()}; <b>which is not cryptographically
107     * secure</b>; for more secure processing use {@link #secure()} or {@link #secureStrong()}.
108     * <p>
109     * The method {@link ThreadLocalRandom#current()} is called on-demand.
110     * </p>
111     *
112     * @return The singleton instance based on {@link ThreadLocalRandom#current()}.
113     * @see ThreadLocalRandom#current()
114     * @see #secure()
115     * @see #secureStrong()
116     * @since 3.16.0
117     */
118    public static RandomStringUtils insecure() {
119        return INSECURE;
120    }
121
122    /**
123     * Creates a random string whose length is the number of characters specified.
124     *
125     * <p>
126     * Characters will be chosen from the set of all characters.
127     * </p>
128     *
129     * @param count The length of random string to create.
130     * @return The random string.
131     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
132     * @deprecated Use {@link #next(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
133     */
134    @Deprecated
135    public static String random(final int count) {
136        return secure().next(count);
137    }
138
139    /**
140     * Creates a random string whose length is the number of characters specified.
141     *
142     * <p>
143     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
144     * </p>
145     *
146     * @param count   The length of random string to create.
147     * @param letters if {@code true}, generated string may include alphabetic characters.
148     * @param numbers if {@code true}, generated string may include numeric characters.
149     * @return The random string.
150     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
151     * @deprecated Use {@link #next(int, boolean, boolean)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
152     */
153    @Deprecated
154    public static String random(final int count, final boolean letters, final boolean numbers) {
155        return secure().next(count, letters, numbers);
156    }
157
158    /**
159     * Creates a random string whose length is the number of characters specified.
160     *
161     * <p>
162     * Characters will be chosen from the set of characters specified.
163     * </p>
164     *
165     * @param count The length of random string to create.
166     * @param chars The character array containing the set of characters to use, may be null.
167     * @return The random string.
168     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
169     * @deprecated Use {@link #next(int, char...)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
170     */
171    @Deprecated
172    public static String random(final int count, final char... chars) {
173        return secure().next(count, chars);
174    }
175
176    /**
177     * Creates a random string whose length is the number of characters specified.
178     *
179     * <p>
180     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
181     * </p>
182     *
183     * @param count   The length of random string to create.
184     * @param start   The position in set of chars to start at.
185     * @param end     The position in set of chars to end before.
186     * @param letters if {@code true}, generated string may include alphabetic characters.
187     * @param numbers if {@code true}, generated string may include numeric characters.
188     * @return The random string.
189     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
190     * @deprecated Use {@link #next(int, int, int, boolean, boolean)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
191     */
192    @Deprecated
193    public static String random(final int count, final int start, final int end, final boolean letters,
194            final boolean numbers) {
195        return secure().next(count, start, end, letters, numbers);
196    }
197
198    /**
199     * Creates a random string based on a variety of options, using default source of randomness.
200     *
201     * <p>
202     * This method has exactly the same semantics as {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
203     * instead of using an externally supplied source of randomness, it uses the internal static {@link Random}
204     * instance.
205     * </p>
206     *
207     * @param count   The length of random string to create.
208     * @param start   The position in set of chars to start at.
209     * @param end     The position in set of chars to end before.
210     * @param letters if {@code true}, generated string may include alphabetic characters.
211     * @param numbers if {@code true}, generated string may include numeric characters.
212     * @param chars   The set of chars to choose randoms from. If {@code null}, then it will use the set of all chars.
213     * @return The random string.
214     * @throws ArrayIndexOutOfBoundsException Thrown if there are not {@code (end - start) + 1} characters in the set array.
215     * @throws IllegalArgumentException       Thrown if {@code count} &lt; 0.
216     * @deprecated Use {@link #next(int, int, int, boolean, boolean, char...)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
217     */
218    @Deprecated
219    public static String random(final int count, final int start, final int end, final boolean letters,
220            final boolean numbers, final char... chars) {
221        return secure().next(count, start, end, letters, numbers, chars);
222    }
223
224    /**
225     * Creates a random string based on a variety of options, using supplied source of randomness.
226     *
227     * <p>
228     * If start and end are both {@code 0}, start and end are set to {@code ' '} and {@code 'z'}, the ASCII printable
229     * characters, will be used, unless letters and numbers are both {@code false}, in which case, start and end are set
230     * to {@code 0} and {@link Character#MAX_CODE_POINT}.
231     *
232     * <p>
233     * If set is not {@code null}, characters between start and end are chosen.
234     * </p>
235     *
236     * <p>
237     * This method accepts a user-supplied {@link Random} instance to use as a source of randomness. By seeding a single
238     * {@link Random} instance with a fixed seed and using it for each call, the same random sequence of strings can be
239     * generated repeatedly and predictably.
240     * </p>
241     *
242     * @param count   The length of random string to create.
243     * @param start   The position in set of chars to start at (inclusive).
244     * @param end     The position in set of chars to end before (exclusive).
245     * @param letters if {@code true}, generated string may include alphabetic characters.
246     * @param digits if {@code true}, generated string may include digit characters.
247     * @param chars   The set of chars to choose randoms from, must not be empty. If {@code null}, then it will use the
248     *                set of all chars.
249     * @param random  A source of randomness.
250     * @return The random string.
251     * @throws ArrayIndexOutOfBoundsException Thrown if there are not {@code (end - start) + 1} characters in the set array.
252     * @throws IllegalArgumentException       Thrown if {@code count} &lt; 0 or the provided chars array is empty.
253     * @since 2.0
254     */
255    public static String random(int count, int start, int end, final boolean letters, final boolean digits,
256            final char[] chars, final Random random) {
257        if (count == 0) {
258            return StringUtils.EMPTY;
259        }
260        if (count < 0) {
261            throw new IllegalArgumentException(String.format("Requested random string length %,d is less than 0.", end));
262        }
263        if (chars != null && chars.length == 0) {
264            throw new IllegalArgumentException("The chars array must not be empty");
265        }
266        if (start == 0 && end == 0) {
267            if (chars != null) {
268                end = chars.length;
269            } else if (!letters && !digits) {
270                end = Character.MAX_CODE_POINT;
271            } else {
272                end = 'z' + 1;
273                start = ' ';
274            }
275        } else if (end <= start) {
276            throw new IllegalArgumentException(String.format("Parameter end (%,d) must be greater than start (%,d)", end, start));
277        } else if (start < 0 || end < 0) {
278            throw new IllegalArgumentException("Character positions MUST be >= 0");
279        } else if (chars != null && start >= chars.length) {
280            throw new IllegalArgumentException("start >= chars.length");
281        } else if (chars != null && end > chars.length) {
282            throw new IllegalArgumentException("end > chars.length");
283        }
284        if (end > Character.MAX_CODE_POINT) {
285            // Technically, it should be `Character.MAX_CODE_POINT+1` as `end` is excluded
286            // But the character `Character.MAX_CODE_POINT` is private use, so it would anyway be excluded
287            end = Character.MAX_CODE_POINT;
288        }
289        // Optimizations and tests when chars == null and using ASCII characters (end <= 0x7f)
290        if (chars == null && end <= 0x7f) {
291            // Optimize generation of full alphanumerical characters
292            // Normally, we would need to pick a 7-bit integer, since gap = 'z' - '0' + 1 = 75 > 64
293            // In turn, this would make us reject the sampling with probability 1 - 62 / 2^7 > 1 / 2
294            // Instead we can pick directly from the right set of 62 characters, which requires
295            // picking a 6-bit integer and only rejecting with probability 2 / 64 = 1 / 32
296            if (letters && digits && start <= ASCII_0 && end >= ASCII_z + 1) {
297                return random(count, 0, 0, false, false, ALPHANUMERICAL_CHARS, random);
298            }
299            // Only reject when none of the requested categories is reachable; otherwise a letters && digits
300            // request would throw on a range that holds one category but not the other (e.g. [ASCII_0, ASCII_A)).
301            if ((!digits || end <= ASCII_0) && (!letters || end <= ASCII_A) && (digits || letters)) {
302                throw new IllegalArgumentException(
303                        String.format("Parameter end (%,d) must be greater than (%,d) for generating digits or greater than (%,d) for generating letters.", end,
304                                ASCII_0, ASCII_A));
305            }
306            // Optimize start and end when filtering by letters and/or numbers:
307            // The range provided may be too large since we filter anyway afterward.
308            // Note the use of Math.min/max (as opposed to setting start to '0' for example),
309            // since it is possible the range start/end excludes some of the letters/numbers,
310            // e.g., it is possible that start already is '1' when numbers = true, and start
311            // needs to stay equal to '1' in that case.
312            // Note that because of the above test, we will always have start < end
313            // even after this optimization.
314            if (letters && digits) {
315                start = Math.max(ASCII_0, start);
316                end = Math.min(ASCII_z + 1, end);
317                // The clamp can empty the range when it sits above the alphanumerics (e.g. [ASCII_z + 1, 0x7f)),
318                // unlike the single-category branches below which are validated by the reachability loops further
319                // down. Reject here so the caller gets a clear range error instead of nextBits(0) failing later.
320                if (start >= end) {
321                    throw new IllegalArgumentException(String.format("No letters or digits exist between start %,d and end %,d.", start, end));
322                }
323            } else if (digits) {
324                // just numbers, no letters
325                start = Math.max(ASCII_0, start);
326                end = Math.min(ASCII_9 + 1, end);
327            } else if (letters) {
328                // just letters, no numbers
329                start = Math.max(ASCII_A, start);
330                end = Math.min(ASCII_z + 1, end);
331            }
332        }
333        if (chars == null) {
334            // start/end are code points: validate using Character.isLetter/isDigit on the
335            // code-point range rather than on the loop index.
336            if (letters && !digits) {
337                boolean ok = false;
338                for (int i = start; i < end; i++) {
339                    if (Character.isLetter(i)) {
340                        ok = true;
341                        break;
342                    }
343                }
344                if (!ok) {
345                    throw new IllegalArgumentException(String.format("No letters exist between start %,d and end %,d.", start, end));
346                }
347            }
348            if (!letters && digits) {
349                boolean ok = false;
350                for (int i = start; i < end; i++) {
351                    if (Character.isDigit(i)) {
352                        ok = true;
353                        break;
354                    }
355                }
356                if (!ok) {
357                    throw new IllegalArgumentException(String.format("No digits exist between start %,d and end %,d.", start, end));
358                }
359            }
360        } else if (letters || digits) {
361            // chars != null. start/end are indices into chars[]; validate the actual
362            // chars contain at least one element matching some requested letter/digit
363            // category to avoid an infinite generation loop when the array lacks every
364            // requested category.
365            boolean hasMatch = false;
366            for (int i = start; i < end; i++) {
367                final char c = chars[i];
368                if (letters && Character.isLetter(c) || digits && Character.isDigit(c)) {
369                    hasMatch = true;
370                    break;
371                }
372            }
373            if (!hasMatch) {
374                throw new IllegalArgumentException(String.format("No %s%s%s exist in chars[%,d..%,d).", letters ? "letters" : "",
375                        letters && digits ? " or " : "", digits ? "digits" : "", start, end));
376            }
377        }
378        final StringBuilder builder = new StringBuilder(count);
379        final int gap = end - start;
380        final int gapBits = Integer.SIZE - Integer.numberOfLeadingZeros(gap);
381        // The size of the cache we use is an heuristic:
382        // about twice the number of bytes required if no rejection
383        // Ideally the cache size depends on multiple factor, including the cost of generating x bytes
384        // of randomness as well as the probability of rejection. It is however not easy to know
385        // those values programmatically for the general case.
386        // Calculate cache size:
387        // 1. Multiply count by bits needed per character (gapBits)
388        // 2. Add padding bits (3) to handle partial bytes
389        // 3. Divide by 5 to convert to bytes (normally this would be by 8, dividing by 5 allows for about 60% extra space)
390        // 4. Add base padding (10) to handle small counts efficiently
391        // 5. Ensure we don't exceed Integer.MAX_VALUE / 5 + 10 to provide a good balance between overflow prevention and
392        // making the cache extremely large
393        final long desiredCacheSize = ((long) count * gapBits + CACHE_PADDING_BITS) / BITS_TO_BYTES_DIVISOR + BASE_CACHE_SIZE_PADDING;
394        final int cacheSize = (int) Math.min(desiredCacheSize, Integer.MAX_VALUE / BITS_TO_BYTES_DIVISOR + BASE_CACHE_SIZE_PADDING);
395        final CachedRandomBits arb = new CachedRandomBits(cacheSize, random);
396        // Bound rejection retries so a range that rejects every sample
397        // (for example, entirely UNASSIGNED/PRIVATE_USE/SURROGATE) raises an
398        // IllegalArgumentException instead of looping indefinitely. Cap is
399        // (end - start) * 10 with a small floor so tiny gaps still get a
400        // reasonable budget. The counter resets on every accepted code point.
401        final int maxRejections = Math.max(64, gap * 10);
402        int rejections = 0;
403        while (count-- != 0) {
404            // Generate a random value between start (included) and end (excluded)
405            final int randomValue = arb.nextBits(gapBits) + start;
406            // Rejection sampling if value too large
407            if (randomValue >= end) {
408                count++;
409                if (++rejections > maxRejections) {
410                    throw new IllegalArgumentException(
411                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
412                }
413                continue;
414            }
415            final int codePoint;
416            if (chars == null) {
417                codePoint = randomValue;
418                switch (Character.getType(codePoint)) {
419                case Character.UNASSIGNED:
420                case Character.PRIVATE_USE:
421                case Character.SURROGATE:
422                    count++;
423                    if (++rejections > maxRejections) {
424                        throw new IllegalArgumentException(
425                                String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
426                    }
427                    continue;
428                }
429            } else {
430                codePoint = chars[randomValue];
431            }
432            final int numberOfChars = Character.charCount(codePoint);
433            if (count == 0 && numberOfChars > 1) {
434                count++;
435                if (++rejections > maxRejections) {
436                    throw new IllegalArgumentException(
437                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
438                }
439                continue;
440            }
441            if (letters && Character.isLetter(codePoint) || digits && Character.isDigit(codePoint) || !letters && !digits) {
442                builder.appendCodePoint(codePoint);
443                if (numberOfChars == 2) {
444                    count--;
445                }
446                rejections = 0;
447            } else {
448                count++;
449                if (++rejections > maxRejections) {
450                    throw new IllegalArgumentException(
451                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
452                }
453            }
454        }
455        return builder.toString();
456    }
457
458    /**
459     * Creates a random string whose length is the number of characters specified.
460     *
461     * <p>
462     * Characters will be chosen from the set of characters specified by the string, must not be empty. If null, the set
463     * of all characters is used.
464     * </p>
465     *
466     * @param count The length of random string to create.
467     * @param chars The String containing the set of characters to use, may be null, but must not be empty.
468     * @return The random string.
469     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0 or the string is empty.
470     * @deprecated Use {@link #next(int, String)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
471     */
472    @Deprecated
473    public static String random(final int count, final String chars) {
474        return secure().next(count, chars);
475    }
476
477    /**
478     * Creates a random string whose length is the number of characters specified.
479     *
480     * <p>
481     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
482     * </p>
483     *
484     * @param count The length of random string to create.
485     * @return The random string.
486     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
487     * @deprecated Use {@link #nextAlphabetic(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
488     */
489    @Deprecated
490    public static String randomAlphabetic(final int count) {
491        return secure().nextAlphabetic(count);
492    }
493
494    /**
495     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
496     *
497     * <p>
498     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
499     * </p>
500     *
501     * @param minLengthInclusive The inclusive minimum length of the string to generate.
502     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
503     * @return The random string.
504     * @since 3.5
505     * @deprecated Use {@link #nextAlphabetic(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
506     */
507    @Deprecated
508    public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
509        return secure().nextAlphabetic(minLengthInclusive, maxLengthExclusive);
510    }
511
512    /**
513     * Creates a random string whose length is the number of characters specified.
514     *
515     * <p>
516     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
517     * </p>
518     *
519     * @param count The length of random string to create.
520     * @return The random string.
521     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
522     * @deprecated Use {@link #nextAlphanumeric(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
523     */
524    @Deprecated
525    public static String randomAlphanumeric(final int count) {
526        return secure().nextAlphanumeric(count);
527    }
528
529    /**
530     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
531     *
532     * <p>
533     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
534     * </p>
535     *
536     * @param minLengthInclusive The inclusive minimum length of the string to generate.
537     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
538     * @return The random string.
539     * @since 3.5
540     * @deprecated Use {@link #nextAlphanumeric(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
541     */
542    @Deprecated
543    public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
544        return secure().nextAlphanumeric(minLengthInclusive, maxLengthExclusive);
545    }
546
547    /**
548     * Creates a random string whose length is the number of characters specified.
549     *
550     * <p>
551     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
552     * (inclusive).
553     * </p>
554     *
555     * @param count The length of random string to create.
556     * @return The random string.
557     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
558     * @deprecated Use {@link #nextAscii(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
559     */
560    @Deprecated
561    public static String randomAscii(final int count) {
562        return secure().nextAscii(count);
563    }
564
565    /**
566     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
567     *
568     * <p>
569     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
570     * (inclusive).
571     * </p>
572     *
573     * @param minLengthInclusive The inclusive minimum length of the string to generate.
574     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
575     * @return The random string.
576     * @since 3.5
577     * @deprecated Use {@link #nextAscii(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
578     */
579    @Deprecated
580    public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
581        return secure().nextAscii(minLengthInclusive, maxLengthExclusive);
582    }
583
584    /**
585     * Creates a random string whose length is the number of characters specified.
586     *
587     * <p>
588     * Characters will be chosen from the set of characters which match the POSIX [:graph:] regular expression character
589     * class. This class contains all visible ASCII characters (i.e. anything except spaces and control characters).
590     * </p>
591     *
592     * @param count The length of random string to create.
593     * @return The random string.
594     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
595     * @since 3.5
596     * @deprecated Use {@link #nextGraph(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
597     */
598    @Deprecated
599    public static String randomGraph(final int count) {
600        return secure().nextGraph(count);
601    }
602
603    /**
604     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
605     *
606     * <p>
607     * Characters will be chosen from the set of \p{Graph} characters.
608     * </p>
609     *
610     * @param minLengthInclusive The inclusive minimum length of the string to generate.
611     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
612     * @return The random string.
613     * @since 3.5
614     * @deprecated Use {@link #nextGraph(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
615     */
616    @Deprecated
617    public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
618        return secure().nextGraph(minLengthInclusive, maxLengthExclusive);
619    }
620
621    /**
622     * Creates a random string whose length is the number of characters specified.
623     *
624     * <p>
625     * Characters will be chosen from the set of numeric characters.
626     * </p>
627     *
628     * @param count The length of random string to create.
629     * @return The random string.
630     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
631     * @deprecated Use {@link #nextNumeric(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
632     */
633    @Deprecated
634    public static String randomNumeric(final int count) {
635        return secure().nextNumeric(count);
636    }
637
638    /**
639     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
640     *
641     * <p>
642     * Characters will be chosen from the set of \p{Digit} characters.
643     * </p>
644     *
645     * @param minLengthInclusive The inclusive minimum length of the string to generate.
646     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
647     * @return The random string.
648     * @since 3.5
649     * @deprecated Use {@link #nextNumeric(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
650     */
651    @Deprecated
652    public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
653        return secure().nextNumeric(minLengthInclusive, maxLengthExclusive);
654    }
655
656    /**
657     * Creates a random string whose length is the number of characters specified.
658     *
659     * <p>
660     * Characters will be chosen from the set of characters which match the POSIX [:print:] regular expression character
661     * class. This class includes all visible ASCII characters and spaces (i.e. anything except control characters).
662     * </p>
663     *
664     * @param count The length of random string to create.
665     * @return The random string.
666     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
667     * @since 3.5
668     * @deprecated Use {@link #nextPrint(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
669     */
670    @Deprecated
671    public static String randomPrint(final int count) {
672        return secure().nextPrint(count);
673    }
674
675    /**
676     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
677     *
678     * <p>
679     * Characters will be chosen from the set of \p{Print} characters.
680     * </p>
681     *
682     * @param minLengthInclusive The inclusive minimum length of the string to generate.
683     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
684     * @return The random string.
685     * @since 3.5
686     * @deprecated Use {@link #nextPrint(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
687     */
688    @Deprecated
689    public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
690        return secure().nextPrint(minLengthInclusive, maxLengthExclusive);
691    }
692
693    /**
694     * Gets the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator (RNG) implementing the default
695     * random number algorithm.
696     * <p>
697     * The method {@link SecureRandom#SecureRandom()} is called on-demand.
698     * </p>
699     *
700     * @return The singleton instance based on {@link SecureRandom#SecureRandom()}.
701     * @see SecureRandom#SecureRandom()
702     * @since 3.16.0
703     */
704    public static RandomStringUtils secure() {
705        return SECURE;
706    }
707
708    /**
709     * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers
710     * specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
711     * <p>
712     * The method {@link SecureRandom#getInstanceStrong()} is called on-demand.
713     * </p>
714     *
715     * @return The singleton instance based on {@link SecureRandom#getInstanceStrong()}.
716     * @see SecureRandom#getInstanceStrong()
717     * @since 3.17.0
718     */
719    public static RandomStringUtils secureStrong() {
720        return SECURE_STRONG;
721    }
722
723    private final Supplier<RandomUtils> random;
724
725    /**
726     * {@link RandomStringUtils} instances should NOT be constructed in standard programming. Instead, the class should
727     * be used as {@code RandomStringUtils.random(5);}.
728     *
729     * <p>
730     * This constructor is public to permit tools that require a JavaBean instance to operate.
731     * </p>
732     *
733     * @deprecated TODO Make private in 4.0.
734     */
735    @Deprecated
736    public RandomStringUtils() {
737        this(SECURE_SUPPLIER);
738    }
739
740    private RandomStringUtils(final Supplier<RandomUtils> random) {
741        this.random = random;
742    }
743
744    /**
745     * Creates a random string whose length is the number of characters specified.
746     *
747     * <p>
748     * Characters will be chosen from the set of all characters.
749     * </p>
750     *
751     * @param count The length of random string to create.
752     * @return The random string.
753     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
754     * @since 3.16.0
755     */
756    public String next(final int count) {
757        return next(count, false, false);
758    }
759
760    /**
761     * Creates a random string whose length is the number of characters specified.
762     *
763     * <p>
764     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
765     * </p>
766     *
767     * @param count   The length of random string to create.
768     * @param letters if {@code true}, generated string may include alphabetic characters.
769     * @param numbers if {@code true}, generated string may include numeric characters.
770     * @return The random string.
771     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
772     * @since 3.16.0
773     */
774    public String next(final int count, final boolean letters, final boolean numbers) {
775        return next(count, 0, 0, letters, numbers);
776    }
777
778    /**
779     * Creates a random string whose length is the number of characters specified.
780     *
781     * <p>
782     * Characters will be chosen from the set of characters specified.
783     * </p>
784     *
785     * @param count The length of random string to create.
786     * @param chars The character array containing the set of characters to use, may be null.
787     * @return The random string.
788     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
789     * @since 3.16.0
790     */
791    public String next(final int count, final char... chars) {
792        if (chars == null) {
793            return random(count, 0, 0, false, false, null, random());
794        }
795        return random(count, 0, chars.length, false, false, chars, random());
796    }
797
798    /**
799     * Creates a random string whose length is the number of characters specified.
800     *
801     * <p>
802     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
803     * </p>
804     *
805     * @param count   The length of random string to create.
806     * @param start   The position in set of chars to start at.
807     * @param end     The position in set of chars to end before.
808     * @param letters if {@code true}, generated string may include alphabetic characters.
809     * @param numbers if {@code true}, generated string may include numeric characters.
810     * @return The random string.
811     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
812     * @since 3.16.0
813     */
814    public String next(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
815        return random(count, start, end, letters, numbers, null, random());
816    }
817
818    /**
819     * Creates a random string based on a variety of options, using default source of randomness.
820     *
821     * <p>
822     * This method has exactly the same semantics as {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
823     * instead of using an externally supplied source of randomness, it uses the internal static {@link Random}
824     * instance.
825     * </p>
826     *
827     * @param count   The length of random string to create.
828     * @param start   The position in set of chars to start at.
829     * @param end     The position in set of chars to end before.
830     * @param letters if {@code true}, generated string may include alphabetic characters.
831     * @param numbers if {@code true}, generated string may include numeric characters.
832     * @param chars   The set of chars to choose randoms from. If {@code null}, then it will use the set of all chars.
833     * @return The random string.
834     * @throws ArrayIndexOutOfBoundsException Thrown if there are not {@code (end - start) + 1} characters in the set array.
835     * @throws IllegalArgumentException       Thrown if {@code count} &lt; 0.
836     */
837    public String next(final int count, final int start, final int end, final boolean letters, final boolean numbers,
838            final char... chars) {
839        return random(count, start, end, letters, numbers, chars, random());
840    }
841
842    /**
843     * Creates a random string whose length is the number of characters specified.
844     *
845     * <p>
846     * Characters will be chosen from the set of characters specified by the string, must not be empty. If null, the set
847     * of all characters is used.
848     * </p>
849     *
850     * @param count The length of random string to create.
851     * @param chars The String containing the set of characters to use, may be null, but must not be empty.
852     * @return The random string.
853     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0 or the string is empty.
854     * @since 3.16.0
855     */
856    public String next(final int count, final String chars) {
857        if (chars == null) {
858            return random(count, 0, 0, false, false, null, random());
859        }
860        return next(count, chars.toCharArray());
861    }
862
863    /**
864     * Creates a random string whose length is the number of characters specified.
865     *
866     * <p>
867     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
868     * </p>
869     *
870     * @param count The length of random string to create.
871     * @return The random string.
872     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
873     */
874    public String nextAlphabetic(final int count) {
875        return next(count, true, false);
876    }
877
878    /**
879     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
880     *
881     * <p>
882     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
883     * </p>
884     *
885     * @param minLengthInclusive The inclusive minimum length of the string to generate.
886     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
887     * @return The random string.
888     * @since 3.5
889     */
890    public String nextAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
891        return nextAlphabetic(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
892    }
893
894    /**
895     * Creates a random string whose length is the number of characters specified.
896     *
897     * <p>
898     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
899     * </p>
900     *
901     * @param count The length of random string to create.
902     * @return The random string.
903     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
904     */
905    public String nextAlphanumeric(final int count) {
906        return next(count, true, true);
907    }
908
909    /**
910     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
911     *
912     * <p>
913     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
914     * </p>
915     *
916     * @param minLengthInclusive The inclusive minimum length of the string to generate.
917     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
918     * @return The random string.
919     * @since 3.5
920     */
921    public String nextAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
922        return nextAlphanumeric(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
923    }
924
925    /**
926     * Creates a random string whose length is the number of characters specified.
927     *
928     * <p>
929     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
930     * (inclusive).
931     * </p>
932     *
933     * @param count The length of random string to create.
934     * @return The random string.
935     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
936     */
937    public String nextAscii(final int count) {
938        return next(count, 32, 127, false, false);
939    }
940
941    /**
942     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
943     *
944     * <p>
945     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
946     * (inclusive).
947     * </p>
948     *
949     * @param minLengthInclusive The inclusive minimum length of the string to generate.
950     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
951     * @return The random string.
952     * @since 3.5
953     */
954    public String nextAscii(final int minLengthInclusive, final int maxLengthExclusive) {
955        return nextAscii(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
956    }
957
958    /**
959     * Creates a random string whose length is the number of characters specified.
960     *
961     * <p>
962     * Characters will be chosen from the set of characters which match the POSIX [:graph:] regular expression character
963     * class. This class contains all visible ASCII characters (i.e. anything except spaces and control characters).
964     * </p>
965     *
966     * @param count The length of random string to create.
967     * @return The random string.
968     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
969     * @since 3.5
970     */
971    public String nextGraph(final int count) {
972        return next(count, 33, 126, false, false);
973    }
974
975    /**
976     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
977     *
978     * <p>
979     * Characters will be chosen from the set of \p{Graph} characters.
980     * </p>
981     *
982     * @param minLengthInclusive The inclusive minimum length of the string to generate.
983     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
984     * @return The random string.
985     * @since 3.5
986     */
987    public String nextGraph(final int minLengthInclusive, final int maxLengthExclusive) {
988        return nextGraph(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
989    }
990
991    /**
992     * Creates a random string whose length is the number of characters specified.
993     *
994     * <p>
995     * Characters will be chosen from the set of numeric characters.
996     * </p>
997     *
998     * @param count The length of random string to create.
999     * @return The random string.
1000     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
1001     */
1002    public String nextNumeric(final int count) {
1003        return next(count, false, true);
1004    }
1005
1006    /**
1007     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
1008     *
1009     * <p>
1010     * Characters will be chosen from the set of \p{Digit} characters.
1011     * </p>
1012     *
1013     * @param minLengthInclusive The inclusive minimum length of the string to generate.
1014     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
1015     * @return The random string.
1016     * @since 3.5
1017     */
1018    public String nextNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
1019        return nextNumeric(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
1020    }
1021
1022    /**
1023     * Creates a random string whose length is the number of characters specified.
1024     *
1025     * <p>
1026     * Characters will be chosen from the set of characters which match the POSIX [:print:] regular expression character
1027     * class. This class includes all visible ASCII characters and spaces (i.e. anything except control characters).
1028     * </p>
1029     *
1030     * @param count The length of random string to create.
1031     * @return The random string.
1032     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
1033     * @since 3.5
1034     * @since 3.16.0
1035     */
1036    public String nextPrint(final int count) {
1037        return next(count, 32, 126, false, false);
1038    }
1039
1040    /**
1041     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
1042     *
1043     * <p>
1044     * Characters will be chosen from the set of \p{Print} characters.
1045     * </p>
1046     *
1047     * @param minLengthInclusive The inclusive minimum length of the string to generate.
1048     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
1049     * @return The random string.
1050     * @since 3.16.0
1051     */
1052    public String nextPrint(final int minLengthInclusive, final int maxLengthExclusive) {
1053        return nextPrint(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
1054    }
1055
1056    /**
1057     * Gets the Random.
1058     *
1059     * @return The Random.
1060     */
1061    private Random random() {
1062        return randomUtils().random();
1063    }
1064
1065    /**
1066     * Gets the RandomUtils.
1067     *
1068     * @return The RandomUtils.
1069     */
1070    private RandomUtils randomUtils() {
1071        return random.get();
1072    }
1073
1074    @Override
1075    public String toString() {
1076        return "RandomStringUtils [random=" + random() + "]";
1077    }
1078
1079}