001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.shiro.lang.util; 020 021import java.util.Collection; 022import java.util.Map; 023 024/** 025 * Assertion utility class that assists in validating arguments. 026 * Useful for identifying programmer errors early and clearly at runtime. 027 * Usage also reduces a program's 028 * <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a>. 029 * 030 * <p>For example, if the contract of a public method states it does not 031 * allow <code>null</code> arguments, Assert can be used to validate that 032 * contract. Doing this clearly indicates a contract violation when it 033 * occurs and protects the class's invariants. 034 * 035 * <p>Typically used to validate method arguments rather than configuration 036 * properties, to check for cases that are usually programmer errors rather than 037 * configuration errors. In contrast to config initialization code, there is 038 * usually no point in falling back to defaults in such methods. 039 * 040 * <p>This class is similar to JUnit's assertion library. If an argument value is 041 * deemed invalid, an {@link IllegalArgumentException} is thrown (typically). 042 * For example: 043 * 044 * <pre class="code"> 045 * Assert.notNull(clazz, "The class must not be null"); 046 * Assert.isTrue(i > 0, "The value must be greater than zero");</pre> 047 * <p> 048 * Mainly for internal use within the framework; consider Jakarta's Commons Lang 049 * >= 2.0 for a more comprehensive suite of assertion utilities. 050 * <p/> 051 * <em>Gratefully borrowed from the Spring Framework, also Apache 2.0 licensed</em> 052 * 053 * @since 1.3 054 */ 055public abstract class Assert { 056 057 /** 058 * Assert a boolean expression, throwing <code>IllegalArgumentException</code> 059 * if the test result is <code>false</code>. 060 * <pre class="code">Assert.isTrue(i > 0, "The value must be greater than zero");</pre> 061 * 062 * @param expression a boolean expression 063 * @param message the exception message to use if the assertion fails 064 * @throws IllegalArgumentException if expression is <code>false</code> 065 */ 066 public static void isTrue(boolean expression, String message) { 067 if (!expression) { 068 throw new IllegalArgumentException(message); 069 } 070 } 071 072 /** 073 * Assert a boolean expression, throwing <code>IllegalArgumentException</code> 074 * if the test result is <code>false</code>. 075 * <pre class="code">Assert.isTrue(i > 0);</pre> 076 * 077 * @param expression a boolean expression 078 * @throws IllegalArgumentException if expression is <code>false</code> 079 */ 080 public static void isTrue(boolean expression) { 081 isTrue(expression, "[Assertion failed] - this expression must be true"); 082 } 083 084 /** 085 * Assert that an object is <code>null</code> . 086 * <pre class="code">Assert.isNull(value, "The value must be null");</pre> 087 * 088 * @param object the object to check 089 * @param message the exception message to use if the assertion fails 090 * @throws IllegalArgumentException if the object is not <code>null</code> 091 */ 092 public static void isNull(Object object, String message) { 093 if (object != null) { 094 throw new IllegalArgumentException(message); 095 } 096 } 097 098 /** 099 * Assert that an object is <code>null</code> . 100 * <pre class="code">Assert.isNull(value);</pre> 101 * 102 * @param object the object to check 103 * @throws IllegalArgumentException if the object is not <code>null</code> 104 */ 105 public static void isNull(Object object) { 106 isNull(object, "[Assertion failed] - the object argument must be null"); 107 } 108 109 /** 110 * Assert that an object is not <code>null</code> . 111 * <pre class="code">Assert.notNull(clazz, "The class must not be null");</pre> 112 * 113 * @param object the object to check 114 * @param message the exception message to use if the assertion fails 115 * @throws IllegalArgumentException if the object is <code>null</code> 116 */ 117 public static void notNull(Object object, String message) { 118 if (object == null) { 119 throw new IllegalArgumentException(message); 120 } 121 } 122 123 /** 124 * Assert that an object is not <code>null</code> . 125 * <pre class="code">Assert.notNull(clazz);</pre> 126 * 127 * @param object the object to check 128 * @throws IllegalArgumentException if the object is <code>null</code> 129 */ 130 public static void notNull(Object object) { 131 notNull(object, "[Assertion failed] - this argument is required; it must not be null"); 132 } 133 134 /** 135 * Assert that the given String is not empty; that is, 136 * it must not be <code>null</code> and not the empty String. 137 * <pre class="code">Assert.hasLength(name, "Name must not be empty");</pre> 138 * 139 * @param text the String to check 140 * @param message the exception message to use if the assertion fails 141 * @see StringUtils#hasLength 142 */ 143 public static void hasLength(String text, String message) { 144 if (!StringUtils.hasLength(text)) { 145 throw new IllegalArgumentException(message); 146 } 147 } 148 149 /** 150 * Assert that the given String is not empty; that is, 151 * it must not be <code>null</code> and not the empty String. 152 * <pre class="code">Assert.hasLength(name);</pre> 153 * 154 * @param text the String to check 155 * @see StringUtils#hasLength 156 */ 157 public static void hasLength(String text) { 158 hasLength(text, 159 "[Assertion failed] - this String argument must have length; it must not be null or empty"); 160 } 161 162 /** 163 * Assert that the given String has valid text content; that is, it must not 164 * be <code>null</code> and must contain at least one non-whitespace character. 165 * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre> 166 * 167 * @param text the String to check 168 * @param message the exception message to use if the assertion fails 169 * @see StringUtils#hasText 170 */ 171 public static void hasText(String text, String message) { 172 if (!StringUtils.hasText(text)) { 173 throw new IllegalArgumentException(message); 174 } 175 } 176 177 /** 178 * Assert that the given String has valid text content; that is, it must not 179 * be <code>null</code> and must contain at least one non-whitespace character. 180 * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre> 181 * 182 * @param text the String to check 183 * @see StringUtils#hasText 184 */ 185 public static void hasText(String text) { 186 hasText(text, 187 "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank"); 188 } 189 190 /** 191 * Assert that the given text does not contain the given substring. 192 * <pre class="code">Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");</pre> 193 * 194 * @param textToSearch the text to search 195 * @param substring the substring to find within the text 196 * @param message the exception message to use if the assertion fails 197 */ 198 public static void doesNotContain(String textToSearch, String substring, String message) { 199 if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) 200 && textToSearch.contains(substring)) { 201 throw new IllegalArgumentException(message); 202 } 203 } 204 205 /** 206 * Assert that the given text does not contain the given substring. 207 * <pre class="code">Assert.doesNotContain(name, "rod");</pre> 208 * 209 * @param textToSearch the text to search 210 * @param substring the substring to find within the text 211 */ 212 public static void doesNotContain(String textToSearch, String substring) { 213 doesNotContain(textToSearch, substring, 214 "[Assertion failed] - this String argument must not contain the substring [" + substring + "]"); 215 } 216 217 218 /** 219 * Assert that an array has elements; that is, it must not be 220 * <code>null</code> and must have at least one element. 221 * <pre class="code">Assert.notEmpty(array, "The array must have elements");</pre> 222 * 223 * @param array the array to check 224 * @param message the exception message to use if the assertion fails 225 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements 226 */ 227 public static void notEmpty(Object[] array, String message) { 228 if (array == null || array.length == 0) { 229 throw new IllegalArgumentException(message); 230 } 231 } 232 233 /** 234 * Assert that an array has elements; that is, it must not be 235 * <code>null</code> and must have at least one element. 236 * <pre class="code">Assert.notEmpty(array);</pre> 237 * 238 * @param array the array to check 239 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements 240 */ 241 public static void notEmpty(Object[] array) { 242 notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element"); 243 } 244 245 /** 246 * Assert that an array has no null elements. 247 * Note: Does not complain if the array is empty! 248 * <pre class="code">Assert.noNullElements(array, "The array must have non-null elements");</pre> 249 * 250 * @param array the array to check 251 * @param message the exception message to use if the assertion fails 252 * @throws IllegalArgumentException if the object array contains a <code>null</code> element 253 */ 254 public static void noNullElements(Object[] array, String message) { 255 if (array != null) { 256 for (int i = 0; i < array.length; i++) { 257 if (array[i] == null) { 258 throw new IllegalArgumentException(message); 259 } 260 } 261 } 262 } 263 264 /** 265 * Assert that an array has no null elements. 266 * Note: Does not complain if the array is empty! 267 * <pre class="code">Assert.noNullElements(array);</pre> 268 * 269 * @param array the array to check 270 * @throws IllegalArgumentException if the object array contains a <code>null</code> element 271 */ 272 public static void noNullElements(Object[] array) { 273 noNullElements(array, "[Assertion failed] - this array must not contain any null elements"); 274 } 275 276 /** 277 * Assert that a collection has elements; that is, it must not be 278 * <code>null</code> and must have at least one element. 279 * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre> 280 * 281 * @param collection the collection to check 282 * @param message the exception message to use if the assertion fails 283 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements 284 */ 285 public static void notEmpty(Collection collection, String message) { 286 if (isEmpty(collection)) { 287 throw new IllegalArgumentException(message); 288 } 289 } 290 291 /** 292 * Assert that a collection has elements; that is, it must not be 293 * <code>null</code> and must have at least one element. 294 * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre> 295 * 296 * @param collection the collection to check 297 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements 298 */ 299 public static void notEmpty(Collection collection) { 300 notEmpty(collection, 301 "[Assertion failed] - this collection must not be empty: it must contain at least 1 element"); 302 } 303 304 /** 305 * Assert that a Map has entries; that is, it must not be <code>null</code> 306 * and must have at least one entry. 307 * <pre class="code">Assert.notEmpty(map, "Map must have entries");</pre> 308 * 309 * @param map the map to check 310 * @param message the exception message to use if the assertion fails 311 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries 312 */ 313 public static void notEmpty(Map map, String message) { 314 if (isEmpty(map)) { 315 throw new IllegalArgumentException(message); 316 } 317 } 318 319 /** 320 * Assert that a Map has entries; that is, it must not be <code>null</code> 321 * and must have at least one entry. 322 * <pre class="code">Assert.notEmpty(map);</pre> 323 * 324 * @param map the map to check 325 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries 326 */ 327 public static void notEmpty(Map map) { 328 notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry"); 329 } 330 331 332 /** 333 * Assert that the provided object is an instance of the provided class. 334 * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre> 335 * 336 * @param clazz the required class 337 * @param obj the object to check 338 * @throws IllegalArgumentException if the object is not an instance of clazz 339 * @see Class#isInstance 340 */ 341 public static void isInstanceOf(Class clazz, Object obj) { 342 isInstanceOf(clazz, obj, ""); 343 } 344 345 /** 346 * Assert that the provided object is an instance of the provided class. 347 * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre> 348 * 349 * @param type the type to check against 350 * @param obj the object to check 351 * @param message a message which will be prepended to the message produced by 352 * the function itself, and which may be used to provide context. It should 353 * normally end in a ": " or ". " so that the function generate message looks 354 * ok when prepended to it. 355 * @throws IllegalArgumentException if the object is not an instance of clazz 356 * @see Class#isInstance 357 */ 358 public static void isInstanceOf(Class type, Object obj, String message) { 359 notNull(type, "Type to check against must not be null"); 360 if (!type.isInstance(obj)) { 361 throw new IllegalArgumentException(message 362 + "Object of class [" + (obj != null ? obj.getClass().getName() : "null") 363 + "] must be an instance of " + type); 364 } 365 } 366 367 /** 368 * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>. 369 * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre> 370 * 371 * @param superType the super type to check 372 * @param subType the sub type to check 373 * @throws IllegalArgumentException if the classes are not assignable 374 */ 375 public static void isAssignable(Class superType, Class subType) { 376 isAssignable(superType, subType, ""); 377 } 378 379 /** 380 * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>. 381 * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre> 382 * 383 * @param superType the super type to check against 384 * @param subType the sub type to check 385 * @param message a message which will be prepended to the message produced by 386 * the function itself, and which may be used to provide context. It should 387 * normally end in a ": " or ". " so that the function generate message looks 388 * ok when prepended to it. 389 * @throws IllegalArgumentException if the classes are not assignable 390 */ 391 public static void isAssignable(Class<?> superType, Class<?> subType, String message) { 392 notNull(superType, "Type to check against must not be null"); 393 if (subType == null || !superType.isAssignableFrom(subType)) { 394 throw new IllegalArgumentException(message + subType + " is not assignable to " + superType); 395 } 396 } 397 398 399 /** 400 * Assert a boolean expression, throwing <code>IllegalStateException</code> 401 * if the test result is <code>false</code>. Call isTrue if you wish to 402 * throw IllegalArgumentException on an assertion failure. 403 * <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre> 404 * 405 * @param expression a boolean expression 406 * @param message the exception message to use if the assertion fails 407 * @throws IllegalStateException if expression is <code>false</code> 408 */ 409 public static void state(boolean expression, String message) { 410 if (!expression) { 411 throw new IllegalStateException(message); 412 } 413 } 414 415 /** 416 * Assert a boolean expression, throwing {@link IllegalStateException} 417 * if the test result is <code>false</code>. 418 * <p>Call {@link #isTrue(boolean)} if you wish to 419 * throw {@link IllegalArgumentException} on an assertion failure. 420 * <pre class="code">Assert.state(id == null);</pre> 421 * 422 * @param expression a boolean expression 423 * @throws IllegalStateException if the supplied expression is <code>false</code> 424 */ 425 public static void state(boolean expression) { 426 state(expression, "[Assertion failed] - this state invariant must be true"); 427 } 428 429 430 ////////////////////////// 431 // From CollectionUtils // 432 ////////////////////////// 433 // CollectionUtils cannot be removed from shiro-core until 2.0 as it has a dependency on PrincipalCollection 434 435 private static boolean isEmpty(Map m) { 436 return m == null || m.isEmpty(); 437 } 438 439 private static boolean isEmpty(Collection c) { 440 return c == null || c.isEmpty(); 441 } 442 443}