1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.base; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.annotations.VisibleForTesting; 21 22 import java.util.Collection; 23 import java.util.NoSuchElementException; 24 25 /** 26 * Simple static methods to be called at the start of your own methods to verify 27 * correct arguments and state. This allows constructs such as 28 * <pre> 29 * if (count <= 0) { 30 * throw new IllegalArgumentException("must be positive: " + count); 31 * }</pre> 32 * 33 * to be replaced with the more compact 34 * <pre> 35 * checkArgument(count > 0, "must be positive: %s", count);</pre> 36 * 37 * Note that the sense of the expression is inverted; with {@code Preconditions} 38 * you declare what you expect to be <i>true</i>, just as you do with an 39 * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html"> 40 * {@code assert}</a> or a JUnit {@code assertTrue} call. 41 * 42 * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a 43 * placeholder in these messages, not the full range of {@link 44 * String#format(String, Object[])} specifiers. 45 * 46 * <p>Take care not to confuse precondition checking with other similar types 47 * of checks! Precondition exceptions -- including those provided here, but also 48 * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link 49 * UnsupportedOperationException} and others -- are used to signal that the 50 * <i>calling method</i> has made an error. This tells the caller that it should 51 * not have invoked the method when it did, with the arguments it did, or 52 * perhaps ever. Postcondition or other invariant failures should not throw 53 * these types of exceptions. 54 * 55 * @author Kevin Bourrillion 56 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library) 57 */ 58 @GwtCompatible 59 public final class Preconditions { 60 private Preconditions() {} 61 62 /** 63 * Ensures the truth of an expression involving one or more parameters to the 64 * calling method. 65 * 66 * @param expression a boolean expression 67 * @throws IllegalArgumentException if {@code expression} is false 68 */ 69 public static void checkArgument(boolean expression) { 70 if (!expression) { 71 throw new IllegalArgumentException(); 72 } 73 } 74 75 /** 76 * Ensures the truth of an expression involving one or more parameters to the 77 * calling method. 78 * 79 * @param expression a boolean expression 80 * @param errorMessage the exception message to use if the check fails; will 81 * be converted to a string using {@link String#valueOf(Object)} 82 * @throws IllegalArgumentException if {@code expression} is false 83 */ 84 public static void checkArgument(boolean expression, Object errorMessage) { 85 if (!expression) { 86 throw new IllegalArgumentException(String.valueOf(errorMessage)); 87 } 88 } 89 90 /** 91 * Ensures the truth of an expression involving one or more parameters to the 92 * calling method. 93 * 94 * @param expression a boolean expression 95 * @param errorMessageTemplate a template for the exception message should the 96 * check fail. The message is formed by replacing each {@code %s} 97 * placeholder in the template with an argument. These are matched by 98 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 99 * Unmatched arguments will be appended to the formatted message in square 100 * braces. Unmatched placeholders will be left as-is. 101 * @param errorMessageArgs the arguments to be substituted into the message 102 * template. Arguments are converted to strings using 103 * {@link String#valueOf(Object)}. 104 * @throws IllegalArgumentException if {@code expression} is false 105 * @throws NullPointerException if the check fails and either {@code 106 * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let 107 * this happen) 108 */ 109 public static void checkArgument(boolean expression, 110 String errorMessageTemplate, Object... errorMessageArgs) { 111 if (!expression) { 112 throw new IllegalArgumentException( 113 format(errorMessageTemplate, errorMessageArgs)); 114 } 115 } 116 117 /** 118 * Ensures the truth of an expression involving the state of the calling 119 * instance, but not involving any parameters to the calling method. 120 * 121 * @param expression a boolean expression 122 * @throws IllegalStateException if {@code expression} is false 123 */ 124 public static void checkState(boolean expression) { 125 if (!expression) { 126 throw new IllegalStateException(); 127 } 128 } 129 130 /** 131 * Ensures the truth of an expression involving the state of the calling 132 * instance, but not involving any parameters to the calling method. 133 * 134 * @param expression a boolean expression 135 * @param errorMessage the exception message to use if the check fails; will 136 * be converted to a string using {@link String#valueOf(Object)} 137 * @throws IllegalStateException if {@code expression} is false 138 */ 139 public static void checkState(boolean expression, Object errorMessage) { 140 if (!expression) { 141 throw new IllegalStateException(String.valueOf(errorMessage)); 142 } 143 } 144 145 /** 146 * Ensures the truth of an expression involving the state of the calling 147 * instance, but not involving any parameters to the calling method. 148 * 149 * @param expression a boolean expression 150 * @param errorMessageTemplate a template for the exception message should the 151 * check fail. The message is formed by replacing each {@code %s} 152 * placeholder in the template with an argument. These are matched by 153 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 154 * Unmatched arguments will be appended to the formatted message in square 155 * braces. Unmatched placeholders will be left as-is. 156 * @param errorMessageArgs the arguments to be substituted into the message 157 * template. Arguments are converted to strings using 158 * {@link String#valueOf(Object)}. 159 * @throws IllegalStateException if {@code expression} is false 160 * @throws NullPointerException if the check fails and either {@code 161 * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let 162 * this happen) 163 */ 164 public static void checkState(boolean expression, 165 String errorMessageTemplate, Object... errorMessageArgs) { 166 if (!expression) { 167 throw new IllegalStateException( 168 format(errorMessageTemplate, errorMessageArgs)); 169 } 170 } 171 172 /** 173 * Ensures that an object reference passed as a parameter to the calling 174 * method is not null. 175 * 176 * @param reference an object reference 177 * @return the non-null reference that was validated 178 * @throws NullPointerException if {@code reference} is null 179 */ 180 public static <T> T checkNotNull(T reference) { 181 if (reference == null) { 182 throw new NullPointerException(); 183 } 184 return reference; 185 } 186 187 /** 188 * Ensures that an object reference passed as a parameter to the calling 189 * method is not null. 190 * 191 * @param reference an object reference 192 * @param errorMessage the exception message to use if the check fails; will 193 * be converted to a string using {@link String#valueOf(Object)} 194 * @return the non-null reference that was validated 195 * @throws NullPointerException if {@code reference} is null 196 */ 197 public static <T> T checkNotNull(T reference, Object errorMessage) { 198 if (reference == null) { 199 throw new NullPointerException(String.valueOf(errorMessage)); 200 } 201 return reference; 202 } 203 204 /** 205 * Ensures that an object reference passed as a parameter to the calling 206 * method is not null. 207 * 208 * @param reference an object reference 209 * @param errorMessageTemplate a template for the exception message should the 210 * check fail. The message is formed by replacing each {@code %s} 211 * placeholder in the template with an argument. These are matched by 212 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 213 * Unmatched arguments will be appended to the formatted message in square 214 * braces. Unmatched placeholders will be left as-is. 215 * @param errorMessageArgs the arguments to be substituted into the message 216 * template. Arguments are converted to strings using 217 * {@link String#valueOf(Object)}. 218 * @return the non-null reference that was validated 219 * @throws NullPointerException if {@code reference} is null 220 */ 221 public static <T> T checkNotNull(T reference, String errorMessageTemplate, 222 Object... errorMessageArgs) { 223 if (reference == null) { 224 // If either of these parameters is null, the right thing happens anyway 225 throw new NullPointerException( 226 format(errorMessageTemplate, errorMessageArgs)); 227 } 228 return reference; 229 } 230 231 /* 232 * All recent hotspots (as of 2009) *really* like to have the natural code 233 * 234 * if (guardExpression) { 235 * throw new BadException(messageExpression); 236 * } 237 * 238 * refactored so that messageExpression is moved to a separate 239 * String-returning method. 240 * 241 * if (guardExpression) { 242 * throw new BadException(badMsg(...)); 243 * } 244 * 245 * The alternative natural refactorings into void or Exception-returning 246 * methods are much slower. This is a big deal - we're talking factors of 247 * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer 248 * bug, which should be fixed, but that's a separate, big project). 249 * 250 * The coding pattern above is heavily used in java.util, e.g. in ArrayList. 251 * There is a RangeCheckMicroBenchmark in the JDK that was used to test this. 252 * 253 * But the methods in this class want to throw different exceptions, 254 * depending on the args, so it appears that this pattern is not directly 255 * applicable. But we can use the ridiculous, devious trick of throwing an 256 * exception in the middle of the construction of another exception. 257 * Hotspot is fine with that. 258 */ 259 260 /** 261 * Ensures that {@code index} specifies a valid <i>element</i> in an array, 262 * list or string of size {@code size}. An element index may range from zero, 263 * inclusive, to {@code size}, exclusive. 264 * 265 * @param index a user-supplied index identifying an element of an array, list 266 * or string 267 * @param size the size of that array, list or string 268 * @return the value of {@code index} 269 * @throws IndexOutOfBoundsException if {@code index} is negative or is not 270 * less than {@code size} 271 * @throws IllegalArgumentException if {@code size} is negative 272 */ 273 public static int checkElementIndex(int index, int size) { 274 return checkElementIndex(index, size, "index"); 275 } 276 277 /** 278 * Ensures that {@code index} specifies a valid <i>element</i> in an array, 279 * list or string of size {@code size}. An element index may range from zero, 280 * inclusive, to {@code size}, exclusive. 281 * 282 * @param index a user-supplied index identifying an element of an array, list 283 * or string 284 * @param size the size of that array, list or string 285 * @param desc the text to use to describe this index in an error message 286 * @return the value of {@code index} 287 * @throws IndexOutOfBoundsException if {@code index} is negative or is not 288 * less than {@code size} 289 * @throws IllegalArgumentException if {@code size} is negative 290 */ 291 public static int checkElementIndex(int index, int size, String desc) { 292 // Carefully optimized for execution by hotspot (explanatory comment above) 293 if (index < 0 || index >= size) { 294 throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); 295 } 296 return index; 297 } 298 299 private static String badElementIndex(int index, int size, String desc) { 300 if (index < 0) { 301 return format("%s (%s) must not be negative", desc, index); 302 } else if (size < 0) { 303 throw new IllegalArgumentException("negative size: " + size); 304 } else { // index >= size 305 return format("%s (%s) must be less than size (%s)", desc, index, size); 306 } 307 } 308 309 /** 310 * Ensures that {@code index} specifies a valid <i>position</i> in an array, 311 * list or string of size {@code size}. A position index may range from zero 312 * to {@code size}, inclusive. 313 * 314 * @param index a user-supplied index identifying a position in an array, list 315 * or string 316 * @param size the size of that array, list or string 317 * @return the value of {@code index} 318 * @throws IndexOutOfBoundsException if {@code index} is negative or is 319 * greater than {@code size} 320 * @throws IllegalArgumentException if {@code size} is negative 321 */ 322 public static int checkPositionIndex(int index, int size) { 323 return checkPositionIndex(index, size, "index"); 324 } 325 326 /** 327 * Ensures that {@code index} specifies a valid <i>position</i> in an array, 328 * list or string of size {@code size}. A position index may range from zero 329 * to {@code size}, inclusive. 330 * 331 * @param index a user-supplied index identifying a position in an array, list 332 * or string 333 * @param size the size of that array, list or string 334 * @param desc the text to use to describe this index in an error message 335 * @return the value of {@code index} 336 * @throws IndexOutOfBoundsException if {@code index} is negative or is 337 * greater than {@code size} 338 * @throws IllegalArgumentException if {@code size} is negative 339 */ 340 public static int checkPositionIndex(int index, int size, String desc) { 341 // Carefully optimized for execution by hotspot (explanatory comment above) 342 if (index < 0 || index > size) { 343 throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); 344 } 345 return index; 346 } 347 348 private static String badPositionIndex(int index, int size, String desc) { 349 if (index < 0) { 350 return format("%s (%s) must not be negative", desc, index); 351 } else if (size < 0) { 352 throw new IllegalArgumentException("negative size: " + size); 353 } else { // index > size 354 return format("%s (%s) must not be greater than size (%s)", 355 desc, index, size); 356 } 357 } 358 359 /** 360 * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> 361 * in an array, list or string of size {@code size}, and are in order. A 362 * position index may range from zero to {@code size}, inclusive. 363 * 364 * @param start a user-supplied index identifying a starting position in an 365 * array, list or string 366 * @param end a user-supplied index identifying a ending position in an array, 367 * list or string 368 * @param size the size of that array, list or string 369 * @throws IndexOutOfBoundsException if either index is negative or is 370 * greater than {@code size}, or if {@code end} is less than {@code start} 371 * @throws IllegalArgumentException if {@code size} is negative 372 */ 373 public static void checkPositionIndexes(int start, int end, int size) { 374 // Carefully optimized for execution by hotspot (explanatory comment above) 375 if (start < 0 || end < start || end > size) { 376 throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); 377 } 378 } 379 380 private static String badPositionIndexes(int start, int end, int size) { 381 if (start < 0 || start > size) { 382 return badPositionIndex(start, size, "start index"); 383 } 384 if (end < 0 || end > size) { 385 return badPositionIndex(end, size, "end index"); 386 } 387 // end < start 388 return format("end index (%s) must not be less than start index (%s)", 389 end, start); 390 } 391 392 /** 393 * Substitutes each {@code %s} in {@code template} with an argument. These 394 * are matched by position - the first {@code %s} gets {@code args[0]}, etc. 395 * If there are more arguments than placeholders, the unmatched arguments will 396 * be appended to the end of the formatted message in square braces. 397 * 398 * @param template a non-null string containing 0 or more {@code %s} 399 * placeholders. 400 * @param args the arguments to be substituted into the message 401 * template. Arguments are converted to strings using 402 * {@link String#valueOf(Object)}. Arguments can be null. 403 */ 404 @VisibleForTesting static String format(String template, Object... args) { 405 // start substituting the arguments into the '%s' placeholders 406 StringBuilder builder = new StringBuilder( 407 template.length() + 16 * args.length); 408 int templateStart = 0; 409 int i = 0; 410 while (i < args.length) { 411 int placeholderStart = template.indexOf("%s", templateStart); 412 if (placeholderStart == -1) { 413 break; 414 } 415 builder.append(template.substring(templateStart, placeholderStart)); 416 builder.append(args[i++]); 417 templateStart = placeholderStart + 2; 418 } 419 builder.append(template.substring(templateStart)); 420 421 // if we run out of placeholders, append the extra args in square braces 422 if (i < args.length) { 423 builder.append(" ["); 424 builder.append(args[i++]); 425 while (i < args.length) { 426 builder.append(", "); 427 builder.append(args[i++]); 428 } 429 builder.append("]"); 430 } 431 432 return builder.toString(); 433 } 434 } 435