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 consecutive rejected draws so impossible requests eventually fail.
397        // Assuming independent uniform draws and at least one value acceptable for
398        // the remaining output length, the acceptance probability is at least
399        // 1 / 2^gapBits. A budget of 64 times that sample space makes the probability
400        // of exhausting the budget less than exp(-64) per accepted code point.
401        // Reset the counter after each accepted code point.
402        final long maxRejections = 64L << gapBits;
403        long rejections = 0;
404        while (count-- != 0) {
405            // Generate a random value between start (included) and end (excluded)
406            final int randomValue = arb.nextBits(gapBits) + start;
407            // Rejection sampling if value too large
408            if (randomValue >= end) {
409                count++;
410                if (++rejections > maxRejections) {
411                    throw new IllegalArgumentException(
412                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
413                }
414                continue;
415            }
416            final int codePoint;
417            if (chars == null) {
418                codePoint = randomValue;
419                switch (Character.getType(codePoint)) {
420                case Character.UNASSIGNED:
421                case Character.PRIVATE_USE:
422                case Character.SURROGATE:
423                    count++;
424                    if (++rejections > maxRejections) {
425                        throw new IllegalArgumentException(
426                                String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
427                    }
428                    continue;
429                }
430            } else {
431                codePoint = chars[randomValue];
432            }
433            final int numberOfChars = Character.charCount(codePoint);
434            if (count == 0 && numberOfChars > 1) {
435                count++;
436                if (++rejections > maxRejections) {
437                    throw new IllegalArgumentException(
438                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
439                }
440                continue;
441            }
442            if (letters && Character.isLetter(codePoint) || digits && Character.isDigit(codePoint) || !letters && !digits) {
443                builder.appendCodePoint(codePoint);
444                if (numberOfChars == 2) {
445                    count--;
446                }
447                rejections = 0;
448            } else {
449                count++;
450                if (++rejections > maxRejections) {
451                    throw new IllegalArgumentException(
452                            String.format("No acceptable code points found in range [%,d, %,d) within %,d attempts.", start, end, maxRejections));
453                }
454            }
455        }
456        return builder.toString();
457    }
458
459    /**
460     * Creates a random string whose length is the number of characters specified.
461     *
462     * <p>
463     * Characters will be chosen from the set of characters specified by the string, must not be empty. If null, the set
464     * of all characters is used.
465     * </p>
466     *
467     * @param count The length of random string to create.
468     * @param chars The String containing the set of characters to use, may be null, but must not be empty.
469     * @return The random string.
470     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0 or the string is empty.
471     * @deprecated Use {@link #next(int, String)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
472     */
473    @Deprecated
474    public static String random(final int count, final String chars) {
475        return secure().next(count, chars);
476    }
477
478    /**
479     * Creates a random string whose length is the number of characters specified.
480     *
481     * <p>
482     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
483     * </p>
484     *
485     * @param count The length of random string to create.
486     * @return The random string.
487     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
488     * @deprecated Use {@link #nextAlphabetic(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
489     */
490    @Deprecated
491    public static String randomAlphabetic(final int count) {
492        return secure().nextAlphabetic(count);
493    }
494
495    /**
496     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
497     *
498     * <p>
499     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
500     * </p>
501     *
502     * @param minLengthInclusive The inclusive minimum length of the string to generate.
503     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
504     * @return The random string.
505     * @since 3.5
506     * @deprecated Use {@link #nextAlphabetic(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
507     */
508    @Deprecated
509    public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
510        return secure().nextAlphabetic(minLengthInclusive, maxLengthExclusive);
511    }
512
513    /**
514     * Creates a random string whose length is the number of characters specified.
515     *
516     * <p>
517     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
518     * </p>
519     *
520     * @param count The length of random string to create.
521     * @return The random string.
522     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
523     * @deprecated Use {@link #nextAlphanumeric(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
524     */
525    @Deprecated
526    public static String randomAlphanumeric(final int count) {
527        return secure().nextAlphanumeric(count);
528    }
529
530    /**
531     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
532     *
533     * <p>
534     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
535     * </p>
536     *
537     * @param minLengthInclusive The inclusive minimum length of the string to generate.
538     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
539     * @return The random string.
540     * @since 3.5
541     * @deprecated Use {@link #nextAlphanumeric(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
542     */
543    @Deprecated
544    public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
545        return secure().nextAlphanumeric(minLengthInclusive, maxLengthExclusive);
546    }
547
548    /**
549     * Creates a random string whose length is the number of characters specified.
550     *
551     * <p>
552     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
553     * (inclusive).
554     * </p>
555     *
556     * @param count The length of random string to create.
557     * @return The random string.
558     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
559     * @deprecated Use {@link #nextAscii(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
560     */
561    @Deprecated
562    public static String randomAscii(final int count) {
563        return secure().nextAscii(count);
564    }
565
566    /**
567     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
568     *
569     * <p>
570     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
571     * (inclusive).
572     * </p>
573     *
574     * @param minLengthInclusive The inclusive minimum length of the string to generate.
575     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
576     * @return The random string.
577     * @since 3.5
578     * @deprecated Use {@link #nextAscii(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
579     */
580    @Deprecated
581    public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
582        return secure().nextAscii(minLengthInclusive, maxLengthExclusive);
583    }
584
585    /**
586     * Creates a random string whose length is the number of characters specified.
587     *
588     * <p>
589     * Characters will be chosen from the set of characters which match the POSIX [:graph:] regular expression character
590     * class. This class contains all visible ASCII characters (i.e. anything except spaces and control characters).
591     * </p>
592     *
593     * @param count The length of random string to create.
594     * @return The random string.
595     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
596     * @since 3.5
597     * @deprecated Use {@link #nextGraph(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
598     */
599    @Deprecated
600    public static String randomGraph(final int count) {
601        return secure().nextGraph(count);
602    }
603
604    /**
605     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
606     *
607     * <p>
608     * Characters will be chosen from the set of \p{Graph} characters.
609     * </p>
610     *
611     * @param minLengthInclusive The inclusive minimum length of the string to generate.
612     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
613     * @return The random string.
614     * @since 3.5
615     * @deprecated Use {@link #nextGraph(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
616     */
617    @Deprecated
618    public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
619        return secure().nextGraph(minLengthInclusive, maxLengthExclusive);
620    }
621
622    /**
623     * Creates a random string whose length is the number of characters specified.
624     *
625     * <p>
626     * Characters will be chosen from the set of numeric characters.
627     * </p>
628     *
629     * @param count The length of random string to create.
630     * @return The random string.
631     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
632     * @deprecated Use {@link #nextNumeric(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
633     */
634    @Deprecated
635    public static String randomNumeric(final int count) {
636        return secure().nextNumeric(count);
637    }
638
639    /**
640     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
641     *
642     * <p>
643     * Characters will be chosen from the set of \p{Digit} characters.
644     * </p>
645     *
646     * @param minLengthInclusive The inclusive minimum length of the string to generate.
647     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
648     * @return The random string.
649     * @since 3.5
650     * @deprecated Use {@link #nextNumeric(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
651     */
652    @Deprecated
653    public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
654        return secure().nextNumeric(minLengthInclusive, maxLengthExclusive);
655    }
656
657    /**
658     * Creates a random string whose length is the number of characters specified.
659     *
660     * <p>
661     * Characters will be chosen from the set of characters which match the POSIX [:print:] regular expression character
662     * class. This class includes all visible ASCII characters and spaces (i.e. anything except control characters).
663     * </p>
664     *
665     * @param count The length of random string to create.
666     * @return The random string.
667     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
668     * @since 3.5
669     * @deprecated Use {@link #nextPrint(int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
670     */
671    @Deprecated
672    public static String randomPrint(final int count) {
673        return secure().nextPrint(count);
674    }
675
676    /**
677     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
678     *
679     * <p>
680     * Characters will be chosen from the set of \p{Print} characters.
681     * </p>
682     *
683     * @param minLengthInclusive The inclusive minimum length of the string to generate.
684     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
685     * @return The random string.
686     * @since 3.5
687     * @deprecated Use {@link #nextPrint(int, int)} from {@link #secure()}, {@link #secureStrong()}, or {@link #insecure()}.
688     */
689    @Deprecated
690    public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
691        return secure().nextPrint(minLengthInclusive, maxLengthExclusive);
692    }
693
694    /**
695     * Gets the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator (RNG) implementing the default
696     * random number algorithm.
697     * <p>
698     * The method {@link SecureRandom#SecureRandom()} is called on-demand.
699     * </p>
700     *
701     * @return The singleton instance based on {@link SecureRandom#SecureRandom()}.
702     * @see SecureRandom#SecureRandom()
703     * @since 3.16.0
704     */
705    public static RandomStringUtils secure() {
706        return SECURE;
707    }
708
709    /**
710     * Gets the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an algorithms/providers
711     * specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
712     * <p>
713     * The method {@link SecureRandom#getInstanceStrong()} is called on-demand.
714     * </p>
715     *
716     * @return The singleton instance based on {@link SecureRandom#getInstanceStrong()}.
717     * @see SecureRandom#getInstanceStrong()
718     * @since 3.17.0
719     */
720    public static RandomStringUtils secureStrong() {
721        return SECURE_STRONG;
722    }
723
724    private final Supplier<RandomUtils> random;
725
726    /**
727     * {@link RandomStringUtils} instances should NOT be constructed in standard programming. Instead, the class should
728     * be used as {@code RandomStringUtils.random(5);}.
729     *
730     * <p>
731     * This constructor is public to permit tools that require a JavaBean instance to operate.
732     * </p>
733     *
734     * @deprecated TODO Make private in 4.0.
735     */
736    @Deprecated
737    public RandomStringUtils() {
738        this(SECURE_SUPPLIER);
739    }
740
741    private RandomStringUtils(final Supplier<RandomUtils> random) {
742        this.random = random;
743    }
744
745    /**
746     * Creates a random string whose length is the number of characters specified.
747     *
748     * <p>
749     * Characters will be chosen from the set of all characters.
750     * </p>
751     *
752     * @param count The length of random string to create.
753     * @return The random string.
754     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
755     * @since 3.16.0
756     */
757    public String next(final int count) {
758        return next(count, false, false);
759    }
760
761    /**
762     * Creates a random string whose length is the number of characters specified.
763     *
764     * <p>
765     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
766     * </p>
767     *
768     * @param count   The length of random string to create.
769     * @param letters if {@code true}, generated string may include alphabetic characters.
770     * @param numbers if {@code true}, generated string may include numeric characters.
771     * @return The random string.
772     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
773     * @since 3.16.0
774     */
775    public String next(final int count, final boolean letters, final boolean numbers) {
776        return next(count, 0, 0, letters, numbers);
777    }
778
779    /**
780     * Creates a random string whose length is the number of characters specified.
781     *
782     * <p>
783     * Characters will be chosen from the set of characters specified.
784     * </p>
785     *
786     * @param count The length of random string to create.
787     * @param chars The character array containing the set of characters to use, may be null.
788     * @return The random string.
789     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
790     * @since 3.16.0
791     */
792    public String next(final int count, final char... chars) {
793        if (chars == null) {
794            return random(count, 0, 0, false, false, null, random());
795        }
796        return random(count, 0, chars.length, false, false, chars, random());
797    }
798
799    /**
800     * Creates a random string whose length is the number of characters specified.
801     *
802     * <p>
803     * Characters will be chosen from the set of alphanumeric characters as indicated by the arguments.
804     * </p>
805     *
806     * @param count   The length of random string to create.
807     * @param start   The position in set of chars to start at.
808     * @param end     The position in set of chars to end before.
809     * @param letters if {@code true}, generated string may include alphabetic characters.
810     * @param numbers if {@code true}, generated string may include numeric characters.
811     * @return The random string.
812     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
813     * @since 3.16.0
814     */
815    public String next(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
816        return random(count, start, end, letters, numbers, null, random());
817    }
818
819    /**
820     * Creates a random string based on a variety of options, using default source of randomness.
821     *
822     * <p>
823     * This method has exactly the same semantics as {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
824     * instead of using an externally supplied source of randomness, it uses the internal static {@link Random}
825     * instance.
826     * </p>
827     *
828     * @param count   The length of random string to create.
829     * @param start   The position in set of chars to start at.
830     * @param end     The position in set of chars to end before.
831     * @param letters if {@code true}, generated string may include alphabetic characters.
832     * @param numbers if {@code true}, generated string may include numeric characters.
833     * @param chars   The set of chars to choose randoms from. If {@code null}, then it will use the set of all chars.
834     * @return The random string.
835     * @throws ArrayIndexOutOfBoundsException Thrown if there are not {@code (end - start) + 1} characters in the set array.
836     * @throws IllegalArgumentException       Thrown if {@code count} &lt; 0.
837     */
838    public String next(final int count, final int start, final int end, final boolean letters, final boolean numbers,
839            final char... chars) {
840        return random(count, start, end, letters, numbers, chars, random());
841    }
842
843    /**
844     * Creates a random string whose length is the number of characters specified.
845     *
846     * <p>
847     * Characters will be chosen from the set of characters specified by the string, must not be empty. If null, the set
848     * of all characters is used.
849     * </p>
850     *
851     * @param count The length of random string to create.
852     * @param chars The String containing the set of characters to use, may be null, but must not be empty.
853     * @return The random string.
854     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0 or the string is empty.
855     * @since 3.16.0
856     */
857    public String next(final int count, final String chars) {
858        if (chars == null) {
859            return random(count, 0, 0, false, false, null, random());
860        }
861        return next(count, chars.toCharArray());
862    }
863
864    /**
865     * Creates a random string whose length is the number of characters specified.
866     *
867     * <p>
868     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
869     * </p>
870     *
871     * @param count The length of random string to create.
872     * @return The random string.
873     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
874     */
875    public String nextAlphabetic(final int count) {
876        return next(count, true, false);
877    }
878
879    /**
880     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
881     *
882     * <p>
883     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).
884     * </p>
885     *
886     * @param minLengthInclusive The inclusive minimum length of the string to generate.
887     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
888     * @return The random string.
889     * @since 3.5
890     */
891    public String nextAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
892        return nextAlphabetic(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
893    }
894
895    /**
896     * Creates a random string whose length is the number of characters specified.
897     *
898     * <p>
899     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
900     * </p>
901     *
902     * @param count The length of random string to create.
903     * @return The random string.
904     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
905     */
906    public String nextAlphanumeric(final int count) {
907        return next(count, true, true);
908    }
909
910    /**
911     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
912     *
913     * <p>
914     * Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z) and the digits 0-9.
915     * </p>
916     *
917     * @param minLengthInclusive The inclusive minimum length of the string to generate.
918     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
919     * @return The random string.
920     * @since 3.5
921     */
922    public String nextAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
923        return nextAlphanumeric(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
924    }
925
926    /**
927     * Creates a random string whose length is the number of characters specified.
928     *
929     * <p>
930     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
931     * (inclusive).
932     * </p>
933     *
934     * @param count The length of random string to create.
935     * @return The random string.
936     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
937     */
938    public String nextAscii(final int count) {
939        return next(count, 32, 127, false, false);
940    }
941
942    /**
943     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
944     *
945     * <p>
946     * Characters will be chosen from the set of characters whose ASCII value is between {@code 32} and {@code 126}
947     * (inclusive).
948     * </p>
949     *
950     * @param minLengthInclusive The inclusive minimum length of the string to generate.
951     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
952     * @return The random string.
953     * @since 3.5
954     */
955    public String nextAscii(final int minLengthInclusive, final int maxLengthExclusive) {
956        return nextAscii(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
957    }
958
959    /**
960     * Creates a random string whose length is the number of characters specified.
961     *
962     * <p>
963     * Characters will be chosen from the set of characters which match the POSIX [:graph:] regular expression character
964     * class. This class contains all visible ASCII characters (i.e. anything except spaces and control characters).
965     * </p>
966     *
967     * @param count The length of random string to create.
968     * @return The random string.
969     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
970     * @since 3.5
971     */
972    public String nextGraph(final int count) {
973        return next(count, 33, 127, false, false);
974    }
975
976    /**
977     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
978     *
979     * <p>
980     * Characters will be chosen from the set of \p{Graph} characters.
981     * </p>
982     *
983     * @param minLengthInclusive The inclusive minimum length of the string to generate.
984     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
985     * @return The random string.
986     * @since 3.5
987     */
988    public String nextGraph(final int minLengthInclusive, final int maxLengthExclusive) {
989        return nextGraph(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
990    }
991
992    /**
993     * Creates a random string whose length is the number of characters specified.
994     *
995     * <p>
996     * Characters will be chosen from the set of numeric characters.
997     * </p>
998     *
999     * @param count The length of random string to create.
1000     * @return The random string.
1001     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
1002     */
1003    public String nextNumeric(final int count) {
1004        return next(count, false, true);
1005    }
1006
1007    /**
1008     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
1009     *
1010     * <p>
1011     * Characters will be chosen from the set of \p{Digit} characters.
1012     * </p>
1013     *
1014     * @param minLengthInclusive The inclusive minimum length of the string to generate.
1015     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
1016     * @return The random string.
1017     * @since 3.5
1018     */
1019    public String nextNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
1020        return nextNumeric(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
1021    }
1022
1023    /**
1024     * Creates a random string whose length is the number of characters specified.
1025     *
1026     * <p>
1027     * Characters will be chosen from the set of characters which match the POSIX [:print:] regular expression character
1028     * class. This class includes all visible ASCII characters and spaces (i.e. anything except control characters).
1029     * </p>
1030     *
1031     * @param count The length of random string to create.
1032     * @return The random string.
1033     * @throws IllegalArgumentException Thrown if {@code count} &lt; 0.
1034     * @since 3.5
1035     * @since 3.16.0
1036     */
1037    public String nextPrint(final int count) {
1038        return next(count, 32, 127, false, false);
1039    }
1040
1041    /**
1042     * Creates a random string whose length is between the inclusive minimum and the exclusive maximum.
1043     *
1044     * <p>
1045     * Characters will be chosen from the set of \p{Print} characters.
1046     * </p>
1047     *
1048     * @param minLengthInclusive The inclusive minimum length of the string to generate.
1049     * @param maxLengthExclusive The exclusive maximum length of the string to generate.
1050     * @return The random string.
1051     * @since 3.16.0
1052     */
1053    public String nextPrint(final int minLengthInclusive, final int maxLengthExclusive) {
1054        return nextPrint(randomUtils().randomInt(minLengthInclusive, maxLengthExclusive));
1055    }
1056
1057    /**
1058     * Gets the Random.
1059     *
1060     * @return The Random.
1061     */
1062    private Random random() {
1063        return randomUtils().random();
1064    }
1065
1066    /**
1067     * Gets the RandomUtils.
1068     *
1069     * @return The RandomUtils.
1070     */
1071    private RandomUtils randomUtils() {
1072        return random.get();
1073    }
1074
1075    @Override
1076    public String toString() {
1077        return "RandomStringUtils [random=" + random() + "]";
1078    }
1079
1080}