/******************************************************************************* * Copyright (c) 2010 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial implementation *******************************************************************************/ package melnorme.utilbox.core; import static melnorme.utilbox.core.CoreUtil.areEqual; /** * Contains utility methods for assertion contract checking . * * Each method in this class, such as 'isTrue', has an identical method * with the 'assert' prefix, (ie, assertTrue). These later methods are named this way so as to be * use with Java's static imports, and are actually the preferred usage. * They are designed to be placed as a favorite in JDT's Content Assist preferences. * * This class can be used without OSGi running. */ public class Assert { protected static final AssertHandler assertHandler; // Poor mans dependency injection public static boolean assertionFailureExpected = false; // Only tests should modify this field static { String assertHandlerStr = System.getProperty(Assert.class.getName() + ".handler"); if(assertHandlerStr == null) { assertHandler = new AssertHandler(); } else if(assertHandlerStr.equals("disable") || assertHandlerStr.equals("null")) { assertHandler = null; // No op handler } else { try { final Class<?> klass = Class.forName(assertHandlerStr); Object handler = klass.newInstance(); if(handler instanceof Runnable) { final Runnable runnableHandler = (Runnable) handler; assertHandler = new AssertHandler() { @Override protected void handleAssert(String message) { runnableHandler.run(); }; }; } else { assertHandler = CoreUtil.downCast(handler); } } catch(Exception e) { throw new RuntimeException(e); // Yes, let our classloading fail. } } } /** Default implementation of the assert handler. */ public static class AssertHandler { protected void handleAssert(String message) { throw new AssertFailedException(message); } } /** * The class thrown by the default assertion failure handler. * Clients should not expect this to be thrown. */ @SuppressWarnings("serial") public static class AssertFailedException extends RuntimeException { public AssertFailedException(String message) { super(message); } @Override public String toString() { String message = getLocalizedMessage(); return AssertFailedException.class.getSimpleName() + ((message == null) ? "" : (": " + message)); //$NON-NLS-1$ } } protected static void checkAssertion(boolean condition, String message) { if(assertHandler != null && condition == false) { if(assertionFailureExpected) { // This does same thing as else branch, but code is separated // so that this case won't trigger the IDE breakpoint assertHandler.handleAssert(message); } else { assertHandler.handleAssert(message); // USEFUL TIP: place IDE breakpoint here } } } /** Asserts if given condition is true or not. If it is not, call assert handler. * Default handler behavior is to throw an {@link AssertFailedException} with given message. */ public static void isTrue(boolean condition, String message) { checkAssertion(condition, message); } /** Like {@link Assert#isTrue(boolean, String)} with no message */ public static void isTrue(boolean expression) { checkAssertion(expression, null); } /** Asserts that the given object is not null, with given message */ public static void isNotNull(Object object, String message) { checkAssertion(!(object == null), message); } /** Like {@link Assert#isNotNull(Object, String)} with no message. */ public static void isNotNull(Object object) { checkAssertion(!(object == null), null); } /** Asserts that given object1 equals object2. */ public static void equals(Object object1, Object object2) { checkAssertion(object1.equals(object2), null); } /** Causes an inconditional assertion failure, with given message. * Will always call the assertion handler, and return an RuntimeException if nothing is thrown. */ public static RuntimeException fail(String message) { checkAssertion(false, message); return new AssertFailedException(message); } /** Like {@link Assert#fail(String)} with no message. */ public static RuntimeException fail() { checkAssertion(false, null); return new AssertFailedException(null); } /** Like {@link Assert#fail(String)}, but specifically signals unreachable code */ public static RuntimeException unreachable() { return fail("Unreachable code."); //$NON-NLS-1$ } /** A namespace class for holding assert methods to use as static imports. */ public static class AssertNamespace { /** Asserts if given condition is true or not. If it is not, call assert handler. * Default handler behavior is to throw an {@link AssertFailedException} with given message. */ public static void assertTrue(boolean condition, String message) { checkAssertion(condition, message); } /** Like {@link Assert#isTrue(boolean, String)} with no message */ public static void assertTrue(boolean expression) { checkAssertion(expression, null); } /** Asserts that the given object is not null, with given message */ public static void assertNotNull(Object object, String message) { checkAssertion(!(object == null), message); } /** Like {@link Assert#isNotNull(Object, String)} with no message. */ public static <T> T assertNotNull(T object) { checkAssertion(!(object == null), null); return object; } /** Asserts that given object1 equals object2. */ public static void assertEquals(Object object1, Object object2) { checkAssertion(object1.equals(object2), null); } public static void assertAreEqual(Object object1, Object object2) { checkAssertion(areEqual(object1, object2), null); } /** Causes an inconditional assertion failure, with given message. * Will always call the assertion handler, and return an RuntimeException if nothing is thrown. */ public static RuntimeException assertFail(String message) { checkAssertion(false, message); return new AssertFailedException(message); } /** Like {@link Assert#fail(String)} with no message. */ public static RuntimeException assertFail() { checkAssertion(false, null); return new AssertFailedException(null); } /** Like {@link Assert#fail(String)}, but specifically signals unreachable code */ public static RuntimeException assertUnreachable() { return fail("Unreachable code."); //$NON-NLS-1$ } } }