package com.twelvemonkeys.lang; import java.lang.reflect.UndeclaredThrowableException; import static com.twelvemonkeys.lang.Validate.notNull; /** * ExceptionUtil * * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author last modified by $Author: haku $ * @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/ExceptionUtil.java#2 $ */ public final class ExceptionUtil { /** * Re-throws an exception, either as-is if the exception was already unchecked, otherwise wrapped in * a {@link RuntimeException} subtype. * "Expected" exception types are wrapped in {@link RuntimeException}s directly, while * "unexpected" exception types are wrapped in {@link java.lang.reflect.UndeclaredThrowableException}s. * * @param pThrowable the exception to launder * @param pExpectedTypes the types of exception the code is expected to throw */ /*public*/ static void launder(final Throwable pThrowable, Class<? extends Throwable>... pExpectedTypes) { if (pThrowable instanceof Error) { throw (Error) pThrowable; } if (pThrowable instanceof RuntimeException) { throw (RuntimeException) pThrowable; } for (Class<? extends Throwable> expectedType : pExpectedTypes) { if (expectedType.isInstance(pThrowable)) { throw new RuntimeException(pThrowable); } } throw new UndeclaredThrowableException(pThrowable); } @SuppressWarnings({"unchecked", "UnusedDeclaration"}) static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T { throw (T) pThrowable; } public static void throwUnchecked(final Throwable pThrowable) { throwAs(RuntimeException.class, pThrowable); } /*@SafeVarargs*/ @SuppressWarnings({"unchecked", "varargs"}) /*public*/ static void handle(final Throwable pThrowable, final ThrowableHandler<? extends Throwable>... pHandlers) { handleImpl(pThrowable, (ThrowableHandler<Throwable>[]) pHandlers); } private static void handleImpl(final Throwable pThrowable, final ThrowableHandler<Throwable>... pHandlers) { // TODO: Sort more specific throwable handlers before less specific? for (ThrowableHandler<Throwable> handler : pHandlers) { if (handler.handles(pThrowable)) { handler.handle(pThrowable); return; } } // Not handled, re-throw throwUnchecked(pThrowable); } public static abstract class ThrowableHandler<T extends Throwable> { private final Class<? extends T>[] throwables; protected ThrowableHandler(final Class<? extends T>... pThrowables) { throwables = notNull(pThrowables).clone(); } final public boolean handles(final Throwable pThrowable) { for (Class<? extends T> throwable : throwables) { if (throwable.isAssignableFrom(pThrowable.getClass())) { return true; } } return false; } public abstract void handle(T pThrowable); } }