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 * @version $Id: RandomStringUtils.java 1532684 2013-10-16 08:28:42Z bayard $ 035 */ 036public 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(final 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(final 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(final 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(final 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(final 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 may include 137 * alphabetic characters 138 * @param numbers if {@code true}, generated string may include 139 * numeric characters 140 * @return the random string 141 */ 142 public static String random(final int count, final boolean letters, final 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 may include 157 * alphabetic characters 158 * @param numbers if {@code true}, generated string may include 159 * numeric characters 160 * @return the random string 161 */ 162 public static String random(final int count, final int start, final int end, final boolean letters, final 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(final int count, final int start, final int end, final boolean letters, final boolean numbers, final 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, must not be empty. 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 or the provided chars array is empty. 221 * @since 2.0 222 */ 223 public static String random(int count, int start, int end, final boolean letters, final boolean numbers, 224 final char[] chars, final 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 (chars != null && chars.length == 0) { 231 throw new IllegalArgumentException("The chars array must not be empty"); 232 } 233 234 if (start == 0 && end == 0) { 235 if (chars != null) { 236 end = chars.length; 237 } else { 238 if (!letters && !numbers) { 239 end = Integer.MAX_VALUE; 240 } else { 241 end = 'z' + 1; 242 start = ' '; 243 } 244 } 245 } else { 246 if (end <= start) { 247 throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")"); 248 } 249 } 250 251 final char[] buffer = new char[count]; 252 final int gap = end - start; 253 254 while (count-- != 0) { 255 char ch; 256 if (chars == null) { 257 ch = (char) (random.nextInt(gap) + start); 258 } else { 259 ch = chars[random.nextInt(gap) + start]; 260 } 261 if (letters && Character.isLetter(ch) 262 || numbers && Character.isDigit(ch) 263 || !letters && !numbers) { 264 if(ch >= 56320 && ch <= 57343) { 265 if(count == 0) { 266 count++; 267 } else { 268 // low surrogate, insert high surrogate after putting it in 269 buffer[count] = ch; 270 count--; 271 buffer[count] = (char) (55296 + random.nextInt(128)); 272 } 273 } else if(ch >= 55296 && ch <= 56191) { 274 if(count == 0) { 275 count++; 276 } else { 277 // high surrogate, insert low surrogate before putting it in 278 buffer[count] = (char) (56320 + random.nextInt(128)); 279 count--; 280 buffer[count] = ch; 281 } 282 } else if(ch >= 56192 && ch <= 56319) { 283 // private high surrogate, no effing clue, so skip it 284 count++; 285 } else { 286 buffer[count] = ch; 287 } 288 } else { 289 count++; 290 } 291 } 292 return new String(buffer); 293 } 294 295 /** 296 * <p>Creates a random string whose length is the number of characters 297 * specified.</p> 298 * 299 * <p>Characters will be chosen from the set of characters 300 * specified by the string, must not be empty. 301 * If null, the set of all characters is used.</p> 302 * 303 * @param count the length of random string to create 304 * @param chars the String containing the set of characters to use, 305 * may be null, but must not be empty 306 * @return the random string 307 * @throws IllegalArgumentException if {@code count} < 0 or the string is empty. 308 */ 309 public static String random(final int count, final String chars) { 310 if (chars == null) { 311 return random(count, 0, 0, false, false, null, RANDOM); 312 } 313 return random(count, chars.toCharArray()); 314 } 315 316 /** 317 * <p>Creates a random string whose length is the number of characters 318 * specified.</p> 319 * 320 * <p>Characters will be chosen from the set of characters specified.</p> 321 * 322 * @param count the length of random string to create 323 * @param chars the character array containing the set of characters to use, 324 * may be null 325 * @return the random string 326 * @throws IllegalArgumentException if {@code count} < 0. 327 */ 328 public static String random(final int count, final char... chars) { 329 if (chars == null) { 330 return random(count, 0, 0, false, false, null, RANDOM); 331 } 332 return random(count, 0, chars.length, false, false, chars, RANDOM); 333 } 334 335}