001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.base; 018 019import com.google.common.annotations.GwtCompatible; 020import com.google.common.annotations.VisibleForTesting; 021 022import java.util.NoSuchElementException; 023 024import javax.annotation.Nullable; 025 026/** 027 * Simple static methods to be called at the start of your own methods to verify 028 * correct arguments and state. This allows constructs such as 029 * 030 * <pre> {@code 031 * if (count <= 0) { 032 * throw new IllegalArgumentException("must be positive: " + count); 033 * }}</pre> 034 * 035 * <p>to be replaced with the more compact 036 * <pre> {@code 037 * checkArgument(count > 0, "must be positive: %s", count);}</pre> 038 * 039 * <p>Note that the sense of the expression is inverted; with {@code Preconditions} 040 * you declare what you expect to be <i>true</i>, just as you do with an 041 * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html"> 042 * {@code assert}</a> or a JUnit {@code assertTrue} call. 043 * 044 * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a 045 * placeholder in these messages, not the full range of {@link 046 * String#format(String, Object[])} specifiers. 047 * 048 * <p>Take care not to confuse precondition checking with other similar types 049 * of checks! Precondition exceptions -- including those provided here, but also 050 * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link 051 * UnsupportedOperationException} and others -- are used to signal that the 052 * <i>calling method</i> has made an error. This tells the caller that it should 053 * not have invoked the method when it did, with the arguments it did, or 054 * perhaps ever. Postcondition or other invariant failures should not throw 055 * these types of exceptions. 056 * 057 * <p>See the Guava User Guide on <a href= 058 * "http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained"> 059 * using {@code Preconditions}</a>. 060 * 061 * @author Kevin Bourrillion 062 * @since 2.0 (imported from Google Collections Library) 063 */ 064@GwtCompatible 065public final class Preconditions { 066 private Preconditions() {} 067 068 /** 069 * Ensures the truth of an expression involving one or more parameters to the 070 * calling method. 071 * 072 * @param expression a boolean expression 073 * @throws IllegalArgumentException if {@code expression} is false 074 */ 075 public static void checkArgument(boolean expression) { 076 if (!expression) { 077 throw new IllegalArgumentException(); 078 } 079 } 080 081 /** 082 * Ensures the truth of an expression involving one or more parameters to the 083 * calling method. 084 * 085 * @param expression a boolean expression 086 * @param errorMessage the exception message to use if the check fails; will 087 * be converted to a string using {@link String#valueOf(Object)} 088 * @throws IllegalArgumentException if {@code expression} is false 089 */ 090 public static void checkArgument( 091 boolean expression, @Nullable Object errorMessage) { 092 if (!expression) { 093 throw new IllegalArgumentException(String.valueOf(errorMessage)); 094 } 095 } 096 097 /** 098 * Ensures the truth of an expression involving one or more parameters to the 099 * calling method. 100 * 101 * @param expression a boolean expression 102 * @param errorMessageTemplate a template for the exception message should the 103 * check fail. The message is formed by replacing each {@code %s} 104 * placeholder in the template with an argument. These are matched by 105 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 106 * Unmatched arguments will be appended to the formatted message in square 107 * braces. Unmatched placeholders will be left as-is. 108 * @param errorMessageArgs the arguments to be substituted into the message 109 * template. Arguments are converted to strings using 110 * {@link String#valueOf(Object)}. 111 * @throws IllegalArgumentException if {@code expression} is false 112 * @throws NullPointerException if the check fails and either {@code 113 * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let 114 * this happen) 115 */ 116 public static void checkArgument(boolean expression, 117 @Nullable String errorMessageTemplate, 118 @Nullable Object... errorMessageArgs) { 119 if (!expression) { 120 throw new IllegalArgumentException( 121 format(errorMessageTemplate, errorMessageArgs)); 122 } 123 } 124 125 /** 126 * Ensures the truth of an expression involving the state of the calling 127 * instance, but not involving any parameters to the calling method. 128 * 129 * @param expression a boolean expression 130 * @throws IllegalStateException if {@code expression} is false 131 */ 132 public static void checkState(boolean expression) { 133 if (!expression) { 134 throw new IllegalStateException(); 135 } 136 } 137 138 /** 139 * Ensures the truth of an expression involving the state of the calling 140 * instance, but not involving any parameters to the calling method. 141 * 142 * @param expression a boolean expression 143 * @param errorMessage the exception message to use if the check fails; will 144 * be converted to a string using {@link String#valueOf(Object)} 145 * @throws IllegalStateException if {@code expression} is false 146 */ 147 public static void checkState( 148 boolean expression, @Nullable Object errorMessage) { 149 if (!expression) { 150 throw new IllegalStateException(String.valueOf(errorMessage)); 151 } 152 } 153 154 /** 155 * Ensures the truth of an expression involving the state of the calling 156 * instance, but not involving any parameters to the calling method. 157 * 158 * @param expression a boolean expression 159 * @param errorMessageTemplate a template for the exception message should the 160 * check fail. The message is formed by replacing each {@code %s} 161 * placeholder in the template with an argument. These are matched by 162 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 163 * Unmatched arguments will be appended to the formatted message in square 164 * braces. Unmatched placeholders will be left as-is. 165 * @param errorMessageArgs the arguments to be substituted into the message 166 * template. Arguments are converted to strings using 167 * {@link String#valueOf(Object)}. 168 * @throws IllegalStateException if {@code expression} is false 169 * @throws NullPointerException if the check fails and either {@code 170 * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let 171 * this happen) 172 */ 173 public static void checkState(boolean expression, 174 @Nullable String errorMessageTemplate, 175 @Nullable Object... errorMessageArgs) { 176 if (!expression) { 177 throw new IllegalStateException( 178 format(errorMessageTemplate, errorMessageArgs)); 179 } 180 } 181 182 /** 183 * Ensures that an object reference passed as a parameter to the calling 184 * method is not null. 185 * 186 * @param reference an object reference 187 * @return the non-null reference that was validated 188 * @throws NullPointerException if {@code reference} is null 189 */ 190 public static <T> T checkNotNull(T reference) { 191 if (reference == null) { 192 throw new NullPointerException(); 193 } 194 return reference; 195 } 196 197 /** 198 * Ensures that an object reference passed as a parameter to the calling 199 * method is not null. 200 * 201 * @param reference an object reference 202 * @param errorMessage the exception message to use if the check fails; will 203 * be converted to a string using {@link String#valueOf(Object)} 204 * @return the non-null reference that was validated 205 * @throws NullPointerException if {@code reference} is null 206 */ 207 public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) { 208 if (reference == null) { 209 throw new NullPointerException(String.valueOf(errorMessage)); 210 } 211 return reference; 212 } 213 214 /** 215 * Ensures that an object reference passed as a parameter to the calling 216 * method is not null. 217 * 218 * @param reference an object reference 219 * @param errorMessageTemplate a template for the exception message should the 220 * check fail. The message is formed by replacing each {@code %s} 221 * placeholder in the template with an argument. These are matched by 222 * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. 223 * Unmatched arguments will be appended to the formatted message in square 224 * braces. Unmatched placeholders will be left as-is. 225 * @param errorMessageArgs the arguments to be substituted into the message 226 * template. Arguments are converted to strings using 227 * {@link String#valueOf(Object)}. 228 * @return the non-null reference that was validated 229 * @throws NullPointerException if {@code reference} is null 230 */ 231 public static <T> T checkNotNull(T reference, 232 @Nullable String errorMessageTemplate, 233 @Nullable Object... errorMessageArgs) { 234 if (reference == null) { 235 // If either of these parameters is null, the right thing happens anyway 236 throw new NullPointerException( 237 format(errorMessageTemplate, errorMessageArgs)); 238 } 239 return reference; 240 } 241 242 /* 243 * All recent hotspots (as of 2009) *really* like to have the natural code 244 * 245 * if (guardExpression) { 246 * throw new BadException(messageExpression); 247 * } 248 * 249 * refactored so that messageExpression is moved to a separate 250 * String-returning method. 251 * 252 * if (guardExpression) { 253 * throw new BadException(badMsg(...)); 254 * } 255 * 256 * The alternative natural refactorings into void or Exception-returning 257 * methods are much slower. This is a big deal - we're talking factors of 258 * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer 259 * bug, which should be fixed, but that's a separate, big project). 260 * 261 * The coding pattern above is heavily used in java.util, e.g. in ArrayList. 262 * There is a RangeCheckMicroBenchmark in the JDK that was used to test this. 263 * 264 * But the methods in this class want to throw different exceptions, 265 * depending on the args, so it appears that this pattern is not directly 266 * applicable. But we can use the ridiculous, devious trick of throwing an 267 * exception in the middle of the construction of another exception. 268 * Hotspot is fine with that. 269 */ 270 271 /** 272 * Ensures that {@code index} specifies a valid <i>element</i> in an array, 273 * list or string of size {@code size}. An element index may range from zero, 274 * inclusive, to {@code size}, exclusive. 275 * 276 * @param index a user-supplied index identifying an element of an array, list 277 * or string 278 * @param size the size of that array, list or string 279 * @return the value of {@code index} 280 * @throws IndexOutOfBoundsException if {@code index} is negative or is not 281 * less than {@code size} 282 * @throws IllegalArgumentException if {@code size} is negative 283 */ 284 public static int checkElementIndex(int index, int size) { 285 return checkElementIndex(index, size, "index"); 286 } 287 288 /** 289 * Ensures that {@code index} specifies a valid <i>element</i> in an array, 290 * list or string of size {@code size}. An element index may range from zero, 291 * inclusive, to {@code size}, exclusive. 292 * 293 * @param index a user-supplied index identifying an element of an array, list 294 * or string 295 * @param size the size of that array, list or string 296 * @param desc the text to use to describe this index in an error message 297 * @return the value of {@code index} 298 * @throws IndexOutOfBoundsException if {@code index} is negative or is not 299 * less than {@code size} 300 * @throws IllegalArgumentException if {@code size} is negative 301 */ 302 public static int checkElementIndex( 303 int index, int size, @Nullable String desc) { 304 // Carefully optimized for execution by hotspot (explanatory comment above) 305 if (index < 0 || index >= size) { 306 throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); 307 } 308 return index; 309 } 310 311 private static String badElementIndex(int index, int size, String desc) { 312 if (index < 0) { 313 return format("%s (%s) must not be negative", desc, index); 314 } else if (size < 0) { 315 throw new IllegalArgumentException("negative size: " + size); 316 } else { // index >= size 317 return format("%s (%s) must be less than size (%s)", desc, index, size); 318 } 319 } 320 321 /** 322 * Ensures that {@code index} specifies a valid <i>position</i> in an array, 323 * list or string of size {@code size}. A position index may range from zero 324 * to {@code size}, inclusive. 325 * 326 * @param index a user-supplied index identifying a position in an array, list 327 * or string 328 * @param size the size of that array, list or string 329 * @return the value of {@code index} 330 * @throws IndexOutOfBoundsException if {@code index} is negative or is 331 * greater than {@code size} 332 * @throws IllegalArgumentException if {@code size} is negative 333 */ 334 public static int checkPositionIndex(int index, int size) { 335 return checkPositionIndex(index, size, "index"); 336 } 337 338 /** 339 * Ensures that {@code index} specifies a valid <i>position</i> in an array, 340 * list or string of size {@code size}. A position index may range from zero 341 * to {@code size}, inclusive. 342 * 343 * @param index a user-supplied index identifying a position in an array, list 344 * or string 345 * @param size the size of that array, list or string 346 * @param desc the text to use to describe this index in an error message 347 * @return the value of {@code index} 348 * @throws IndexOutOfBoundsException if {@code index} is negative or is 349 * greater than {@code size} 350 * @throws IllegalArgumentException if {@code size} is negative 351 */ 352 public static int checkPositionIndex( 353 int index, int size, @Nullable String desc) { 354 // Carefully optimized for execution by hotspot (explanatory comment above) 355 if (index < 0 || index > size) { 356 throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); 357 } 358 return index; 359 } 360 361 private static String badPositionIndex(int index, int size, String desc) { 362 if (index < 0) { 363 return format("%s (%s) must not be negative", desc, index); 364 } else if (size < 0) { 365 throw new IllegalArgumentException("negative size: " + size); 366 } else { // index > size 367 return format("%s (%s) must not be greater than size (%s)", 368 desc, index, size); 369 } 370 } 371 372 /** 373 * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> 374 * in an array, list or string of size {@code size}, and are in order. A 375 * position index may range from zero to {@code size}, inclusive. 376 * 377 * @param start a user-supplied index identifying a starting position in an 378 * array, list or string 379 * @param end a user-supplied index identifying a ending position in an array, 380 * list or string 381 * @param size the size of that array, list or string 382 * @throws IndexOutOfBoundsException if either index is negative or is 383 * greater than {@code size}, or if {@code end} is less than {@code start} 384 * @throws IllegalArgumentException if {@code size} is negative 385 */ 386 public static void checkPositionIndexes(int start, int end, int size) { 387 // Carefully optimized for execution by hotspot (explanatory comment above) 388 if (start < 0 || end < start || end > size) { 389 throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); 390 } 391 } 392 393 private static String badPositionIndexes(int start, int end, int size) { 394 if (start < 0 || start > size) { 395 return badPositionIndex(start, size, "start index"); 396 } 397 if (end < 0 || end > size) { 398 return badPositionIndex(end, size, "end index"); 399 } 400 // end < start 401 return format("end index (%s) must not be less than start index (%s)", 402 end, start); 403 } 404 405 /** 406 * Substitutes each {@code %s} in {@code template} with an argument. These 407 * are matched by position - the first {@code %s} gets {@code args[0]}, etc. 408 * If there are more arguments than placeholders, the unmatched arguments will 409 * be appended to the end of the formatted message in square braces. 410 * 411 * @param template a non-null string containing 0 or more {@code %s} 412 * placeholders. 413 * @param args the arguments to be substituted into the message 414 * template. Arguments are converted to strings using 415 * {@link String#valueOf(Object)}. Arguments can be null. 416 */ 417 @VisibleForTesting static String format(String template, 418 @Nullable Object... args) { 419 template = String.valueOf(template); // null -> "null" 420 421 // start substituting the arguments into the '%s' placeholders 422 StringBuilder builder = new StringBuilder( 423 template.length() + 16 * args.length); 424 int templateStart = 0; 425 int i = 0; 426 while (i < args.length) { 427 int placeholderStart = template.indexOf("%s", templateStart); 428 if (placeholderStart == -1) { 429 break; 430 } 431 builder.append(template.substring(templateStart, placeholderStart)); 432 builder.append(args[i++]); 433 templateStart = placeholderStart + 2; 434 } 435 builder.append(template.substring(templateStart)); 436 437 // if we run out of placeholders, append the extra args in square braces 438 if (i < args.length) { 439 builder.append(" ["); 440 builder.append(args[i++]); 441 while (i < args.length) { 442 builder.append(", "); 443 builder.append(args[i++]); 444 } 445 builder.append(']'); 446 } 447 448 return builder.toString(); 449 } 450}