IuException.java
/*
* Copyright © 2025 Indiana University
* All rights reserved.
*
* BSD 3-Clause License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package edu.iu;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationTargetException;
/**
* Exception handling utilities.
*/
public final class IuException {
/**
* Expects a {@link Throwable} to be an (unchecked) {@link RuntimeException}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable} or one or more {@link Exception checked exceptions} are
* thrown from a downstream invocation, but a {@link Exception checked
* exception} <em>must not</em> be thrown from the interface being implemented
* and no special handling is specified.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.unchecked(e);
* }
* </pre>
*
* @param throwable Any {@link Throwable}
* @return {@code throwable} if {@link RuntimeException}
* @throws IllegalStateException if {@code throwable} is a {@link Exception
* checked exception} or {@link Throwable custom
* throwable}
* @throws Error if {@code throwable} is an {@link Error}
*/
public static RuntimeException unchecked(Throwable throwable) throws IllegalStateException, Error {
return unchecked(throwable, (String) null);
}
/**
* Expects a {@link Throwable} to be an (unchecked) {@link RuntimeException}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable} or one or more {@link Exception checked exceptions} are
* thrown from a downstream invocation, but a {@link Exception checked
* exception} <em>must not</em> be thrown from the interface being implemented
* and no special handling is specified.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.unchecked(e);
* }
* </pre>
*
* @param throwable Any {@link Throwable}
* @param message Message to use with {@link IllegalStateException} if
* throwable is not a {@link RuntimeException} or {@link Error}
* @return {@code throwable} if {@link RuntimeException}
* @throws IllegalStateException if {@code throwable} is a {@link Exception
* checked exception} or {@link Throwable custom
* throwable}
* @throws Error if {@code throwable} is an {@link Error}
*/
public static RuntimeException unchecked(Throwable throwable, String message) throws IllegalStateException, Error {
if (throwable instanceof RuntimeException)
return (RuntimeException) throwable;
if (throwable instanceof Error)
throw (Error) throwable;
throw new IllegalStateException(message, throwable);
}
/**
* Expects a {@link Throwable} to be a {@link Exception checked exception}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable} is thrown from a downstream invocation, but only
* {@link Exception exception} <em>may</em> be thrown from the interface being
* implemented and special handling is not specified for {@link Throwable custom
* throwables}.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.checked(e);
* }
* </pre>
*
* @param throwable Any {@link Throwable}
* @return {@code throwable} if {@link Exception}
* @throws IllegalStateException if {@code throwable} is a {@link Throwable
* custom throwable}
* @throws Error if {@code throwable} is an {@link Error}
*/
public static Exception checked(Throwable throwable) throws Error, IllegalStateException {
if (throwable instanceof Exception)
return (Exception) throwable;
else if (throwable instanceof Error)
throw (Error) throwable;
throw new IllegalStateException(throwable);
}
/**
* Expects a {@link Throwable} to be a specific {@link Exception checked
* exception}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable}, {@link Exception}, or specific {@link Exception checked
* exceptions} are thrown from a downstream invocation, but at least one of
* these <em>must not</em> be thrown from the interface being implemented and
* special handling is not specified for the unexpected {@link Throwable
* throwable types}.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.checked(e, ACheckedException.class);
* }
* </pre>
*
* @param <T> Expected exception type
*
* @param throwable Any {@link Throwable}
* @param expectedExceptionClass Expected exception class
* @return {@code throwable} if {@code instanceof T}
*
* @throws RuntimeException if {@code throwable} is a
* {@link RuntimeException}
* @throws Error if {@code throwable} is an {@link Error}
* @throws IllegalStateException if {@code throwable} is custom or a
* {@link Exception checked exception} other than
* {@code T}
*/
public static <T extends Exception> T checked(Throwable throwable, Class<T> expectedExceptionClass)
throws RuntimeException, Error, IllegalStateException {
if (expectedExceptionClass.isInstance(throwable))
return expectedExceptionClass.cast(throwable);
else if (throwable instanceof Error)
throw (Error) throwable;
else if (throwable instanceof RuntimeException)
throw (RuntimeException) throwable;
throw new IllegalStateException(throwable);
}
/**
* Expects a {@link Throwable} to be a specific {@link Exception checked
* exception}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable}, {@link Exception}, or specific {@link Exception checked
* exceptions} are thrown from a downstream invocation, but at least one of
* these <em>must not</em> be thrown from the interface being implemented and
* special handling is not specified for the unexpected {@link Throwable
* throwable types}.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.checked(e, ACheckedException.class, AnotherCheckedException.class);
* }
* </pre>
*
* @param <T1> Expected exception type
* @param <T2> Additional exception type that <em>may</em> be
* thrown
*
* @param throwable Any {@link Throwable}
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Additional exception class that <em>may</em>
* be thrown
* @return {@code throwable} if {@code instanceof T1}
* @throws T2 if {@code throwable} is {@code T2}
* @throws RuntimeException if {@code throwable} is a
* {@link RuntimeException}
* @throws Error if {@code throwable} is an {@link Error}
* @throws IllegalStateException if {@code throwable} is custom or a
* {@link Exception checked exception} other than
* {@code T} be thrown
*/
public static <T1 extends Exception, T2 extends Exception> T1 checked(Throwable throwable,
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2)
throws T2, RuntimeException, Error, IllegalStateException {
if (expectedExceptionClass1.isInstance(throwable))
return expectedExceptionClass1.cast(throwable);
else if (expectedExceptionClass2.isInstance(throwable))
throw expectedExceptionClass2.cast(throwable);
else if (throwable instanceof RuntimeException)
throw (RuntimeException) throwable;
else if (throwable instanceof Error)
throw (Error) throwable;
throw new IllegalStateException(throwable);
}
/**
* Expects a {@link Throwable} to be a specific {@link Exception checked
* exception}.
*
* <p>
* This method <em>may</em> be used as an exception handler in situations where
* {@link Throwable}, {@link Exception}, or specific {@link Exception checked
* exceptions} are thrown from a downstream invocation, but at least one of
* these <em>must not</em> be thrown from the interface being implemented and
* special handling is not specified for the unexpected {@link Throwable
* throwable types}.
* </p>
*
* <pre>
* try {
* // something unsafe
* } catch (Throwable e) {
* throw IuException.checked(e, ACheckedException.class, AnotherCheckedException.class,
* YetAnotherCheckedException.class);
* }
* </pre>
*
* @param <T1> Expected exception type
* @param <T2> Additional exception type that <em>may</em> be
* thrown
* @param <T3> Additional exception type that <em>may</em> be
* thrown
*
* @param throwable Any {@link Throwable}
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Additional exception class that <em>may</em>
* be thrown
* @param expectedExceptionClass3 Additional exception class that <em>may</em>
* be thrown
* @return {@code throwable} if {@code instanceof T1}
* @throws T2 if {@code throwable} is {@code T2}
* @throws T3 if {@code throwable} is {@code T3}
* @throws RuntimeException if {@code throwable} is a
* {@link RuntimeException}
* @throws Error if {@code throwable} is an {@link Error}
* @throws IllegalStateException if {@code throwable} is custom or a
* {@link Exception checked exception} other than
* {@code T} be thrown
*/
public static <T1 extends Exception, T2 extends Exception, T3 extends Exception> T1 checked(Throwable throwable,
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3)
throws T2, T3, RuntimeException, Error, IllegalStateException {
if (expectedExceptionClass1.isInstance(throwable))
return expectedExceptionClass1.cast(throwable);
else if (expectedExceptionClass2.isInstance(throwable))
throw expectedExceptionClass2.cast(throwable);
else if (expectedExceptionClass3.isInstance(throwable))
throw expectedExceptionClass3.cast(throwable);
else if (throwable instanceof RuntimeException)
throw (RuntimeException) throwable;
else if (throwable instanceof Error)
throw (Error) throwable;
throw new IllegalStateException(throwable);
}
/**
* Gracefully invokes a supplier assumed to wrap {@link Executable invocation}.
*
* <p>
* Handles {@link InvocationTargetException} by unwrapping the cause and
* re-throwing.
* </p>
* <p>
* Handles other exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <R> result type
* @param supplier {@link UnsafeSupplier} assumed to wrap {@link Executable
* invocation}.
* @return result
*/
public static <R> R uncheckedInvocation(UnsafeSupplier<R> supplier) {
try {
try {
return supplier.get();
} catch (InvocationTargetException e) {
throw e.getCause();
}
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully invokes a {@link Executable method or constructor}.
*
* <p>
* Handles {@link InvocationTargetException} by unwrapping the cause and
* re-throwing.
* </p>
* <p>
* Handles other exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <R> result type
* @param supplier {@link UnsafeSupplier} assumed to wrap {@link Executable
* invocation}.
* @return result
* @throws Exception If invocation fails
*/
public static <R> R checkedInvocation(UnsafeSupplier<R> supplier) throws Exception {
try {
try {
return supplier.get();
} catch (InvocationTargetException e) {
throw e.getCause();
}
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully invokes a {@link Executable method or constructor}.
*
* <p>
* Handles {@link InvocationTargetException} by unwrapping the cause and
* re-throwing.
* </p>
* <p>
* Handles other exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <R> result type
* @param <T> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param supplier {@link UnsafeSupplier} assumed to wrap
* {@link Executable invocation}.
* @return result
*
* @throws T If invocation fails
*/
public static <R, T extends Exception> R checkedInvocation(Class<T> expectedExceptionClass,
UnsafeSupplier<R> supplier) throws T {
try {
try {
return supplier.get();
} catch (InvocationTargetException e) {
throw e.getCause();
}
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully invokes a {@link Executable method or constructor}.
*
* <p>
* Handles {@link InvocationTargetException} by unwrapping the cause and
* re-throwing.
* </p>
* <p>
* Handles other exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param supplier {@link UnsafeSupplier} assumed to wrap
* {@link Executable invocation}.
* @return result
* @throws T1 If invocation fails
* @throws T2 If invocation fails
*/
public static <R, T1 extends Exception, T2 extends Exception> R checkedInvocation(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, UnsafeSupplier<R> supplier) throws T1, T2 {
try {
try {
return supplier.get();
} catch (InvocationTargetException e) {
throw e.getCause();
}
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully invokes a {@link Executable method or constructor}.
*
* <p>
* Handles {@link InvocationTargetException} by unwrapping the cause and
* re-throwing.
* </p>
* <p>
* Handles other exceptions via
* {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param supplier {@link UnsafeSupplier} assumed to wrap
* {@link Executable invocation}.
* @return result
* @throws T1 If invocation fails
* @throws T2 If invocation fails
* @throws T3 If invocation fails
*/
public static <R, T1 extends Exception, T2 extends Exception, T3 extends Exception> R checkedInvocation(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
UnsafeSupplier<R> supplier) throws T1, T2, T3 {
try {
try {
return supplier.get();
} catch (InvocationTargetException e) {
throw e.getCause();
}
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param runnable Any {@link UnsafeRunnable}
*/
public static void unchecked(UnsafeRunnable runnable) {
unchecked(runnable, (String) null);
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param runnable Any {@link UnsafeRunnable}
* @param message message for use with {@link #unchecked(Throwable, String)}
*/
public static void unchecked(UnsafeRunnable runnable, String message) {
try {
runnable.run();
} catch (Throwable e) {
throw unchecked(e, message);
}
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param runnable Any {@link UnsafeRunnable}
* @throws Exception If thrown by {@link UnsafeRunnable#run()}
*/
public static void checked(UnsafeRunnable runnable) throws Exception {
try {
runnable.run();
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> Expected exception type
*
* @param expectedExceptionClass Expected exception class
*
* @param runnable Any {@link UnsafeRunnable}
* @throws T If thrown by {@link UnsafeRunnable#run()}
*/
public static <T extends Exception> void checked(Class<T> expectedExceptionClass, UnsafeRunnable runnable)
throws T {
try {
runnable.run();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
*
* @param runnable Any {@link UnsafeRunnable}
* @throws T1 If thrown by {@link UnsafeRunnable#run()}
* @throws T2 If thrown by {@link UnsafeRunnable#run()}
*/
public static <T1 extends Exception, T2 extends Exception> void checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, UnsafeRunnable runnable) throws T1, T2 {
try {
runnable.run();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully runs an {@link UnsafeRunnable}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
*
* @param runnable Any {@link UnsafeRunnable}
* @throws T1 If thrown by {@link UnsafeRunnable#run()}
* @throws T2 If thrown by {@link UnsafeRunnable#run()}
* @throws T3 If thrown by {@link UnsafeRunnable#run()}
*/
public static <T1 extends Exception, T2 extends Exception, T3 extends Exception> void checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
UnsafeRunnable runnable) throws T1, T2, T3 {
try {
runnable.run();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> result type
*
* @param supplier Any {@link UnsafeSupplier}
* @return result
*/
public static <T> T unchecked(UnsafeSupplier<T> supplier) {
return unchecked(supplier, (String) null);
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> result type
*
* @param supplier Any {@link UnsafeSupplier}
* @param message Message to use with {@link #unchecked(Throwable, String)}
* @return result
*/
public static <T> T unchecked(UnsafeSupplier<T> supplier, String message) {
try {
return supplier.get();
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <T> result type
*
* @param supplier Any {@link UnsafeSupplier}
* @return result
* @throws Exception If thrown by {@link UnsafeSupplier#get()}
*/
public static <T> T checked(UnsafeSupplier<T> supplier) throws Exception {
try {
return supplier.get();
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> result type
* @param <T1> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param supplier Any {@link UnsafeSupplier}
* @return result
* @throws T1 If thrown by {@link UnsafeSupplier#get()}
*/
public static <T, T1 extends Exception> T checked(Class<T1> expectedExceptionClass, UnsafeSupplier<T> supplier)
throws T1 {
try {
return supplier.get();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param supplier Any {@link UnsafeSupplier}
* @return result
* @throws T1 If thrown by {@link UnsafeSupplier#get()}
* @throws T2 If thrown by {@link UnsafeSupplier#get()}
*/
public static <T, T1 extends Exception, T2 extends Exception> T checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, UnsafeSupplier<T> supplier) throws T1, T2 {
try {
return supplier.get();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully gets from an {@link UnsafeSupplier}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param supplier Any {@link UnsafeSupplier}
* @return result
* @throws T1 If thrown by {@link UnsafeSupplier#get()}
* @throws T2 If thrown by {@link UnsafeSupplier#get()}
* @throws T3 If thrown by {@link UnsafeSupplier#get()}
*/
public static <T, T1 extends Exception, T2 extends Exception, T3 extends Exception> T checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
UnsafeSupplier<T> supplier) throws T1, T2, T3 {
try {
return supplier.get();
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeConsumer}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> argument type
*
* @param argument Argument for {@link UnsafeConsumer#accept(Object)}
* @param consumer Any {@link UnsafeConsumer}
*/
public static <T> void unchecked(T argument, UnsafeConsumer<T> consumer) {
try {
consumer.accept(argument);
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <T> argument type
*
* @param argument Argument for {@link UnsafeConsumer#accept(Object)}
* @param consumer Any {@link UnsafeConsumer}
* @throws Exception If thrown by {@link UnsafeConsumer#accept(Object)}
*/
public static <T> void checked(T argument, UnsafeConsumer<T> consumer) throws Exception {
try {
consumer.accept(argument);
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> argument type
* @param <T1> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param argument Argument for
* {@link UnsafeConsumer#accept(Object)}
* @param consumer Any {@link UnsafeConsumer}
*
* @throws T1 If thrown by {@link UnsafeConsumer#accept(Object)}
*/
public static <T, T1 extends Exception> void checked(Class<T1> expectedExceptionClass, T argument,
UnsafeConsumer<T> consumer) throws T1 {
try {
consumer.accept(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T> argument type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param argument Argument for
* {@link UnsafeConsumer#accept(Object)}
* @param consumer Any {@link UnsafeConsumer}
*
* @throws T1 If thrown by {@link UnsafeConsumer#accept(Object)}
* @throws T2 If thrown by {@link UnsafeConsumer#accept(Object)}
*/
public static <T, T1 extends Exception, T2 extends Exception> void checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, T argument, UnsafeConsumer<T> consumer) throws T1, T2 {
try {
consumer.accept(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T> argument type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param argument Argument for
* {@link UnsafeConsumer#accept(Object)}
* @param consumer Any {@link UnsafeConsumer}
*
* @throws T1 If thrown by {@link UnsafeConsumer#accept(Object)}
* @throws T2 If thrown by {@link UnsafeConsumer#accept(Object)}
* @throws T3 If thrown by {@link UnsafeConsumer#accept(Object)}
*/
public static <T, T1 extends Exception, T2 extends Exception, T3 extends Exception> void checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
T argument, UnsafeConsumer<T> consumer) throws T1, T2, T3 {
try {
consumer.accept(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully applies an {@link UnsafeFunction}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> argument type
* @param <R> result type
*
* @param argument Argument to {@link UnsafeFunction#apply(Object)}
* @param function Any {@link UnsafeFunction}
* @return result
*/
public static <T, R> R unchecked(T argument, UnsafeFunction<T, R> function) {
try {
return function.apply(argument);
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully applies an {@link UnsafeFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <T> argument type
* @param <R> result type
*
* @param argument Argument to {@link UnsafeFunction#apply(Object)}
* @param function Any {@link UnsafeFunction}
* @return result
* @throws Exception If thrown by {@link UnsafeFunction#apply(Object)}
*/
public static <T, R> R checked(T argument, UnsafeFunction<T, R> function) throws Exception {
try {
return function.apply(argument);
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully applies an {@link UnsafeFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> argument type
* @param <R> result type
* @param <T1> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param argument Argument to
* {@link UnsafeFunction#apply(Object)}
* @param function Any {@link UnsafeFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeFunction#apply(Object)}
*/
public static <T, R, T1 extends Exception> R checked(Class<T1> expectedExceptionClass, T argument,
UnsafeFunction<T, R> function) throws T1 {
try {
return function.apply(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully applies an {@link UnsafeFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T> argument type
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param argument Argument to
* {@link UnsafeFunction#apply(Object)}
* @param function Any {@link UnsafeFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeFunction#apply(Object)}
* @throws T2 If thrown by {@link UnsafeFunction#apply(Object)}
*/
public static <T, R, T1 extends Exception, T2 extends Exception> R checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, T argument, UnsafeFunction<T, R> function) throws T1, T2 {
try {
return function.apply(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully applies an {@link UnsafeFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T> argument type
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param argument Argument to
* {@link UnsafeFunction#apply(Object)}
* @param function Any {@link UnsafeFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeFunction#apply(Object)}
* @throws T2 If thrown by {@link UnsafeFunction#apply(Object)}
* @throws T3 If thrown by {@link UnsafeFunction#apply(Object)}
*/
public static <T, R, T1 extends Exception, T2 extends Exception, T3 extends Exception> R checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
T argument, UnsafeFunction<T, R> function) throws T1, T2, T3 {
try {
return function.apply(argument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeBiConsumer}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
*
* @param firstArgument First argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param secondArgument Second argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param consumer Any {@link UnsafeBiConsumer}
*/
public static <T, U> void unchecked(T firstArgument, U secondArgument, UnsafeBiConsumer<T, U> consumer) {
try {
consumer.accept(firstArgument, secondArgument);
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeBiConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
*
* @param firstArgument Argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param secondArgument Second argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param consumer Any {@link UnsafeBiConsumer}
* @throws Exception If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
*/
public static <T, U> void checked(T firstArgument, U secondArgument, UnsafeBiConsumer<T, U> consumer)
throws Exception {
try {
consumer.accept(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeBiConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <T1> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param firstArgument Argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param secondArgument Second argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param consumer Any {@link UnsafeBiConsumer}
*
* @throws T1 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
*/
public static <T, U, T1 extends Exception> void checked(Class<T1> expectedExceptionClass, T firstArgument,
U secondArgument, UnsafeBiConsumer<T, U> consumer) throws T1 {
try {
consumer.accept(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeBiConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param firstArgument Argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param secondArgument Second argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param consumer Any {@link UnsafeBiConsumer}
*
* @throws T1 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
* @throws T2 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
*/
public static <T, U, T1 extends Exception, T2 extends Exception> void checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, T firstArgument, U secondArgument, UnsafeBiConsumer<T, U> consumer)
throws T1, T2 {
try {
consumer.accept(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully supplies a value to an {@link UnsafeBiConsumer}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param firstArgument Argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param secondArgument Second argument for
* {@link UnsafeBiConsumer#accept(Object,Object)}
* @param consumer Any {@link UnsafeBiConsumer}
*
* @throws T1 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
* @throws T2 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
* @throws T3 If thrown by {@link UnsafeBiConsumer#accept(Object,Object)}
*/
public static <T, U, T1 extends Exception, T2 extends Exception, T3 extends Exception> void checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
T firstArgument, U secondArgument, UnsafeBiConsumer<T, U> consumer) throws T1, T2, T3 {
try {
consumer.accept(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully applies an {@link UnsafeBiFunction}.
*
* <p>
* Handles exceptions via {@link #unchecked(Throwable)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <R> result type
*
* @param firstArgument First argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param secondArgument Second argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param function Any {@link UnsafeFunction}
* @return result
*/
public static <T, U, R> R unchecked(T firstArgument, U secondArgument, UnsafeBiFunction<T, U, R> function) {
try {
return function.apply(firstArgument, secondArgument);
} catch (Throwable e) {
throw unchecked(e);
}
}
/**
* Gracefully applies an {@link UnsafeBiFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <R> result type
*
* @param firstArgument First argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param secondArgument Second argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param function Any {@link UnsafeBiFunction}
* @return result
* @throws Exception If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
*/
public static <T, U, R> R checked(T firstArgument, U secondArgument, UnsafeBiFunction<T, U, R> function)
throws Exception {
try {
return function.apply(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e);
}
}
/**
* Gracefully applies an {@link UnsafeBiFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <R> result type
* @param <T1> Expected exception type
*
* @param expectedExceptionClass Expected exception class
* @param firstArgument First argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param secondArgument Second argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param function Any {@link UnsafeBiFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
*/
public static <T, U, R, T1 extends Exception> R checked(Class<T1> expectedExceptionClass, T firstArgument,
U secondArgument, UnsafeBiFunction<T, U, R> function) throws T1 {
try {
return function.apply(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass);
}
}
/**
* Gracefully applies an {@link UnsafeBiFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param firstArgument First argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param secondArgument Second argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param function Any {@link UnsafeBiFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
* @throws T2 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
*/
public static <T, U, R, T1 extends Exception, T2 extends Exception> R checked(Class<T1> expectedExceptionClass1,
Class<T2> expectedExceptionClass2, T firstArgument, U secondArgument, UnsafeBiFunction<T, U, R> function)
throws T1, T2 {
try {
return function.apply(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2);
}
}
/**
* Gracefully applies an {@link UnsafeBiFunction}.
*
* <p>
* Handles exceptions via {@link #checked(Throwable, Class, Class, Class)}.
* </p>
*
* @param <T> first argument type
* @param <U> second argument type
* @param <R> result type
* @param <T1> Expected exception type
* @param <T2> Expected exception type
* @param <T3> Expected exception type
*
* @param expectedExceptionClass1 Expected exception class
* @param expectedExceptionClass2 Expected exception class
* @param expectedExceptionClass3 Expected exception class
* @param firstArgument First argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param secondArgument Second argument to
* {@link UnsafeBiFunction#apply(Object, Object)}
* @param function Any {@link UnsafeBiFunction}
* @return result
* @throws T1 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
* @throws T2 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
* @throws T3 If thrown by {@link UnsafeBiFunction#apply(Object, Object)}
*/
public static <T, U, R, T1 extends Exception, T2 extends Exception, T3 extends Exception> R checked(
Class<T1> expectedExceptionClass1, Class<T2> expectedExceptionClass2, Class<T3> expectedExceptionClass3,
T firstArgument, U secondArgument, UnsafeBiFunction<T, U, R> function) throws T1, T2, T3 {
try {
return function.apply(firstArgument, secondArgument);
} catch (Throwable e) {
throw checked(e, expectedExceptionClass1, expectedExceptionClass2, expectedExceptionClass3);
}
}
/**
* Gracefully initializes a component that depends on an {@link AutoCloseable}
* resource, {@link AutoCloseable#close() closing} the resource and suppressing
* any close errors before rethrowing a checked exception if the component fails
* to initialize.
*
* <p>
* If no exception or error is thrown by {@code initializer}, then the resource
* remains open, and becomes the responsibility of the initialized component to
* close when finished with it.
* </p>
*
* @param <T> {@link AutoCloseable} resource type
* @param <R> {@link UnsafeFunction} dependent component type
*
* @param resource Open resource
* @param initializer {@link UnsafeFunction} for initializing the resource
* @return {@code resource}, after successfully invoking
* {@code initializationConsumer}
* @throws Exception If thrown from by {@code initializationConsumer}
*/
public static <T extends AutoCloseable, R> R initialize(T resource, UnsafeFunction<T, R> initializer)
throws Exception {
try {
return initializer.apply(resource);
} catch (Throwable e) {
suppress(e, resource::close);
throw checked(e);
}
}
/**
* Runs an {@link UnsafeRunnable} and adds any exception thrown as suppressed by
* an another exception.
*
* <p>
* This is useful for adding clean-up tasks to error handling routines related
* to failed initialization of closeable resources.
* </p>
*
* @param throwable Throwable that will
* {@link Throwable#addSuppressed(Throwable) suppress}
* exceptions thrown from {@code runnable}.
* @param runnable {@link UnsafeRunnable}; will be run, and any exceptions
* thrown will be suppressed by {@code throwable}
* @return throwable if non-null; the exception thrown from runnable or null if
* no exception was thrown
*/
public static Throwable suppress(Throwable throwable, UnsafeRunnable runnable) {
try {
runnable.run();
} catch (Throwable e) {
if (throwable == null)
throwable = e;
else
throwable.addSuppressed(e);
}
return throwable;
}
/**
* Runs a sequence of tasks with error suppression.
*
* <p>
* All tasks are guaranteed to run, but not guaranteed to finish. After all
* tasks have run, the first error encountered will be thrown; all additional
* errors will be suppressed.
* </p>
*
* @param tasks tasks to run
* @throws Throwable from the first task the fails in error
*/
public static void suppress(UnsafeRunnable... tasks) throws Throwable {
suppress(IuIterable.iter(tasks));
}
/**
* Runs a sequence of tasks with error suppression.
*
* <p>
* All tasks are guaranteed to run, but not guaranteed to finish. After all
* tasks have run, the first error encountered will be thrown; all additional
* errors will be suppressed.
* </p>
*
* @param tasks tasks to run
* @throws Throwable from the first task the fails in error
*/
public static void suppress(Iterable<UnsafeRunnable> tasks) throws Throwable {
Throwable e = null;
for (final var task : tasks)
e = suppress(e, task);
if (e != null)
throw e;
}
/**
* Gets a stack trace from a {@link Throwable} as a {@link String}.
*
* @param e {@link Throwable}
* @return {@link String} representation of the stack trace.
*/
public static String trace(Throwable e) {
final var w = new StringWriter();
try (final var pw = new PrintWriter(w)) {
e.printStackTrace(pw);
}
return w.toString();
}
private IuException() {
}
}