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