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 */
017 package org.apache.commons.lang3;
018
019 import 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 *
032 * <p>#ThreadSafe#</p>
033 * @since 1.0
034 * @version $Id: RandomStringUtils.java 1148520 2011-07-19 20:53:23Z ggregory $
035 */
036 public class RandomStringUtils {
037
038 /**
039 * <p>Random object used by random method. This has to be not local
040 * to the random method so as to not return the same value in the
041 * same millisecond.</p>
042 */
043 private static final Random RANDOM = new Random();
044
045 /**
046 * <p>{@code RandomStringUtils} instances should NOT be constructed in
047 * standard programming. Instead, the class should be used as
048 * {@code RandomStringUtils.random(5);}.</p>
049 *
050 * <p>This constructor is public to permit tools that require a JavaBean instance
051 * to operate.</p>
052 */
053 public RandomStringUtils() {
054 super();
055 }
056
057 // Random
058 //-----------------------------------------------------------------------
059 /**
060 * <p>Creates a random string whose length is the number of characters
061 * specified.</p>
062 *
063 * <p>Characters will be chosen from the set of all characters.</p>
064 *
065 * @param count the length of random string to create
066 * @return the random string
067 */
068 public static String random(int count) {
069 return random(count, false, false);
070 }
071
072 /**
073 * <p>Creates a random string whose length is the number of characters
074 * specified.</p>
075 *
076 * <p>Characters will be chosen from the set of characters whose
077 * ASCII value is between {@code 32} and {@code 126} (inclusive).</p>
078 *
079 * @param count the length of random string to create
080 * @return the random string
081 */
082 public static String randomAscii(int count) {
083 return random(count, 32, 127, false, false);
084 }
085
086 /**
087 * <p>Creates a random string whose length is the number of characters
088 * specified.</p>
089 *
090 * <p>Characters will be chosen from the set of alphabetic
091 * characters.</p>
092 *
093 * @param count the length of random string to create
094 * @return the random string
095 */
096 public static String randomAlphabetic(int count) {
097 return random(count, true, false);
098 }
099
100 /**
101 * <p>Creates a random string whose length is the number of characters
102 * specified.</p>
103 *
104 * <p>Characters will be chosen from the set of alpha-numeric
105 * characters.</p>
106 *
107 * @param count the length of random string to create
108 * @return the random string
109 */
110 public static String randomAlphanumeric(int count) {
111 return random(count, true, true);
112 }
113
114 /**
115 * <p>Creates a random string whose length is the number of characters
116 * specified.</p>
117 *
118 * <p>Characters will be chosen from the set of numeric
119 * characters.</p>
120 *
121 * @param count the length of random string to create
122 * @return the random string
123 */
124 public static String randomNumeric(int count) {
125 return random(count, false, true);
126 }
127
128 /**
129 * <p>Creates a random string whose length is the number of characters
130 * specified.</p>
131 *
132 * <p>Characters will be chosen from the set of alpha-numeric
133 * characters as indicated by the arguments.</p>
134 *
135 * @param count the length of random string to create
136 * @param letters if {@code true}, generated string will include
137 * alphabetic characters
138 * @param numbers if {@code true}, generated string will include
139 * numeric characters
140 * @return the random string
141 */
142 public static String random(int count, boolean letters, boolean numbers) {
143 return random(count, 0, 0, letters, numbers);
144 }
145
146 /**
147 * <p>Creates a random string whose length is the number of characters
148 * specified.</p>
149 *
150 * <p>Characters will be chosen from the set of alpha-numeric
151 * characters as indicated by the arguments.</p>
152 *
153 * @param count the length of random string to create
154 * @param start the position in set of chars to start at
155 * @param end the position in set of chars to end before
156 * @param letters if {@code true}, generated string will include
157 * alphabetic characters
158 * @param numbers if {@code true}, generated string will include
159 * numeric characters
160 * @return the random string
161 */
162 public static String random(int count, int start, int end, boolean letters, boolean numbers) {
163 return random(count, start, end, letters, numbers, null, RANDOM);
164 }
165
166 /**
167 * <p>Creates a random string based on a variety of options, using
168 * default source of randomness.</p>
169 *
170 * <p>This method has exactly the same semantics as
171 * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
172 * instead of using an externally supplied source of randomness, it uses
173 * the internal static {@link Random} instance.</p>
174 *
175 * @param count the length of random string to create
176 * @param start the position in set of chars to start at
177 * @param end the position in set of chars to end before
178 * @param letters only allow letters?
179 * @param numbers only allow numbers?
180 * @param chars the set of chars to choose randoms from.
181 * If {@code null}, then it will use the set of all chars.
182 * @return the random string
183 * @throws ArrayIndexOutOfBoundsException if there are not
184 * {@code (end - start) + 1} characters in the set array.
185 */
186 public static String random(int count, int start, int end, boolean letters, boolean numbers, char... chars) {
187 return random(count, start, end, letters, numbers, chars, RANDOM);
188 }
189
190 /**
191 * <p>Creates a random string based on a variety of options, using
192 * supplied source of randomness.</p>
193 *
194 * <p>If start and end are both {@code 0}, start and end are set
195 * to {@code ' '} and {@code 'z'}, the ASCII printable
196 * characters, will be used, unless letters and numbers are both
197 * {@code false}, in which case, start and end are set to
198 * {@code 0} and {@code Integer.MAX_VALUE}.
199 *
200 * <p>If set is not {@code null}, characters between start and
201 * end are chosen.</p>
202 *
203 * <p>This method accepts a user-supplied {@link Random}
204 * instance to use as a source of randomness. By seeding a single
205 * {@link Random} instance with a fixed seed and using it for each call,
206 * the same random sequence of strings can be generated repeatedly
207 * and predictably.</p>
208 *
209 * @param count the length of random string to create
210 * @param start the position in set of chars to start at
211 * @param end the position in set of chars to end before
212 * @param letters only allow letters?
213 * @param numbers only allow numbers?
214 * @param chars the set of chars to choose randoms from.
215 * If {@code null}, then it will use the set of all chars.
216 * @param random a source of randomness.
217 * @return the random string
218 * @throws ArrayIndexOutOfBoundsException if there are not
219 * {@code (end - start) + 1} characters in the set array.
220 * @throws IllegalArgumentException if {@code count} < 0.
221 * @since 2.0
222 */
223 public static String random(int count, int start, int end, boolean letters, boolean numbers,
224 char[] chars, Random random) {
225 if (count == 0) {
226 return "";
227 } else if (count < 0) {
228 throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
229 }
230 if ((start == 0) && (end == 0)) {
231 end = 'z' + 1;
232 start = ' ';
233 if (!letters && !numbers) {
234 start = 0;
235 end = Integer.MAX_VALUE;
236 }
237 }
238
239 char[] buffer = new char[count];
240 int gap = end - start;
241
242 while (count-- != 0) {
243 char ch;
244 if (chars == null) {
245 ch = (char) (random.nextInt(gap) + start);
246 } else {
247 ch = chars[random.nextInt(gap) + start];
248 }
249 if ((letters && Character.isLetter(ch))
250 || (numbers && Character.isDigit(ch))
251 || (!letters && !numbers)) {
252 if(ch >= 56320 && ch <= 57343) {
253 if(count == 0) {
254 count++;
255 } else {
256 // low surrogate, insert high surrogate after putting it in
257 buffer[count] = ch;
258 count--;
259 buffer[count] = (char) (55296 + random.nextInt(128));
260 }
261 } else if(ch >= 55296 && ch <= 56191) {
262 if(count == 0) {
263 count++;
264 } else {
265 // high surrogate, insert low surrogate before putting it in
266 buffer[count] = (char) (56320 + random.nextInt(128));
267 count--;
268 buffer[count] = ch;
269 }
270 } else if(ch >= 56192 && ch <= 56319) {
271 // private high surrogate, no effing clue, so skip it
272 count++;
273 } else {
274 buffer[count] = ch;
275 }
276 } else {
277 count++;
278 }
279 }
280 return new String(buffer);
281 }
282
283 /**
284 * <p>Creates a random string whose length is the number of characters
285 * specified.</p>
286 *
287 * <p>Characters will be chosen from the set of characters
288 * specified.</p>
289 *
290 * @param count the length of random string to create
291 * @param chars the String containing the set of characters to use,
292 * may be null
293 * @return the random string
294 * @throws IllegalArgumentException if {@code count} < 0.
295 */
296 public static String random(int count, String chars) {
297 if (chars == null) {
298 return random(count, 0, 0, false, false, null, RANDOM);
299 }
300 return random(count, chars.toCharArray());
301 }
302
303 /**
304 * <p>Creates a random string whose length is the number of characters
305 * specified.</p>
306 *
307 * <p>Characters will be chosen from the set of characters specified.</p>
308 *
309 * @param count the length of random string to create
310 * @param chars the character array containing the set of characters to use,
311 * may be null
312 * @return the random string
313 * @throws IllegalArgumentException if {@code count} < 0.
314 */
315 public static String random(int count, char... chars) {
316 if (chars == null) {
317 return random(count, 0, 0, false, false, null, RANDOM);
318 }
319 return random(count, 0, chars.length, false, false, chars, RANDOM);
320 }
321
322 }