View Javadoc
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    *      http://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.util.Random;
20  import java.util.concurrent.ThreadLocalRandom;
21  
22  /**
23   * Generates random {@link String}s.
24   *
25   * <p><b>Caveat: Instances of {@link Random}, upon which the implementation of this
26   * class relies, are not cryptographically secure.</b></p>
27   *
28   * <p>RandomStringUtils is intended for simple use cases. For more advanced
29   * use cases consider using Apache Commons Text's
30   * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html">
31   * RandomStringGenerator</a> instead.</p>
32   *
33   * <p>The Apache Commons project provides
34   * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a> dedicated to pseudo-random number generation, that may be
35   * a better choice for applications with more stringent requirements
36   * (performance and/or correctness).</p>
37   *
38   * <p>Note that <em>private high surrogate</em> characters are ignored.
39   * These are Unicode characters that fall between the values 56192 (db80)
40   * and 56319 (dbff) as we don't know how to handle them.
41   * High and low surrogates are correctly dealt with - that is if a
42   * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
43   * then it is followed by a low surrogate. If a low surrogate is chosen,
44   * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
45   * chosen high surrogate.</p>
46   *
47   * <p>#ThreadSafe#</p>
48   * @since 1.0
49   */
50  public class RandomStringUtils {
51  
52      private static ThreadLocalRandom random() {
53          return ThreadLocalRandom.current();
54      }
55  
56      // Random
57      /**
58       * Creates a random string whose length is the number of characters
59       * specified.
60       *
61       * <p>Characters will be chosen from the set of all characters.</p>
62       *
63       * @param count  the length of random string to create
64       * @return the random string
65       * @throws IllegalArgumentException if {@code count} &lt; 0.
66       */
67      public static String random(final int count) {
68          return random(count, false, false);
69      }
70  
71      /**
72       * Creates a random string whose length is the number of characters
73       * specified.
74       *
75       * <p>Characters will be chosen from the set of alpha-numeric
76       * characters as indicated by the arguments.</p>
77       *
78       * @param count  the length of random string to create
79       * @param letters  if {@code true}, generated string may include
80       *  alphabetic characters
81       * @param numbers  if {@code true}, generated string may include
82       *  numeric characters
83       * @return the random string
84       * @throws IllegalArgumentException if {@code count} &lt; 0.
85       */
86      public static String random(final int count, final boolean letters, final boolean numbers) {
87          return random(count, 0, 0, letters, numbers);
88      }
89  
90      /**
91       * Creates a random string whose length is the number of characters
92       * specified.
93       *
94       * <p>Characters will be chosen from the set of characters specified.</p>
95       *
96       * @param count  the length of random string to create
97       * @param chars  the character array containing the set of characters to use,
98       *  may be null
99       * @return the random string
100      * @throws IllegalArgumentException if {@code count} &lt; 0.
101      */
102     public static String random(final int count, final char... chars) {
103         if (chars == null) {
104             return random(count, 0, 0, false, false, null, random());
105         }
106         return random(count, 0, chars.length, false, false, chars, random());
107     }
108 
109     /**
110      * Creates a random string whose length is the number of characters
111      * specified.
112      *
113      * <p>Characters will be chosen from the set of alpha-numeric
114      * characters as indicated by the arguments.</p>
115      *
116      * @param count  the length of random string to create
117      * @param start  the position in set of chars to start at
118      * @param end  the position in set of chars to end before
119      * @param letters  if {@code true}, generated string may include
120      *  alphabetic characters
121      * @param numbers  if {@code true}, generated string may include
122      *  numeric characters
123      * @return the random string
124      * @throws IllegalArgumentException if {@code count} &lt; 0.
125      */
126     public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
127         return random(count, start, end, letters, numbers, null, random());
128     }
129 
130     /**
131      * Creates a random string based on a variety of options, using
132      * default source of randomness.
133      *
134      * <p>This method has exactly the same semantics as
135      * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
136      * instead of using an externally supplied source of randomness, it uses
137      * the internal static {@link Random} instance.</p>
138      *
139      * @param count  the length of random string to create
140      * @param start  the position in set of chars to start at
141      * @param end  the position in set of chars to end before
142      * @param letters  if {@code true}, generated string may include
143      *  alphabetic characters
144      * @param numbers  if {@code true}, generated string may include
145      *  numeric characters
146      * @param chars  the set of chars to choose randoms from.
147      *  If {@code null}, then it will use the set of all chars.
148      * @return the random string
149      * @throws ArrayIndexOutOfBoundsException if there are not
150      *  {@code (end - start) + 1} characters in the set array.
151      * @throws IllegalArgumentException if {@code count} &lt; 0.
152      */
153     public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers, final char... chars) {
154         return random(count, start, end, letters, numbers, chars, random());
155     }
156 
157     /**
158      * Creates a random string based on a variety of options, using
159      * supplied source of randomness.
160      *
161      * <p>If start and end are both {@code 0}, start and end are set
162      * to {@code ' '} and {@code 'z'}, the ASCII printable
163      * characters, will be used, unless letters and numbers are both
164      * {@code false}, in which case, start and end are set to
165      * {@code 0} and {@link Character#MAX_CODE_POINT}.
166      *
167      * <p>If set is not {@code null}, characters between start and
168      * end are chosen.</p>
169      *
170      * <p>This method accepts a user-supplied {@link Random}
171      * instance to use as a source of randomness. By seeding a single
172      * {@link Random} instance with a fixed seed and using it for each call,
173      * the same random sequence of strings can be generated repeatedly
174      * and predictably.</p>
175      *
176      * @param count  the length of random string to create
177      * @param start  the position in set of chars to start at (inclusive)
178      * @param end  the position in set of chars to end before (exclusive)
179      * @param letters  if {@code true}, generated string may include
180      *  alphabetic characters
181      * @param numbers  if {@code true}, generated string may include
182      *  numeric characters
183      * @param chars  the set of chars to choose randoms from, must not be empty.
184      *  If {@code null}, then it will use the set of all chars.
185      * @param random  a source of randomness.
186      * @return the random string
187      * @throws ArrayIndexOutOfBoundsException if there are not
188      *  {@code (end - start) + 1} characters in the set array.
189      * @throws IllegalArgumentException if {@code count} &lt; 0 or the provided chars array is empty.
190      * @since 2.0
191      */
192     public static String random(int count, int start, int end, final boolean letters, final boolean numbers,
193                                 final char[] chars, final Random random) {
194         if (count == 0) {
195             return StringUtils.EMPTY;
196         }
197         if (count < 0) {
198             throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
199         }
200         if (chars != null && chars.length == 0) {
201             throw new IllegalArgumentException("The chars array must not be empty");
202         }
203 
204         if (start == 0 && end == 0) {
205             if (chars != null) {
206                 end = chars.length;
207             } else if (!letters && !numbers) {
208                 end = Character.MAX_CODE_POINT;
209             } else {
210                 end = 'z' + 1;
211                 start = ' ';
212             }
213         } else if (end <= start) {
214             throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")");
215         }
216 
217         final int zeroDigitAscii = 48;
218         final int firstLetterAscii = 65;
219 
220         if (chars == null && (numbers && end <= zeroDigitAscii
221                 || letters && end <= firstLetterAscii)) {
222             throw new IllegalArgumentException("Parameter end (" + end + ") must be greater then (" + zeroDigitAscii + ") for generating digits " +
223                     "or greater then (" + firstLetterAscii + ") for generating letters.");
224         }
225 
226         final StringBuilder builder = new StringBuilder(count);
227         final int gap = end - start;
228 
229         while (count-- != 0) {
230             final int codePoint;
231             if (chars == null) {
232                 codePoint = random.nextInt(gap) + start;
233 
234                 switch (Character.getType(codePoint)) {
235                 case Character.UNASSIGNED:
236                 case Character.PRIVATE_USE:
237                 case Character.SURROGATE:
238                     count++;
239                     continue;
240                 }
241 
242             } else {
243                 codePoint = chars[random.nextInt(gap) + start];
244             }
245 
246             final int numberOfChars = Character.charCount(codePoint);
247             if (count == 0 && numberOfChars > 1) {
248                 count++;
249                 continue;
250             }
251 
252             if (letters && Character.isLetter(codePoint)
253                     || numbers && Character.isDigit(codePoint)
254                     || !letters && !numbers) {
255                 builder.appendCodePoint(codePoint);
256 
257                 if (numberOfChars == 2) {
258                     count--;
259                 }
260 
261             } else {
262                 count++;
263             }
264         }
265         return builder.toString();
266     }
267 
268     /**
269      * Creates a random string whose length is the number of characters
270      * specified.
271      *
272      * <p>Characters will be chosen from the set of characters
273      * specified by the string, must not be empty.
274      * If null, the set of all characters is used.</p>
275      *
276      * @param count  the length of random string to create
277      * @param chars  the String containing the set of characters to use,
278      *  may be null, but must not be empty
279      * @return the random string
280      * @throws IllegalArgumentException if {@code count} &lt; 0 or the string is empty.
281      */
282     public static String random(final int count, final String chars) {
283         if (chars == null) {
284             return random(count, 0, 0, false, false, null, random());
285         }
286         return random(count, chars.toCharArray());
287     }
288 
289     /**
290      * Creates a random string whose length is the number of characters
291      * specified.
292      *
293      * <p>Characters will be chosen from the set of Latin alphabetic
294      * characters (a-z, A-Z).</p>
295      *
296      * @param count  the length of random string to create
297      * @return the random string
298      * @throws IllegalArgumentException if {@code count} &lt; 0.
299      */
300     public static String randomAlphabetic(final int count) {
301         return random(count, true, false);
302     }
303 
304     /**
305      * Creates a random string whose length is between the inclusive minimum and
306      * the exclusive maximum.
307      *
308      * <p>Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).</p>
309      *
310      * @param minLengthInclusive the inclusive minimum length of the string to generate
311      * @param maxLengthExclusive the exclusive maximum length of the string to generate
312      * @return the random string
313      * @since 3.5
314      */
315     public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
316         return randomAlphabetic(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
317     }
318 
319     /**
320      * Creates a random string whose length is the number of characters
321      * specified.
322      *
323      * <p>Characters will be chosen from the set of Latin alphabetic
324      * characters (a-z, A-Z) and the digits 0-9.</p>
325      *
326      * @param count  the length of random string to create
327      * @return the random string
328      * @throws IllegalArgumentException if {@code count} &lt; 0.
329      */
330     public static String randomAlphanumeric(final int count) {
331         return random(count, true, true);
332     }
333 
334     /**
335      * Creates a random string whose length is between the inclusive minimum and
336      * the exclusive maximum.
337      *
338      * <p>Characters will be chosen from the set of Latin alphabetic
339      * characters (a-z, A-Z) and the digits 0-9.</p>
340      *
341      * @param minLengthInclusive the inclusive minimum length of the string to generate
342      * @param maxLengthExclusive the exclusive maximum length of the string to generate
343      * @return the random string
344      * @since 3.5
345      */
346     public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
347         return randomAlphanumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
348     }
349 
350     /**
351      * Creates a random string whose length is the number of characters
352      * specified.
353      *
354      * <p>Characters will be chosen from the set of characters whose
355      * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
356      *
357      * @param count  the length of random string to create
358      * @return the random string
359      * @throws IllegalArgumentException if {@code count} &lt; 0.
360      */
361     public static String randomAscii(final int count) {
362         return random(count, 32, 127, false, false);
363     }
364 
365     /**
366      * Creates a random string whose length is between the inclusive minimum and
367      * the exclusive maximum.
368      *
369      * <p>Characters will be chosen from the set of characters whose
370      * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
371      *
372      * @param minLengthInclusive the inclusive minimum length of the string to generate
373      * @param maxLengthExclusive the exclusive maximum length of the string to generate
374      * @return the random string
375      * @since 3.5
376      */
377     public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
378         return randomAscii(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
379     }
380 
381     /**
382      * Creates a random string whose length is the number of characters specified.
383      *
384      * <p>Characters will be chosen from the set of characters which match the POSIX [:graph:]
385      * regular expression character class. This class contains all visible ASCII characters
386      * (i.e. anything except spaces and control characters).</p>
387      *
388      * @param count  the length of random string to create
389      * @return the random string
390      * @throws IllegalArgumentException if {@code count} &lt; 0.
391      * @since 3.5
392      */
393     public static String randomGraph(final int count) {
394         return random(count, 33, 126, false, false);
395     }
396 
397     /**
398      * Creates a random string whose length is between the inclusive minimum and
399      * the exclusive maximum.
400      *
401      * <p>Characters will be chosen from the set of \p{Graph} characters.</p>
402      *
403      * @param minLengthInclusive the inclusive minimum length of the string to generate
404      * @param maxLengthExclusive the exclusive maximum length of the string to generate
405      * @return the random string
406      * @since 3.5
407      */
408     public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
409         return randomGraph(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
410     }
411 
412     /**
413      * Creates a random string whose length is the number of characters
414      * specified.
415      *
416      * <p>Characters will be chosen from the set of numeric
417      * characters.</p>
418      *
419      * @param count  the length of random string to create
420      * @return the random string
421      * @throws IllegalArgumentException if {@code count} &lt; 0.
422      */
423     public static String randomNumeric(final int count) {
424         return random(count, false, true);
425     }
426 
427     /**
428      * Creates a random string whose length is between the inclusive minimum and
429      * the exclusive maximum.
430      *
431      * <p>Characters will be chosen from the set of \p{Digit} characters.</p>
432      *
433      * @param minLengthInclusive the inclusive minimum length of the string to generate
434      * @param maxLengthExclusive the exclusive maximum length of the string to generate
435      * @return the random string
436      * @since 3.5
437      */
438     public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
439         return randomNumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
440     }
441 
442     /**
443      * Creates a random string whose length is the number of characters specified.
444      *
445      * <p>Characters will be chosen from the set of characters which match the POSIX [:print:]
446      * regular expression character class. This class includes all visible ASCII characters and spaces
447      * (i.e. anything except control characters).</p>
448      *
449      * @param count  the length of random string to create
450      * @return the random string
451      * @throws IllegalArgumentException if {@code count} &lt; 0.
452      * @since 3.5
453      */
454     public static String randomPrint(final int count) {
455         return random(count, 32, 126, false, false);
456     }
457 
458 
459     /**
460      * Creates a random string whose length is between the inclusive minimum and
461      * the exclusive maximum.
462      *
463      * <p>Characters will be chosen from the set of \p{Print} characters.</p>
464      *
465      * @param minLengthInclusive the inclusive minimum length of the string to generate
466      * @param maxLengthExclusive the exclusive maximum length of the string to generate
467      * @return the random string
468      * @since 3.5
469      */
470     public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
471         return randomPrint(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
472     }
473 
474     /**
475      * {@link RandomStringUtils} instances should NOT be constructed in
476      * standard programming. Instead, the class should be used as
477      * {@code RandomStringUtils.random(5);}.
478      *
479      * <p>This constructor is public to permit tools that require a JavaBean instance
480      * to operate.</p>
481      */
482     public RandomStringUtils() {
483     }
484 
485 }