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.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 * usally 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 *
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 * @author Keith Donald
054 * @author Juergen Hoeller
055 * @author Colin Sampaleanu
056 * @author Rob Harrop
057 * @since 1.3
058 */
059public abstract class Assert {
060
061    /**
062     * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
063     * if the test result is <code>false</code>.
064     * <pre class="code">Assert.isTrue(i &gt; 0, "The value must be greater than zero");</pre>
065     * @param expression a boolean expression
066     * @param message the exception message to use if the assertion fails
067     * @throws IllegalArgumentException if expression is <code>false</code>
068     */
069    public static void isTrue(boolean expression, String message) {
070        if (!expression) {
071            throw new IllegalArgumentException(message);
072        }
073    }
074
075    /**
076     * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
077     * if the test result is <code>false</code>.
078     * <pre class="code">Assert.isTrue(i &gt; 0);</pre>
079     * @param expression a boolean expression
080     * @throws IllegalArgumentException if expression is <code>false</code>
081     */
082    public static void isTrue(boolean expression) {
083        isTrue(expression, "[Assertion failed] - this expression must be true");
084    }
085
086    /**
087     * Assert that an object is <code>null</code> .
088     * <pre class="code">Assert.isNull(value, "The value must be null");</pre>
089     * @param object the object to check
090     * @param message the exception message to use if the assertion fails
091     * @throws IllegalArgumentException if the object is not <code>null</code>
092     */
093    public static void isNull(Object object, String message) {
094        if (object != null) {
095            throw new IllegalArgumentException(message);
096        }
097    }
098
099    /**
100     * Assert that an object is <code>null</code> .
101     * <pre class="code">Assert.isNull(value);</pre>
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     * @param object the object to check
113     * @param message the exception message to use if the assertion fails
114     * @throws IllegalArgumentException if the object is <code>null</code>
115     */
116    public static void notNull(Object object, String message) {
117        if (object == null) {
118            throw new IllegalArgumentException(message);
119        }
120    }
121
122    /**
123     * Assert that an object is not <code>null</code> .
124     * <pre class="code">Assert.notNull(clazz);</pre>
125     * @param object the object to check
126     * @throws IllegalArgumentException if the object is <code>null</code>
127     */
128    public static void notNull(Object object) {
129        notNull(object, "[Assertion failed] - this argument is required; it must not be null");
130    }
131
132    /**
133     * Assert that the given String is not empty; that is,
134     * it must not be <code>null</code> and not the empty String.
135     * <pre class="code">Assert.hasLength(name, "Name must not be empty");</pre>
136     * @param text the String to check
137     * @param message the exception message to use if the assertion fails
138     * @see StringUtils#hasLength
139     */
140    public static void hasLength(String text, String message) {
141        if (!StringUtils.hasLength(text)) {
142            throw new IllegalArgumentException(message);
143        }
144    }
145
146    /**
147     * Assert that the given String is not empty; that is,
148     * it must not be <code>null</code> and not the empty String.
149     * <pre class="code">Assert.hasLength(name);</pre>
150     * @param text the String to check
151     * @see StringUtils#hasLength
152     */
153    public static void hasLength(String text) {
154        hasLength(text,
155                "[Assertion failed] - this String argument must have length; it must not be null or empty");
156    }
157
158    /**
159     * Assert that the given String has valid text content; that is, it must not
160     * be <code>null</code> and must contain at least one non-whitespace character.
161     * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
162     * @param text the String to check
163     * @param message the exception message to use if the assertion fails
164     * @see StringUtils#hasText
165     */
166    public static void hasText(String text, String message) {
167        if (!StringUtils.hasText(text)) {
168            throw new IllegalArgumentException(message);
169        }
170    }
171
172    /**
173     * Assert that the given String has valid text content; that is, it must not
174     * be <code>null</code> and must contain at least one non-whitespace character.
175     * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
176     * @param text the String to check
177     * @see StringUtils#hasText
178     */
179    public static void hasText(String text) {
180        hasText(text,
181                "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
182    }
183
184    /**
185     * Assert that the given text does not contain the given substring.
186     * <pre class="code">Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");</pre>
187     * @param textToSearch the text to search
188     * @param substring the substring to find within the text
189     * @param message the exception message to use if the assertion fails
190     */
191    public static void doesNotContain(String textToSearch, String substring, String message) {
192        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
193                textToSearch.indexOf(substring) != -1) {
194            throw new IllegalArgumentException(message);
195        }
196    }
197
198    /**
199     * Assert that the given text does not contain the given substring.
200     * <pre class="code">Assert.doesNotContain(name, "rod");</pre>
201     * @param textToSearch the text to search
202     * @param substring the substring to find within the text
203     */
204    public static void doesNotContain(String textToSearch, String substring) {
205        doesNotContain(textToSearch, substring,
206                "[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
207    }
208
209
210    /**
211     * Assert that an array has elements; that is, it must not be
212     * <code>null</code> and must have at least one element.
213     * <pre class="code">Assert.notEmpty(array, "The array must have elements");</pre>
214     * @param array the array to check
215     * @param message the exception message to use if the assertion fails
216     * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
217     */
218    public static void notEmpty(Object[] array, String message) {
219        if (array == null || array.length == 0) {
220            throw new IllegalArgumentException(message);
221        }
222    }
223
224    /**
225     * Assert that an array has elements; that is, it must not be
226     * <code>null</code> and must have at least one element.
227     * <pre class="code">Assert.notEmpty(array);</pre>
228     * @param array the array to check
229     * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
230     */
231    public static void notEmpty(Object[] array) {
232        notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
233    }
234
235    /**
236     * Assert that an array has no null elements.
237     * Note: Does not complain if the array is empty!
238     * <pre class="code">Assert.noNullElements(array, "The array must have non-null elements");</pre>
239     * @param array the array to check
240     * @param message the exception message to use if the assertion fails
241     * @throws IllegalArgumentException if the object array contains a <code>null</code> element
242     */
243    public static void noNullElements(Object[] array, String message) {
244        if (array != null) {
245            for (int i = 0; i < array.length; i++) {
246                if (array[i] == null) {
247                    throw new IllegalArgumentException(message);
248                }
249            }
250        }
251    }
252
253    /**
254     * Assert that an array has no null elements.
255     * Note: Does not complain if the array is empty!
256     * <pre class="code">Assert.noNullElements(array);</pre>
257     * @param array the array to check
258     * @throws IllegalArgumentException if the object array contains a <code>null</code> element
259     */
260    public static void noNullElements(Object[] array) {
261        noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
262    }
263
264    /**
265     * Assert that a collection has elements; that is, it must not be
266     * <code>null</code> and must have at least one element.
267     * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
268     * @param collection the collection to check
269     * @param message the exception message to use if the assertion fails
270     * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
271     */
272    public static void notEmpty(Collection collection, String message) {
273        if (CollectionUtils.isEmpty(collection)) {
274            throw new IllegalArgumentException(message);
275        }
276    }
277
278    /**
279     * Assert that a collection has elements; that is, it must not be
280     * <code>null</code> and must have at least one element.
281     * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
282     * @param collection the collection to check
283     * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
284     */
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 has entries; that is, it must not be <code>null</code>
292     * and must have at least one entry.
293     * <pre class="code">Assert.notEmpty(map, "Map must have 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</code> or has 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     * 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);</pre>
308     * @param map the map to check
309     * @throws IllegalArgumentException if the map is <code>null</code> or has no entries
310     */
311    public static void notEmpty(Map map) {
312        notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
313    }
314
315
316    /**
317     * Assert that the provided object is an instance of the provided class.
318     * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
319     * @param clazz the required class
320     * @param obj the object to check
321     * @throws IllegalArgumentException if the object is not an instance of clazz
322     * @see Class#isInstance
323     */
324    public static void isInstanceOf(Class clazz, Object obj) {
325        isInstanceOf(clazz, obj, "");
326    }
327
328    /**
329     * Assert that the provided object is an instance of the provided class.
330     * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
331     * @param type the type to check against
332     * @param obj the object to check
333     * @param message a message which will be prepended to the message produced by
334     * the function itself, and which may be used to provide context. It should
335     * normally end in a ": " or ". " so that the function generate message looks
336     * ok when prepended to it.
337     * @throws IllegalArgumentException if the object is not an instance of clazz
338     * @see Class#isInstance
339     */
340    public static void isInstanceOf(Class type, Object obj, String message) {
341        notNull(type, "Type to check against must not be null");
342        if (!type.isInstance(obj)) {
343            throw new IllegalArgumentException(message +
344                    "Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
345                    "] must be an instance of " + type);
346        }
347    }
348
349    /**
350     * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
351     * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
352     * @param superType the super type to check
353     * @param subType the sub type to check
354     * @throws IllegalArgumentException if the classes are not assignable
355     */
356    public static void isAssignable(Class superType, Class subType) {
357        isAssignable(superType, subType, "");
358    }
359
360    /**
361     * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
362     * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
363     * @param superType the super type to check against
364     * @param subType the sub type to check
365     * @param message a message which will be prepended to the message produced by
366     * the function itself, and which may be used to provide context. It should
367     * normally end in a ": " or ". " so that the function generate message looks
368     * ok when prepended to it.
369     * @throws IllegalArgumentException if the classes are not assignable
370     */
371    public static void isAssignable(Class superType, Class subType, String message) {
372        notNull(superType, "Type to check against must not be null");
373        if (subType == null || !superType.isAssignableFrom(subType)) {
374            throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
375        }
376    }
377
378
379    /**
380     * Assert a boolean expression, throwing <code>IllegalStateException</code>
381     * if the test result is <code>false</code>. Call isTrue if you wish to
382     * throw IllegalArgumentException on an assertion failure.
383     * <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre>
384     * @param expression a boolean expression
385     * @param message the exception message to use if the assertion fails
386     * @throws IllegalStateException if expression is <code>false</code>
387     */
388    public static void state(boolean expression, String message) {
389        if (!expression) {
390            throw new IllegalStateException(message);
391        }
392    }
393
394    /**
395     * Assert a boolean expression, throwing {@link IllegalStateException}
396     * if the test result is <code>false</code>.
397     * <p>Call {@link #isTrue(boolean)} if you wish to
398     * throw {@link IllegalArgumentException} on an assertion failure.
399     * <pre class="code">Assert.state(id == null);</pre>
400     * @param expression a boolean expression
401     * @throws IllegalStateException if the supplied expression is <code>false</code>
402     */
403    public static void state(boolean expression) {
404        state(expression, "[Assertion failed] - this state invariant must be true");
405    }
406
407}