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