2022-07-20 13:18:57 +02:00
|
|
|
package fr.pandacube.lib.util;
|
2016-11-26 19:00:43 +01:00
|
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.PrintStream;
|
2022-07-08 01:31:45 +02:00
|
|
|
import java.lang.reflect.InvocationTargetException;
|
2022-07-10 00:55:56 +02:00
|
|
|
import java.nio.charset.StandardCharsets;
|
2022-08-06 22:18:43 +02:00
|
|
|
import java.util.function.BiConsumer;
|
2016-11-26 19:00:43 +01:00
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
/**
|
|
|
|
* Utility class to easily manipulate {@link Throwable}s.
|
|
|
|
*/
|
2016-11-26 19:00:43 +01:00
|
|
|
public class ThrowableUtil {
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a {@link Throwable} into a {@link String} using the {@link Throwable#printStackTrace(PrintStream)} method,
|
|
|
|
* so the returned string contains the full stack trace.
|
|
|
|
* @param t the {@link Throwable}
|
|
|
|
* @return a {@link String} containing the full stack thace of the provided {@link Throwable}.
|
|
|
|
*/
|
2016-11-26 19:00:43 +01:00
|
|
|
public static String stacktraceToString(Throwable t) {
|
|
|
|
if (t == null) return null;
|
2022-07-28 01:13:35 +02:00
|
|
|
try (ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
|
|
PrintStream ps = new PrintStream(os, false, StandardCharsets.UTF_8)) {
|
|
|
|
t.printStackTrace(ps);
|
|
|
|
ps.flush();
|
2022-07-10 00:55:56 +02:00
|
|
|
return os.toString(StandardCharsets.UTF_8);
|
2016-11-26 19:00:43 +01:00
|
|
|
} catch (IOException e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 22:59:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wraps a {@link SupplierException} into a try catch.
|
|
|
|
* @param supp the {@link SupplierException} to run and get the value from.
|
|
|
|
* @return the value returned by the provided supplier.
|
2022-06-23 23:54:52 +02:00
|
|
|
* @throws RuntimeException if the provided {@link SupplierException} throws a checked exception.
|
2022-07-28 01:13:35 +02:00
|
|
|
* @param <T> the type of the returned object
|
2022-02-17 22:59:50 +01:00
|
|
|
*/
|
|
|
|
public static <T> T wrapEx(SupplierException<T> supp) {
|
|
|
|
try {
|
|
|
|
return supp.get();
|
|
|
|
} catch (Exception e) {
|
2022-07-08 01:31:45 +02:00
|
|
|
throw uncheck(e, false);
|
2022-02-17 22:59:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-07-08 01:31:45 +02:00
|
|
|
* Wraps a {@link RunnableException} into a try catch.
|
|
|
|
* @param run the {@link RunnableException} to run.
|
|
|
|
* @throws RuntimeException if the provided {@link RunnableException} throws a checked exception.
|
2022-02-17 22:59:50 +01:00
|
|
|
*/
|
2022-07-08 01:31:45 +02:00
|
|
|
public static void wrapEx(RunnableException run) {
|
|
|
|
try {
|
|
|
|
run.run();
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw uncheck(e, false);
|
|
|
|
}
|
2022-02-17 22:59:50 +01:00
|
|
|
}
|
2022-07-08 01:31:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2022-07-28 01:13:35 +02:00
|
|
|
* Wraps a {@link SupplierException} into a try catch, with special handling of subclasses of
|
|
|
|
* {@link ReflectiveOperationException}.
|
2022-07-08 01:31:45 +02:00
|
|
|
* @param supp the {@link SupplierException} to run and get the value from.
|
|
|
|
* @return the value returned by the provided supplier.
|
|
|
|
* @throws RuntimeException if the provided {@link SupplierException} throws a checked exception.
|
2022-07-28 01:13:35 +02:00
|
|
|
* @param <T> the type of the returned object
|
2022-07-08 01:31:45 +02:00
|
|
|
*/
|
|
|
|
public static <T> T wrapReflectEx(SupplierException<T> supp) {
|
|
|
|
try {
|
|
|
|
return supp.get();
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw uncheck(e, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 22:59:50 +01:00
|
|
|
/**
|
2022-07-28 01:13:35 +02:00
|
|
|
* Wraps a {@link RunnableException} into a try catch with special handling of subclasses of
|
|
|
|
* {@link ReflectiveOperationException}.
|
2022-02-17 22:59:50 +01:00
|
|
|
* @param run the {@link RunnableException} to run.
|
2022-06-23 23:54:52 +02:00
|
|
|
* @throws RuntimeException if the provided {@link RunnableException} throws a checked exception.
|
2022-02-17 22:59:50 +01:00
|
|
|
*/
|
2022-07-08 01:31:45 +02:00
|
|
|
public static void wrapReflectEx(RunnableException run) {
|
2022-02-17 22:59:50 +01:00
|
|
|
try {
|
|
|
|
run.run();
|
|
|
|
} catch (Exception e) {
|
2022-07-08 01:31:45 +02:00
|
|
|
throw uncheck(e, true);
|
2022-02-17 22:59:50 +01:00
|
|
|
}
|
|
|
|
}
|
2022-07-08 01:31:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-07 00:40:08 +02:00
|
|
|
|
|
|
|
private static RuntimeException uncheck(Throwable t, boolean convertReflectionExceptionToError) {
|
|
|
|
if (t instanceof Error er) {
|
|
|
|
throw er;
|
|
|
|
}
|
|
|
|
if (t instanceof RuntimeException re)
|
|
|
|
return re;
|
|
|
|
|
|
|
|
if (convertReflectionExceptionToError) {
|
|
|
|
Error er = null;
|
|
|
|
if (t instanceof ClassNotFoundException ce) {
|
|
|
|
er = new NoClassDefFoundError();
|
|
|
|
er.initCause(ce);
|
|
|
|
}
|
|
|
|
else if (t instanceof IllegalAccessException ce) {
|
|
|
|
er = new IllegalAccessError();
|
|
|
|
er.initCause(ce);
|
|
|
|
}
|
|
|
|
else if (t instanceof NoSuchFieldException ce) {
|
|
|
|
er = new NoSuchFieldError();
|
|
|
|
er.initCause(ce);
|
|
|
|
}
|
|
|
|
else if (t instanceof NoSuchMethodException ce) {
|
|
|
|
er = new NoSuchMethodError();
|
|
|
|
er.initCause(ce);
|
|
|
|
}
|
|
|
|
else if (t instanceof InstantiationException ce) {
|
|
|
|
er = new InstantiationError();
|
|
|
|
er.initCause(ce);
|
|
|
|
}
|
|
|
|
if (er != null)
|
|
|
|
throw er;
|
|
|
|
|
|
|
|
if (t instanceof InvocationTargetException ce) {
|
|
|
|
Throwable cause = ce.getCause();
|
|
|
|
return uncheck(cause, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new RuntimeException(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-08 01:31:45 +02:00
|
|
|
/**
|
2022-07-28 01:13:35 +02:00
|
|
|
* A supplier that can possibly throw a checked exception.
|
2022-07-08 01:31:45 +02:00
|
|
|
*/
|
|
|
|
@FunctionalInterface
|
2022-08-06 22:18:43 +02:00
|
|
|
public interface SupplierException<T> { // TODO make exception type generic
|
2022-07-28 01:13:35 +02:00
|
|
|
/**
|
|
|
|
* Gets a result.
|
|
|
|
* @return a result.
|
|
|
|
* @throws Exception if implementation failed to run.
|
|
|
|
*/
|
2022-07-10 00:55:56 +02:00
|
|
|
T get() throws Exception;
|
2022-07-08 01:31:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2022-07-28 01:13:35 +02:00
|
|
|
* A runnable that can possibly throw a checked exception.
|
2022-07-08 01:31:45 +02:00
|
|
|
*/
|
|
|
|
@FunctionalInterface
|
2022-08-06 22:18:43 +02:00
|
|
|
public interface RunnableException { // TODO make exception type generic
|
2022-07-28 01:13:35 +02:00
|
|
|
/**
|
|
|
|
* Run any code implemented.
|
|
|
|
* @throws Exception if implementation failed to run.
|
|
|
|
*/
|
2022-07-10 00:55:56 +02:00
|
|
|
void run() throws Exception;
|
2022-07-08 01:31:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-06 22:18:43 +02:00
|
|
|
/**
|
|
|
|
* A predicate that can possibly throw a checked exception.
|
|
|
|
*/
|
|
|
|
@FunctionalInterface
|
|
|
|
public interface PredicateException<T, E extends Exception> {
|
|
|
|
/**
|
|
|
|
* Test the predicate on the specified value.
|
|
|
|
* @param value the value to test against.
|
|
|
|
* @return the result of the test.
|
|
|
|
* @throws E if implementation failed to run.
|
|
|
|
*/
|
|
|
|
boolean test(T value) throws E;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A function that can possibly throw a checked exception.
|
|
|
|
*/
|
|
|
|
public interface ToIntBiFunctionException<T, U, E extends Exception> {
|
|
|
|
/**
|
|
|
|
* Run on the specified parameters to return an int value.
|
|
|
|
* @param t the first parameter of the function.
|
|
|
|
* @param u the second parameter of the function.
|
|
|
|
* @return the result of the function.
|
|
|
|
* @throws E if the function fails.
|
|
|
|
*/
|
|
|
|
int applyAsInt(T t, U u) throws E;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A consumer that can possibly throw a checked exception.
|
|
|
|
*/
|
2022-08-07 00:40:08 +02:00
|
|
|
public interface BiConsumerException<T, U, E extends Exception> {
|
2022-08-06 22:18:43 +02:00
|
|
|
/**
|
|
|
|
* Run the consumer on the specified parameters.
|
|
|
|
* @param t the first parameter of the consumer.
|
|
|
|
* @param u the second parameter of the consumer.
|
|
|
|
* @throws E if the function fails.
|
|
|
|
*/
|
|
|
|
void accept(T t, U u) throws E;
|
|
|
|
}
|
2022-02-17 22:59:50 +01:00
|
|
|
|
2016-11-26 19:00:43 +01:00
|
|
|
}
|