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;
020
021/**
022 * <p>Operations for random {@code String}s.</p>
023 * <p>Currently <em>private high surrogate</em> characters are ignored.
024 * These are Unicode characters that fall between the values 56192 (db80)
025 * and 56319 (dbff) as we don't know how to handle them.
026 * High and low surrogates are correctly dealt with - that is if a
027 * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
028 * then it is followed by a low surrogate. If a low surrogate is chosen,
029 * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
030 * chosen high surrogate.</p>
031 * <p>RandomStringUtils is intended for simple use cases. For more advanced
032 * use cases consider using commons-text
033 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html">
034 * RandomStringGenerator</a> instead.</p>
035 *
036 * <p>#ThreadSafe#</p>
037 * @since 1.0
038 */
039public class RandomStringUtils {
040
041    /**
042     * <p>Random object used by random method. This has to be not local
043     * to the random method so as to not return the same value in the
044     * same millisecond.</p>
045     */
046    private static final Random RANDOM = new Random();
047
048    /**
049     * <p>{@code RandomStringUtils} instances should NOT be constructed in
050     * standard programming. Instead, the class should be used as
051     * {@code RandomStringUtils.random(5);}.</p>
052     *
053     * <p>This constructor is public to permit tools that require a JavaBean instance
054     * to operate.</p>
055     */
056    public RandomStringUtils() {
057      super();
058    }
059
060    // Random
061    //-----------------------------------------------------------------------
062    /**
063     * <p>Creates a random string whose length is the number of characters
064     * specified.</p>
065     *
066     * <p>Characters will be chosen from the set of all characters.</p>
067     *
068     * @param count  the length of random string to create
069     * @return the random string
070     */
071    public static String random(final int count) {
072        return random(count, false, false);
073    }
074
075    /**
076     * <p>Creates a random string whose length is the number of characters
077     * specified.</p>
078     *
079     * <p>Characters will be chosen from the set of characters whose
080     * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
081     *
082     * @param count  the length of random string to create
083     * @return the random string
084     */
085    public static String randomAscii(final int count) {
086        return random(count, 32, 127, false, false);
087    }
088
089    /**
090     * <p>Creates a random string whose length is between the inclusive minimum and
091     * the exclusive maximum.</p>
092     *
093     * <p>Characters will be chosen from the set of characters whose
094     * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
095     *
096     * @param minLengthInclusive the inclusive minimum length of the string to generate
097     * @param maxLengthExclusive the exclusive maximum length of the string to generate
098     * @return the random string
099     * @since 3.5
100     */
101    public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
102        return randomAscii(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
103    }
104
105    /**
106     * <p>Creates a random string whose length is the number of characters
107     * specified.</p>
108     *
109     * <p>Characters will be chosen from the set of Latin alphabetic
110     * characters (a-z, A-Z).</p>
111     *
112     * @param count  the length of random string to create
113     * @return the random string
114     */
115    public static String randomAlphabetic(final int count) {
116        return random(count, true, false);
117    }
118
119    /**
120     * <p>Creates a random string whose length is between the inclusive minimum and
121     * the exclusive maximum.</p>
122     *
123     * <p>Characters will be chosen from the set of Latin alphabetic characters (a-z, A-Z).</p>
124     *
125     * @param minLengthInclusive the inclusive minimum length of the string to generate
126     * @param maxLengthExclusive the exclusive maximum length of the string to generate
127     * @return the random string
128     * @since 3.5
129     */
130    public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
131        return randomAlphabetic(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
132    }
133
134    /**
135     * <p>Creates a random string whose length is the number of characters
136     * specified.</p>
137     *
138     * <p>Characters will be chosen from the set of Latin alphabetic
139     * characters (a-z, A-Z) and the digits 0-9.</p>
140     *
141     * @param count  the length of random string to create
142     * @return the random string
143     */
144    public static String randomAlphanumeric(final int count) {
145        return random(count, true, true);
146    }
147
148    /**
149     * <p>Creates a random string whose length is between the inclusive minimum and
150     * the exclusive maximum.</p>
151     *
152     * <p>Characters will be chosen from the set of Latin alphabetic
153     * characters (a-z, A-Z) and the digits 0-9.</p>
154     *
155     * @param minLengthInclusive the inclusive minimum length of the string to generate
156     * @param maxLengthExclusive the exclusive maximum length of the string to generate
157     * @return the random string
158     * @since 3.5
159     */
160    public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
161        return randomAlphanumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
162    }
163
164    /**
165     * <p>Creates a random string whose length is the number of characters specified.</p>
166     *
167     * <p>Characters will be chosen from the set of characters which match the POSIX [:graph:]
168     * regular expression character class. This class contains all visible ASCII characters
169     * (i.e. anything except spaces and control characters).</p>
170     *
171     * @param count  the length of random string to create
172     * @return the random string
173     * @since 3.5
174     */
175    public static String randomGraph(final int count) {
176        return random(count, 33, 126, false, false);
177    }
178
179    /**
180     * <p>Creates a random string whose length is between the inclusive minimum and
181     * the exclusive maximum.</p>
182     *
183     * <p>Characters will be chosen from the set of \p{Graph} characters.</p>
184     *
185     * @param minLengthInclusive the inclusive minimum length of the string to generate
186     * @param maxLengthExclusive the exclusive maximum length of the string to generate
187     * @return the random string
188     * @since 3.5
189     */
190    public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
191        return randomGraph(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
192    }
193
194    /**
195     * <p>Creates a random string whose length is the number of characters
196     * specified.</p>
197     *
198     * <p>Characters will be chosen from the set of numeric
199     * characters.</p>
200     *
201     * @param count  the length of random string to create
202     * @return the random string
203     */
204    public static String randomNumeric(final int count) {
205        return random(count, false, true);
206    }
207
208    /**
209     * <p>Creates a random string whose length is between the inclusive minimum and
210     * the exclusive maximum.</p>
211     *
212     * <p>Characters will be chosen from the set of \p{Digit} characters.</p>
213     *
214     * @param minLengthInclusive the inclusive minimum length of the string to generate
215     * @param maxLengthExclusive the exclusive maximum length of the string to generate
216     * @return the random string
217     * @since 3.5
218     */
219    public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
220        return randomNumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
221    }
222
223    /**
224     * <p>Creates a random string whose length is the number of characters specified.</p>
225     *
226     * <p>Characters will be chosen from the set of characters which match the POSIX [:print:]
227     * regular expression character class. This class includes all visible ASCII characters and spaces
228     * (i.e. anything except control characters).</p>
229     *
230     * @param count  the length of random string to create
231     * @return the random string
232     * @since 3.5
233     */
234    public static String randomPrint(final int count) {
235        return random(count, 32, 126, false, false);
236    }
237
238    /**
239     * <p>Creates a random string whose length is between the inclusive minimum and
240     * the exclusive maximum.</p>
241     *
242     * <p>Characters will be chosen from the set of \p{Print} characters.</p>
243     *
244     * @param minLengthInclusive the inclusive minimum length of the string to generate
245     * @param maxLengthExclusive the exclusive maximum length of the string to generate
246     * @return the random string
247     * @since 3.5
248     */
249    public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
250        return randomPrint(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
251    }
252
253    /**
254     * <p>Creates a random string whose length is the number of characters
255     * specified.</p>
256     *
257     * <p>Characters will be chosen from the set of alpha-numeric
258     * characters as indicated by the arguments.</p>
259     *
260     * @param count  the length of random string to create
261     * @param letters  if {@code true}, generated string may include
262     *  alphabetic characters
263     * @param numbers  if {@code true}, generated string may include
264     *  numeric characters
265     * @return the random string
266     */
267    public static String random(final int count, final boolean letters, final boolean numbers) {
268        return random(count, 0, 0, letters, numbers);
269    }
270
271    /**
272     * <p>Creates a random string whose length is the number of characters
273     * specified.</p>
274     *
275     * <p>Characters will be chosen from the set of alpha-numeric
276     * characters as indicated by the arguments.</p>
277     *
278     * @param count  the length of random string to create
279     * @param start  the position in set of chars to start at
280     * @param end  the position in set of chars to end before
281     * @param letters  if {@code true}, generated string may include
282     *  alphabetic characters
283     * @param numbers  if {@code true}, generated string may include
284     *  numeric characters
285     * @return the random string
286     */
287    public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
288        return random(count, start, end, letters, numbers, null, RANDOM);
289    }
290
291    /**
292     * <p>Creates a random string based on a variety of options, using
293     * default source of randomness.</p>
294     *
295     * <p>This method has exactly the same semantics as
296     * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
297     * instead of using an externally supplied source of randomness, it uses
298     * the internal static {@link Random} instance.</p>
299     *
300     * @param count  the length of random string to create
301     * @param start  the position in set of chars to start at
302     * @param end  the position in set of chars to end before
303     * @param letters  only allow letters?
304     * @param numbers  only allow numbers?
305     * @param chars  the set of chars to choose randoms from.
306     *  If {@code null}, then it will use the set of all chars.
307     * @return the random string
308     * @throws ArrayIndexOutOfBoundsException if there are not
309     *  {@code (end - start) + 1} characters in the set array.
310     */
311    public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers, final char... chars) {
312        return random(count, start, end, letters, numbers, chars, RANDOM);
313    }
314
315    /**
316     * <p>Creates a random string based on a variety of options, using
317     * supplied source of randomness.</p>
318     *
319     * <p>If start and end are both {@code 0}, start and end are set
320     * to {@code ' '} and {@code 'z'}, the ASCII printable
321     * characters, will be used, unless letters and numbers are both
322     * {@code false}, in which case, start and end are set to
323     * {@code 0} and {@link Character#MAX_CODE_POINT}.
324     *
325     * <p>If set is not {@code null}, characters between start and
326     * end are chosen.</p>
327     *
328     * <p>This method accepts a user-supplied {@link Random}
329     * instance to use as a source of randomness. By seeding a single
330     * {@link Random} instance with a fixed seed and using it for each call,
331     * the same random sequence of strings can be generated repeatedly
332     * and predictably.</p>
333     *
334     * @param count  the length of random string to create
335     * @param start  the position in set of chars to start at (inclusive)
336     * @param end  the position in set of chars to end before (exclusive)
337     * @param letters  only allow letters?
338     * @param numbers  only allow numbers?
339     * @param chars  the set of chars to choose randoms from, must not be empty.
340     *  If {@code null}, then it will use the set of all chars.
341     * @param random  a source of randomness.
342     * @return the random string
343     * @throws ArrayIndexOutOfBoundsException if there are not
344     *  {@code (end - start) + 1} characters in the set array.
345     * @throws IllegalArgumentException if {@code count} &lt; 0 or the provided chars array is empty.
346     * @since 2.0
347     */
348    public static String random(int count, int start, int end, final boolean letters, final boolean numbers,
349                                final char[] chars, final Random random) {
350        if (count == 0) {
351            return StringUtils.EMPTY;
352        } else if (count < 0) {
353            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
354        }
355        if (chars != null && chars.length == 0) {
356            throw new IllegalArgumentException("The chars array must not be empty");
357        }
358
359        if (start == 0 && end == 0) {
360            if (chars != null) {
361                end = chars.length;
362            } else {
363                if (!letters && !numbers) {
364                    end = Character.MAX_CODE_POINT;
365                } else {
366                    end = 'z' + 1;
367                    start = ' ';
368                }
369            }
370        } else {
371            if (end <= start) {
372                throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")");
373            }
374        }
375
376        final int zero_digit_ascii = 48;
377        final int first_letter_ascii = 65;
378
379        if (chars == null && (numbers && end <= zero_digit_ascii
380                || letters && end <= first_letter_ascii)) {
381            throw new IllegalArgumentException("Parameter end (" + end + ") must be greater then (" + zero_digit_ascii + ") for generating digits " +
382                    "or greater then (" + first_letter_ascii + ") for generating letters.");
383        }
384
385        final StringBuilder builder = new StringBuilder(count);
386        final int gap = end - start;
387
388        while (count-- != 0) {
389            int codePoint;
390            if (chars == null) {
391                codePoint = random.nextInt(gap) + start;
392
393                switch (Character.getType(codePoint)) {
394                case Character.UNASSIGNED:
395                case Character.PRIVATE_USE:
396                case Character.SURROGATE:
397                    count++;
398                    continue;
399                }
400
401            } else {
402                codePoint = chars[random.nextInt(gap) + start];
403            }
404
405            final int numberOfChars = Character.charCount(codePoint);
406            if (count == 0 && numberOfChars > 1) {
407                count++;
408                continue;
409            }
410
411            if (letters && Character.isLetter(codePoint)
412                    || numbers && Character.isDigit(codePoint)
413                    || !letters && !numbers) {
414                builder.appendCodePoint(codePoint);
415
416                if (numberOfChars == 2) {
417                    count--;
418                }
419
420            } else {
421                count++;
422            }
423        }
424        return builder.toString();
425    }
426
427
428    /**
429     * <p>Creates a random string whose length is the number of characters
430     * specified.</p>
431     *
432     * <p>Characters will be chosen from the set of characters
433     * specified by the string, must not be empty.
434     * If null, the set of all characters is used.</p>
435     *
436     * @param count  the length of random string to create
437     * @param chars  the String containing the set of characters to use,
438     *  may be null, but must not be empty
439     * @return the random string
440     * @throws IllegalArgumentException if {@code count} &lt; 0 or the string is empty.
441     */
442    public static String random(final int count, final String chars) {
443        if (chars == null) {
444            return random(count, 0, 0, false, false, null, RANDOM);
445        }
446        return random(count, chars.toCharArray());
447    }
448
449    /**
450     * <p>Creates a random string whose length is the number of characters
451     * specified.</p>
452     *
453     * <p>Characters will be chosen from the set of characters specified.</p>
454     *
455     * @param count  the length of random string to create
456     * @param chars  the character array containing the set of characters to use,
457     *  may be null
458     * @return the random string
459     * @throws IllegalArgumentException if {@code count} &lt; 0.
460     */
461    public static String random(final int count, final char... chars) {
462        if (chars == null) {
463            return random(count, 0, 0, false, false, null, RANDOM);
464        }
465        return random(count, 0, chars.length, false, false, chars, RANDOM);
466    }
467
468}