001/* 002 * Copyright 2002-2017 the original author or 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 * https://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 org.springframework.util; 018 019import java.util.Collection; 020import java.util.Map; 021 022/** 023 * Assertion utility class that assists in validating arguments. 024 * 025 * <p>Useful for identifying programmer errors early and clearly at runtime. 026 * 027 * <p>For example, if the contract of a public method states it does not 028 * allow {@code null} arguments, {@code Assert} can be used to validate that 029 * contract. Doing this clearly indicates a contract violation when it 030 * occurs and protects the class's invariants. 031 * 032 * <p>Typically used to validate method arguments rather than configuration 033 * properties, to check for cases that are usually programmer errors rather 034 * than configuration errors. In contrast to configuration initialization 035 * code, there is usually no point in falling back to defaults in such methods. 036 * 037 * <p>This class is similar to JUnit's assertion library. If an argument value is 038 * deemed invalid, an {@link IllegalArgumentException} is thrown (typically). 039 * For example: 040 * 041 * <pre class="code"> 042 * Assert.notNull(clazz, "The class must not be null"); 043 * Assert.isTrue(i > 0, "The value must be greater than zero");</pre> 044 * 045 * <p>Mainly for internal use within the framework; consider 046 * <a href="https://commons.apache.org/proper/commons-lang/">Apache's Commons Lang</a> 047 * for a more comprehensive suite of {@code String} utilities. 048 * 049 * @author Keith Donald 050 * @author Juergen Hoeller 051 * @author Sam Brannen 052 * @author Colin Sampaleanu 053 * @author Rob Harrop 054 * @since 1.1.2 055 */ 056public abstract class Assert { 057 058 /** 059 * Assert a boolean expression, throwing an {@code IllegalStateException} 060 * if the expression evaluates to {@code false}. 061 * <p>Call {@link #isTrue} if you wish to throw an {@code IllegalArgumentException} 062 * on an assertion failure. 063 * <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre> 064 * @param expression a boolean expression 065 * @param message the exception message to use if the assertion fails 066 * @throws IllegalStateException if {@code expression} is {@code false} 067 */ 068 public static void state(boolean expression, String message) { 069 if (!expression) { 070 throw new IllegalStateException(message); 071 } 072 } 073 074 /** 075 * @deprecated as of 4.3.7, in favor of {@link #state(boolean, String)} 076 */ 077 @Deprecated 078 public static void state(boolean expression) { 079 state(expression, "[Assertion failed] - this state invariant must be true"); 080 } 081 082 /** 083 * Assert a boolean expression, throwing an {@code IllegalArgumentException} 084 * if the expression evaluates to {@code false}. 085 * <pre class="code">Assert.isTrue(i > 0, "The value must be greater than zero");</pre> 086 * @param expression a boolean expression 087 * @param message the exception message to use if the assertion fails 088 * @throws IllegalArgumentException if {@code expression} is {@code false} 089 */ 090 public static void isTrue(boolean expression, String message) { 091 if (!expression) { 092 throw new IllegalArgumentException(message); 093 } 094 } 095 096 /** 097 * @deprecated as of 4.3.7, in favor of {@link #isTrue(boolean, String)} 098 */ 099 @Deprecated 100 public static void isTrue(boolean expression) { 101 isTrue(expression, "[Assertion failed] - this expression must be true"); 102 } 103 104 /** 105 * Assert that an object is {@code null}. 106 * <pre class="code">Assert.isNull(value, "The value must be null");</pre> 107 * @param object the object to check 108 * @param message the exception message to use if the assertion fails 109 * @throws IllegalArgumentException if the object is not {@code null} 110 */ 111 public static void isNull(Object object, String message) { 112 if (object != null) { 113 throw new IllegalArgumentException(message); 114 } 115 } 116 117 /** 118 * @deprecated as of 4.3.7, in favor of {@link #isNull(Object, String)} 119 */ 120 @Deprecated 121 public static void isNull(Object object) { 122 isNull(object, "[Assertion failed] - the object argument must be null"); 123 } 124 125 /** 126 * Assert that an object is not {@code null}. 127 * <pre class="code">Assert.notNull(clazz, "The class must not be null");</pre> 128 * @param object the object to check 129 * @param message the exception message to use if the assertion fails 130 * @throws IllegalArgumentException if the object is {@code null} 131 */ 132 public static void notNull(Object object, String message) { 133 if (object == null) { 134 throw new IllegalArgumentException(message); 135 } 136 } 137 138 /** 139 * @deprecated as of 4.3.7, in favor of {@link #notNull(Object, String)} 140 */ 141 @Deprecated 142 public static void notNull(Object object) { 143 notNull(object, "[Assertion failed] - this argument is required; it must not be null"); 144 } 145 146 /** 147 * Assert that the given String is not empty; that is, 148 * it must not be {@code null} and not the empty String. 149 * <pre class="code">Assert.hasLength(name, "Name must not be empty");</pre> 150 * @param text the String to check 151 * @param message the exception message to use if the assertion fails 152 * @see StringUtils#hasLength 153 * @throws IllegalArgumentException if the text is empty 154 */ 155 public static void hasLength(String text, String message) { 156 if (!StringUtils.hasLength(text)) { 157 throw new IllegalArgumentException(message); 158 } 159 } 160 161 /** 162 * @deprecated as of 4.3.7, in favor of {@link #hasLength(String, String)} 163 */ 164 @Deprecated 165 public static void hasLength(String text) { 166 hasLength(text, 167 "[Assertion failed] - this String argument must have length; it must not be null or empty"); 168 } 169 170 /** 171 * Assert that the given String contains valid text content; that is, it must not 172 * be {@code null} and must contain at least one non-whitespace character. 173 * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre> 174 * @param text the String to check 175 * @param message the exception message to use if the assertion fails 176 * @see StringUtils#hasText 177 * @throws IllegalArgumentException if the text does not contain valid text content 178 */ 179 public static void hasText(String text, String message) { 180 if (!StringUtils.hasText(text)) { 181 throw new IllegalArgumentException(message); 182 } 183 } 184 185 /** 186 * @deprecated as of 4.3.7, in favor of {@link #hasText(String, String)} 187 */ 188 @Deprecated 189 public static void hasText(String text) { 190 hasText(text, 191 "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank"); 192 } 193 194 /** 195 * Assert that the given text does not contain the given substring. 196 * <pre class="code">Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");</pre> 197 * @param textToSearch the text to search 198 * @param substring the substring to find within the text 199 * @param message the exception message to use if the assertion fails 200 * @throws IllegalArgumentException if the text contains the substring 201 */ 202 public static void doesNotContain(String textToSearch, String substring, String message) { 203 if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && 204 textToSearch.contains(substring)) { 205 throw new IllegalArgumentException(message); 206 } 207 } 208 209 /** 210 * @deprecated as of 4.3.7, in favor of {@link #doesNotContain(String, String, String)} 211 */ 212 @Deprecated 213 public static void doesNotContain(String textToSearch, String substring) { 214 doesNotContain(textToSearch, substring, 215 "[Assertion failed] - this String argument must not contain the substring [" + substring + "]"); 216 } 217 218 /** 219 * Assert that an array contains elements; that is, it must not be 220 * {@code null} and must contain at least one element. 221 * <pre class="code">Assert.notEmpty(array, "The array must contain elements");</pre> 222 * @param array the array to check 223 * @param message the exception message to use if the assertion fails 224 * @throws IllegalArgumentException if the object array is {@code null} or contains no elements 225 */ 226 public static void notEmpty(Object[] array, String message) { 227 if (ObjectUtils.isEmpty(array)) { 228 throw new IllegalArgumentException(message); 229 } 230 } 231 232 /** 233 * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Object[], String)} 234 */ 235 @Deprecated 236 public static void notEmpty(Object[] array) { 237 notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element"); 238 } 239 240 /** 241 * Assert that an array contains no {@code null} elements. 242 * <p>Note: Does not complain if the array is empty! 243 * <pre class="code">Assert.noNullElements(array, "The array must contain non-null elements");</pre> 244 * @param array the array to check 245 * @param message the exception message to use if the assertion fails 246 * @throws IllegalArgumentException if the object array contains a {@code null} element 247 */ 248 public static void noNullElements(Object[] array, String message) { 249 if (array != null) { 250 for (Object element : array) { 251 if (element == null) { 252 throw new IllegalArgumentException(message); 253 } 254 } 255 } 256 } 257 258 /** 259 * @deprecated as of 4.3.7, in favor of {@link #noNullElements(Object[], String)} 260 */ 261 @Deprecated 262 public static void noNullElements(Object[] array) { 263 noNullElements(array, "[Assertion failed] - this array must not contain any null elements"); 264 } 265 266 /** 267 * Assert that a collection contains elements; that is, it must not be 268 * {@code null} and must contain at least one element. 269 * <pre class="code">Assert.notEmpty(collection, "Collection must contain elements");</pre> 270 * @param collection the collection to check 271 * @param message the exception message to use if the assertion fails 272 * @throws IllegalArgumentException if the collection is {@code null} or 273 * contains no elements 274 */ 275 public static void notEmpty(Collection<?> collection, String message) { 276 if (CollectionUtils.isEmpty(collection)) { 277 throw new IllegalArgumentException(message); 278 } 279 } 280 281 /** 282 * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Collection, String)} 283 */ 284 @Deprecated 285 public static void notEmpty(Collection<?> collection) { 286 notEmpty(collection, 287 "[Assertion failed] - this collection must not be empty: it must contain at least 1 element"); 288 } 289 290 /** 291 * Assert that a Map contains entries; that is, it must not be {@code null} 292 * and must contain at least one entry. 293 * <pre class="code">Assert.notEmpty(map, "Map must contain entries");</pre> 294 * @param map the map to check 295 * @param message the exception message to use if the assertion fails 296 * @throws IllegalArgumentException if the map is {@code null} or contains no entries 297 */ 298 public static void notEmpty(Map<?, ?> map, String message) { 299 if (CollectionUtils.isEmpty(map)) { 300 throw new IllegalArgumentException(message); 301 } 302 } 303 304 /** 305 * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Map, String)} 306 */ 307 @Deprecated 308 public static void notEmpty(Map<?, ?> map) { 309 notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry"); 310 } 311 312 /** 313 * Assert that the provided object is an instance of the provided class. 314 * <pre class="code">Assert.instanceOf(Foo.class, foo, "Foo expected");</pre> 315 * @param type the type to check against 316 * @param obj the object to check 317 * @param message a message which will be prepended to provide further context. 318 * If it is empty or ends in ":" or ";" or "," or ".", a full exception message 319 * will be appended. If it ends in a space, the name of the offending object's 320 * type will be appended. In any other case, a ":" with a space and the name 321 * of the offending object's type will be appended. 322 * @throws IllegalArgumentException if the object is not an instance of type 323 */ 324 public static void isInstanceOf(Class<?> type, Object obj, String message) { 325 notNull(type, "Type to check against must not be null"); 326 if (!type.isInstance(obj)) { 327 instanceCheckFailed(type, obj, message); 328 } 329 } 330 331 /** 332 * Assert that the provided object is an instance of the provided class. 333 * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre> 334 * @param type the type to check against 335 * @param obj the object to check 336 * @throws IllegalArgumentException if the object is not an instance of type 337 */ 338 public static void isInstanceOf(Class<?> type, Object obj) { 339 isInstanceOf(type, obj, ""); 340 } 341 342 /** 343 * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}. 344 * <pre class="code">Assert.isAssignable(Number.class, myClass, "Number expected");</pre> 345 * @param superType the super type to check against 346 * @param subType the sub type to check 347 * @param message a message which will be prepended to provide further context. 348 * If it is empty or ends in ":" or ";" or "," or ".", a full exception message 349 * will be appended. If it ends in a space, the name of the offending sub type 350 * will be appended. In any other case, a ":" with a space and the name of the 351 * offending sub type will be appended. 352 * @throws IllegalArgumentException if the classes are not assignable 353 */ 354 public static void isAssignable(Class<?> superType, Class<?> subType, String message) { 355 notNull(superType, "Super type to check against must not be null"); 356 if (subType == null || !superType.isAssignableFrom(subType)) { 357 assignableCheckFailed(superType, subType, message); 358 } 359 } 360 361 /** 362 * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}. 363 * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre> 364 * @param superType the super type to check 365 * @param subType the sub type to check 366 * @throws IllegalArgumentException if the classes are not assignable 367 */ 368 public static void isAssignable(Class<?> superType, Class<?> subType) { 369 isAssignable(superType, subType, ""); 370 } 371 372 373 private static void instanceCheckFailed(Class<?> type, Object obj, String msg) { 374 String className = (obj != null ? obj.getClass().getName() : "null"); 375 String result = ""; 376 boolean defaultMessage = true; 377 if (StringUtils.hasLength(msg)) { 378 if (endsWithSeparator(msg)) { 379 result = msg + " "; 380 } 381 else { 382 result = messageWithTypeName(msg, className); 383 defaultMessage = false; 384 } 385 } 386 if (defaultMessage) { 387 result = result + ("Object of class [" + className + "] must be an instance of " + type); 388 } 389 throw new IllegalArgumentException(result); 390 } 391 392 private static void assignableCheckFailed(Class<?> superType, Class<?> subType, String msg) { 393 String result = ""; 394 boolean defaultMessage = true; 395 if (StringUtils.hasLength(msg)) { 396 if (endsWithSeparator(msg)) { 397 result = msg + " "; 398 } 399 else { 400 result = messageWithTypeName(msg, subType); 401 defaultMessage = false; 402 } 403 } 404 if (defaultMessage) { 405 result = result + (subType + " is not assignable to " + superType); 406 } 407 throw new IllegalArgumentException(result); 408 } 409 410 private static boolean endsWithSeparator(String msg) { 411 return (msg.endsWith(":") || msg.endsWith(";") || msg.endsWith(",") || msg.endsWith(".")); 412 } 413 414 private static String messageWithTypeName(String msg, Object typeName) { 415 return msg + (msg.endsWith(" ") ? "" : ": ") + typeName; 416 } 417 418}