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.lang; 018 019 import java.util.Random; 020 /** 021 * <p>Operations for random <code>String</code>s.</p> 022 * <p>Currently <em>private high surrogate</em> characters are ignored. 023 * These are unicode characters that fall between the values 56192 (db80) 024 * and 56319 (dbff) as we don't know how to handle them. 025 * High and low surrogates are correctly dealt with - that is if a 026 * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f) 027 * then it is followed by a low surrogate. If a low surrogate is chosen, 028 * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly 029 * chosen high surrogate. </p> 030 * 031 * <p>#ThreadSafe#</p> 032 * @author Apache Software Foundation 033 * @author <a href="mailto:steven@caswell.name">Steven Caswell</a> 034 * @author Gary Gregory 035 * @author Phil Steitz 036 * @since 1.0 037 * @version $Id: RandomStringUtils.java 1056988 2011-01-09 17:58:53Z niallp $ 038 */ 039 public 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</code> instances should NOT be constructed in 050 * standard programming. Instead, the class should be used as 051 * <code>RandomStringUtils.random(5);</code>.</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(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</code> and <code>126</code> (inclusive).</p> 081 * 082 * @param count the length of random string to create 083 * @return the random string 084 */ 085 public static String randomAscii(int count) { 086 return random(count, 32, 127, false, false); 087 } 088 089 /** 090 * <p>Creates a random string whose length is the number of characters 091 * specified.</p> 092 * 093 * <p>Characters will be chosen from the set of alphabetic 094 * characters.</p> 095 * 096 * @param count the length of random string to create 097 * @return the random string 098 */ 099 public static String randomAlphabetic(int count) { 100 return random(count, true, false); 101 } 102 103 /** 104 * <p>Creates a random string whose length is the number of characters 105 * specified.</p> 106 * 107 * <p>Characters will be chosen from the set of alpha-numeric 108 * characters.</p> 109 * 110 * @param count the length of random string to create 111 * @return the random string 112 */ 113 public static String randomAlphanumeric(int count) { 114 return random(count, true, true); 115 } 116 117 /** 118 * <p>Creates a random string whose length is the number of characters 119 * specified.</p> 120 * 121 * <p>Characters will be chosen from the set of numeric 122 * characters.</p> 123 * 124 * @param count the length of random string to create 125 * @return the random string 126 */ 127 public static String randomNumeric(int count) { 128 return random(count, false, true); 129 } 130 131 /** 132 * <p>Creates a random string whose length is the number of characters 133 * specified.</p> 134 * 135 * <p>Characters will be chosen from the set of alpha-numeric 136 * characters as indicated by the arguments.</p> 137 * 138 * @param count the length of random string to create 139 * @param letters if <code>true</code>, generated string will include 140 * alphabetic characters 141 * @param numbers if <code>true</code>, generated string will include 142 * numeric characters 143 * @return the random string 144 */ 145 public static String random(int count, boolean letters, boolean numbers) { 146 return random(count, 0, 0, letters, numbers); 147 } 148 149 /** 150 * <p>Creates a random string whose length is the number of characters 151 * specified.</p> 152 * 153 * <p>Characters will be chosen from the set of alpha-numeric 154 * characters as indicated by the arguments.</p> 155 * 156 * @param count the length of random string to create 157 * @param start the position in set of chars to start at 158 * @param end the position in set of chars to end before 159 * @param letters if <code>true</code>, generated string will include 160 * alphabetic characters 161 * @param numbers if <code>true</code>, generated string will include 162 * numeric characters 163 * @return the random string 164 */ 165 public static String random(int count, int start, int end, boolean letters, boolean numbers) { 166 return random(count, start, end, letters, numbers, null, RANDOM); 167 } 168 169 /** 170 * <p>Creates a random string based on a variety of options, using 171 * default source of randomness.</p> 172 * 173 * <p>This method has exactly the same semantics as 174 * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but 175 * instead of using an externally supplied source of randomness, it uses 176 * the internal static {@link Random} instance.</p> 177 * 178 * @param count the length of random string to create 179 * @param start the position in set of chars to start at 180 * @param end the position in set of chars to end before 181 * @param letters only allow letters? 182 * @param numbers only allow numbers? 183 * @param chars the set of chars to choose randoms from. 184 * If <code>null</code>, then it will use the set of all chars. 185 * @return the random string 186 * @throws ArrayIndexOutOfBoundsException if there are not 187 * <code>(end - start) + 1</code> characters in the set array. 188 */ 189 public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) { 190 return random(count, start, end, letters, numbers, chars, RANDOM); 191 } 192 193 /** 194 * <p>Creates a random string based on a variety of options, using 195 * supplied source of randomness.</p> 196 * 197 * <p>If start and end are both <code>0</code>, start and end are set 198 * to <code>' '</code> and <code>'z'</code>, the ASCII printable 199 * characters, will be used, unless letters and numbers are both 200 * <code>false</code>, in which case, start and end are set to 201 * <code>0</code> and <code>Integer.MAX_VALUE</code>. 202 * 203 * <p>If set is not <code>null</code>, characters between start and 204 * end are chosen.</p> 205 * 206 * <p>This method accepts a user-supplied {@link Random} 207 * instance to use as a source of randomness. By seeding a single 208 * {@link Random} instance with a fixed seed and using it for each call, 209 * the same random sequence of strings can be generated repeatedly 210 * and predictably.</p> 211 * 212 * @param count the length of random string to create 213 * @param start the position in set of chars to start at 214 * @param end the position in set of chars to end before 215 * @param letters only allow letters? 216 * @param numbers only allow numbers? 217 * @param chars the set of chars to choose randoms from. 218 * If <code>null</code>, then it will use the set of all chars. 219 * @param random a source of randomness. 220 * @return the random string 221 * @throws ArrayIndexOutOfBoundsException if there are not 222 * <code>(end - start) + 1</code> characters in the set array. 223 * @throws IllegalArgumentException if <code>count</code> < 0. 224 * @since 2.0 225 */ 226 public static String random(int count, int start, int end, boolean letters, boolean numbers, 227 char[] chars, Random random) { 228 if (count == 0) { 229 return ""; 230 } else if (count < 0) { 231 throw new IllegalArgumentException("Requested random string length " + count + " is less than 0."); 232 } 233 if ((start == 0) && (end == 0)) { 234 end = 'z' + 1; 235 start = ' '; 236 if (!letters && !numbers) { 237 start = 0; 238 end = Integer.MAX_VALUE; 239 } 240 } 241 242 char[] buffer = new char[count]; 243 int gap = end - start; 244 245 while (count-- != 0) { 246 char ch; 247 if (chars == null) { 248 ch = (char) (random.nextInt(gap) + start); 249 } else { 250 ch = chars[random.nextInt(gap) + start]; 251 } 252 if ((letters && Character.isLetter(ch)) 253 || (numbers && Character.isDigit(ch)) 254 || (!letters && !numbers)) 255 { 256 if(ch >= 56320 && ch <= 57343) { 257 if(count == 0) { 258 count++; 259 } else { 260 // low surrogate, insert high surrogate after putting it in 261 buffer[count] = ch; 262 count--; 263 buffer[count] = (char) (55296 + random.nextInt(128)); 264 } 265 } else if(ch >= 55296 && ch <= 56191) { 266 if(count == 0) { 267 count++; 268 } else { 269 // high surrogate, insert low surrogate before putting it in 270 buffer[count] = (char) (56320 + random.nextInt(128)); 271 count--; 272 buffer[count] = ch; 273 } 274 } else if(ch >= 56192 && ch <= 56319) { 275 // private high surrogate, no effing clue, so skip it 276 count++; 277 } else { 278 buffer[count] = ch; 279 } 280 } else { 281 count++; 282 } 283 } 284 return new String(buffer); 285 } 286 287 /** 288 * <p>Creates a random string whose length is the number of characters 289 * specified.</p> 290 * 291 * <p>Characters will be chosen from the set of characters 292 * specified.</p> 293 * 294 * @param count the length of random string to create 295 * @param chars the String containing the set of characters to use, 296 * may be null 297 * @return the random string 298 * @throws IllegalArgumentException if <code>count</code> < 0. 299 */ 300 public static String random(int count, String chars) { 301 if (chars == null) { 302 return random(count, 0, 0, false, false, null, RANDOM); 303 } 304 return random(count, chars.toCharArray()); 305 } 306 307 /** 308 * <p>Creates a random string whose length is the number of characters 309 * specified.</p> 310 * 311 * <p>Characters will be chosen from the set of characters specified.</p> 312 * 313 * @param count the length of random string to create 314 * @param chars the character array containing the set of characters to use, 315 * may be null 316 * @return the random string 317 * @throws IllegalArgumentException if <code>count</code> < 0. 318 */ 319 public static String random(int count, char[] chars) { 320 if (chars == null) { 321 return random(count, 0, 0, false, false, null, RANDOM); 322 } 323 return random(count, 0, chars.length, false, false, chars, RANDOM); 324 } 325 326 }