1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang3;
18
19 import java.security.SecureRandom;
20 import java.security.Security;
21 import java.util.Random;
22 import java.util.concurrent.ThreadLocalRandom;
23 import java.util.function.Supplier;
24
25 /**
26 * Generates random {@link String}s.
27 * <p>
28 * Use {@link #secure()} to get the singleton instance based on {@link SecureRandom#SecureRandom()} which uses a secure random number generator implementing the
29 * default random number algorithm.
30 * </p>
31 * <p>
32 * Use {@link #secureStrong()} to get the singleton instance based on {@link SecureRandom#getInstanceStrong()} which uses an instance that was selected by using
33 * the algorithms/providers specified in the {@code securerandom.strongAlgorithms} {@link Security} property.
34 * </p>
35 * <p>
36 * Use {@link #insecure()} to get the singleton instance based on {@link ThreadLocalRandom#current()} <strong>which is not cryptographically secure</strong>. In addition,
37 * instances do not use a cryptographically random seed unless the {@linkplain System#getProperty system property} {@code java.util.secureRandomSeed} is set to
38 * {@code true}.
39 * </p>
40 * <p>
41 * Starting in version 3.17.0, the method {@link #secure()} uses {@link SecureRandom#SecureRandom()} instead of {@link SecureRandom#getInstanceStrong()}, and
42 * adds {@link #secureStrong()}.
43 * </p>
44 * <p>
45 * Starting in version 3.16.0, this class uses {@link #secure()} for static methods and adds {@link #insecure()}.
46 * </p>
47 * <p>
48 * Starting in version 3.15.0, this class uses {@link SecureRandom#getInstanceStrong()} for static methods.
49 * </p>
50 * <p>
51 * Before version 3.15.0, this class used {@link ThreadLocalRandom#current()} for static methods, which is not cryptographically secure.
52 * </p>
53 * <p>
54 * RandomStringUtils is intended for simple use cases. For more advanced use cases consider using Apache Commons Text's
55 * <a href= "https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html"> RandomStringGenerator</a>
56 * instead.
57 * </p>
58 * <p>
59 * The Apache Commons project provides <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a> dedicated to pseudo-random number generation,
60 * that may be a better choice for applications with more stringent requirements (performance and/or correctness).
61 * </p>
62 * <p>
63 * 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
64 * 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
65 * (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
66 * surrogate.
67 * </p>
68 * <p>
69 * #ThreadSafe#
70 * </p>
71 *
72 * @see #secure()
73 * @see #secureStrong()
74 * @see #insecure()
75 * @see SecureRandom#SecureRandom()
76 * @see SecureRandom#getInstanceStrong()
77 * @see ThreadLocalRandom#current()
78 * @see RandomUtils
79 * @since 1.0
80 */
81 public class RandomStringUtils {
82
83 private static final Supplier<RandomUtils> SECURE_SUPPLIER = RandomUtils::secure;
84
85 private static final RandomStringUtils INSECURE = new RandomStringUtils(RandomUtils::insecure);
86
87 private static final RandomStringUtils SECURE = new RandomStringUtils(SECURE_SUPPLIER);
88
89 private static final RandomStringUtils SECURE_STRONG = new RandomStringUtils(RandomUtils::secureStrong);
90
91 private static final char[] ALPHANUMERICAL_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
92 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
93 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1',
94 '2', '3', '4', '5', '6', '7', '8', '9' };
95
96 private static final int ASCII_0 = '0';
97 private static final int ASCII_9 = '9';
98 private static final int ASCII_A = 'A';
99 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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} < 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 }