001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.util.Random;
020import java.util.concurrent.ThreadLocalRandom;
021
022/**
023 * Generates random {@link String}s.
024 *
025 * <p><b>Caveat: Instances of {@link Random}, upon which the implementation of this
026 * class relies, are not cryptographically secure.</b></p>
027 *
028 * <p>RandomStringUtils is intended for simple use cases. For more advanced
029 * use cases consider using Apache Commons Text's
030 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html">
031 * RandomStringGenerator</a> instead.</p>
032 *
033 * <p>The Apache Commons project provides
034 * <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a> dedicated to pseudo-random number generation, that may be
035 * a better choice for applications with more stringent requirements
036 * (performance and/or correctness).</p>
037 *
038 * <p>Note that <em>private high surrogate</em> characters are ignored.
039 * These are Unicode characters that fall between the values 56192 (db80)
040 * and 56319 (dbff) as we don't know how to handle them.
041 * High and low surrogates are correctly dealt with - that is if a
042 * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
043 * then it is followed by a low surrogate. If a low surrogate is chosen,
044 * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
045 * chosen high surrogate.</p>
046 *
047 * <p>#ThreadSafe#</p>
048 * @since 1.0
049 */
050public class RandomStringUtils {
051
052    private static ThreadLocalRandom random() {
053        return ThreadLocalRandom.current();
054    }
055
056    // Random
057    /**
058     * Creates a random string whose length is the number of characters
059     * specified.
060     *
061     * <p>Characters will be chosen from the set of all characters.</p>
062     *
063     * @param count  the length of random string to create
064     * @return the random string
065     * @throws IllegalArgumentException if {@code count} &lt; 0.
066     */
067    public static String random(final int count) {
068        return random(count, false, false);
069    }
070
071    /**
072     * Creates a random string whose length is the number of characters
073     * specified.
074     *
075     * <p>Characters will be chosen from the set of alpha-numeric
076     * characters as indicated by the arguments.</p>
077     *
078     * @param count  the length of random string to create
079     * @param letters  if {@code true}, generated string may include
080     *  alphabetic characters
081     * @param numbers  if {@code true}, generated string may include
082     *  numeric characters
083     * @return the random string
084     * @throws IllegalArgumentException if {@code count} &lt; 0.
085     */
086    public static String random(final int count, final boolean letters, final boolean numbers) {
087        return random(count, 0, 0, letters, numbers);
088    }
089
090    /**
091     * Creates a random string whose length is the number of characters
092     * specified.
093     *
094     * <p>Characters will be chosen from the set of characters specified.</p>
095     *
096     * @param count  the length of random string to create
097     * @param chars  the character array containing the set of characters to use,
098     *  may be null
099     * @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}