package org.marketcetera.photon.commons; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.marketcetera.util.misc.ClassVersion; /* $License$ */ /** * Utilities for working with exceptions. * * @author <a href="mailto:will@marketcetera.com">Will Horn</a> * @version $Id: ExceptionUtils.java 16154 2012-07-14 16:34:05Z colin $ * @since 2.0.0 */ @ClassVersion("$Id: ExceptionUtils.java 16154 2012-07-14 16:34:05Z colin $") public class ExceptionUtils { /** * Safely casts a Throwable to RuntimeException. If the throwable is an * error, it will be thrown. If the throwable is a checked exception, an * IllegalStateException will be thrown. * * @param throwable * the throwable to launder * @return throwable if it is a runtime exception * @throws IllegalArgumentException * if throwable is null * @throws Error * throwable, if throwable is an error * @throws IllegalStateException * if throwable is a checked exception */ public static RuntimeException launderThrowable(Throwable throwable) { Validate.notNull(throwable, "throwable"); //$NON-NLS-1$ if (throwable instanceof RuntimeException) return (RuntimeException) throwable; else if (throwable instanceof Error) throw (Error) throwable; else throw new IllegalStateException("Not unchecked", throwable); //$NON-NLS-1$ } /** * Gets the result of a future, laundering any resulting * {@link ExecutionException}. If a runtime exception, or error is found as * the cause, it will be rethrown. Otherwise an IllegalStateException will * be thrown. * * @param future * the future to await * @return the result of future.get() * @throws CancellationException * if the computation was canceled * @throws InterruptedException * if the current thread was interrupted while waiting * @throws IllegalStateException * if the future task throws a checked exception */ public static <T> T launderedGet(Future<T> future) throws InterruptedException { try { return future.get(); } catch (ExecutionException e) { throw launderThrowable(e.getCause()); } } /** * Gets the result of a future, laundering the cause of any resulting * {@link ExecutionException}. If an expected checked exception, runtime * exception, or error is found as the cause, it will be rethrown. Otherwise * an IllegalStateException will be thrown. * * @param future * the future to await * @param expected * the optional expected checked exceptions * @return the result of future.get() * @throws CancellationException * if the computation was canceled * @throws InterruptedException * if the current thread was interrupted while waiting * @throws Exception * if one of the expected exceptions was thrown by the task, it * will be rethrown here * @throws IllegalStateException * if the future task throws a unexpected checked exception */ public static <T> T launderedGet(Future<T> future, Class<?>... expected) throws InterruptedException, Exception { try { return future.get(); } catch (ExecutionException e) { Throwable cause = e.getCause(); for (Class<?> clazz : expected) { if (clazz.isInstance(cause)) { throw (Exception) cause; } } throw launderThrowable(e.getCause()); } } private ExceptionUtils() { throw new AssertionError("non-instantiable"); //$NON-NLS-1$ } }