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