1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.shiro.lang.util;
20
21 import java.util.Collection;
22 import java.util.Map;
23
24 /**
25 * Assertion utility class that assists in validating arguments.
26 * Useful for identifying programmer errors early and clearly at runtime.
27 * Usage also reduces a program's
28 * <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a>.
29 *
30 * <p>For example, if the contract of a public method states it does not
31 * allow <code>null</code> arguments, Assert can be used to validate that
32 * contract. Doing this clearly indicates a contract violation when it
33 * occurs and protects the class's invariants.
34 *
35 * <p>Typically used to validate method arguments rather than configuration
36 * properties, to check for cases that are usually programmer errors rather than
37 * configuration errors. In contrast to config initialization code, there is
38 * usually no point in falling back to defaults in such methods.
39 *
40 * <p>This class is similar to JUnit's assertion library. If an argument value is
41 * deemed invalid, an {@link IllegalArgumentException} is thrown (typically).
42 * For example:
43 *
44 * <pre class="code">
45 * Assert.notNull(clazz, "The class must not be null");
46 * Assert.isTrue(i > 0, "The value must be greater than zero");</pre>
47 * <p>
48 * Mainly for internal use within the framework; consider Jakarta's Commons Lang
49 * >= 2.0 for a more comprehensive suite of assertion utilities.
50 * <p/>
51 * <em>Gratefully borrowed from the Spring Framework, also Apache 2.0 licensed</em>
52 *
53 * @since 1.3
54 */
55 public abstract class Assert {
56
57 /**
58 * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
59 * if the test result is <code>false</code>.
60 * <pre class="code">Assert.isTrue(i > 0, "The value must be greater than zero");</pre>
61 *
62 * @param expression a boolean expression
63 * @param message the exception message to use if the assertion fails
64 * @throws IllegalArgumentException if expression is <code>false</code>
65 */
66 public static void isTrue(boolean expression, String message) {
67 if (!expression) {
68 throw new IllegalArgumentException(message);
69 }
70 }
71
72 /**
73 * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
74 * if the test result is <code>false</code>.
75 * <pre class="code">Assert.isTrue(i > 0);</pre>
76 *
77 * @param expression a boolean expression
78 * @throws IllegalArgumentException if expression is <code>false</code>
79 */
80 public static void isTrue(boolean expression) {
81 isTrue(expression, "[Assertion failed] - this expression must be true");
82 }
83
84 /**
85 * Assert that an object is <code>null</code> .
86 * <pre class="code">Assert.isNull(value, "The value must be null");</pre>
87 *
88 * @param object the object to check
89 * @param message the exception message to use if the assertion fails
90 * @throws IllegalArgumentException if the object is not <code>null</code>
91 */
92 public static void isNull(Object object, String message) {
93 if (object != null) {
94 throw new IllegalArgumentException(message);
95 }
96 }
97
98 /**
99 * 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 }