ProjectAres/Util/core/src/main/java/tc/oc/commons/core/util/ExceptionUtils.java

136 lines
4.4 KiB
Java

package tc.oc.commons.core.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import com.google.common.util.concurrent.UncheckedExecutionException;
public class ExceptionUtils {
public static String formatStackTrace(@Nullable StackTraceElement[] trace) {
return formatStackTrace(trace, Predicates.alwaysFalse());
}
public static String formatStackTrace(@Nullable StackTraceElement[] trace, Predicate<StackTraceElement> skipWhile) {
if(trace == null || trace.length == 0) return "";
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int i = 0;
for(; i < trace.length && skipWhile.test(trace[i]); i++);
for(; i < trace.length; i++) {
pw.println("\tat " + trace[i]);
}
return sw.toString();
}
public static RuntimeException propagate(Throwable e) {
// If exception is not checked, throw it directly
if(e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if(e instanceof Error) {
throw (Error) e;
}
// Unwrap uninteresting wrappers
if(e instanceof InvocationTargetException ||
e instanceof ExecutionException) {
return propagate(e.getCause());
}
// Replace reflection exceptions with their unchecked equivalents
if(e instanceof InstantiationException) {
throw new InstantiationError(e.getMessage());
} else if(e instanceof IllegalAccessException) {
throw new IllegalAccessError(e.getMessage());
} else if(e instanceof NoSuchFieldException) {
throw new NoSuchFieldError(e.getMessage());
} else if(e instanceof NoSuchMethodException) {
throw new NoSuchMethodError(e.getMessage());
} else if(e instanceof ClassNotFoundException) {
throw new NoClassDefFoundError(e.getMessage());
}
// Last resort, use an unchecked wrapper
throw new UncheckedExecutionException(e);
}
public static void propagate(ThrowingRunnable<Throwable> block) {
propagate(() -> {
block.runThrows();
return null;
});
}
public static <T> T propagate(ThrowingSupplier<T, Throwable> block) {
try {
return block.getThrows();
} catch(Throwable e) {
throw propagate(e);
}
}
public static <E extends Throwable> void propagate(Class<E> ex, ThrowingRunnable<Throwable> block) throws E {
propagate(ex, () -> {
block.runThrows();
return null;
});
}
public static <T, E extends Throwable> T propagate(Class<E> ex, ThrowingSupplier<T, Throwable> block) throws E {
try {
return block.getThrows();
} catch(Throwable e) {
if(ex.isInstance(e)) {
throw (E) e;
} else {
throw propagate(e);
}
}
}
public static <E extends Throwable> void collect(Class<E> type, Collection<? super E> errors, ThrowingRunnable<? extends E> block) {
try {
block.runThrows();
} catch(Throwable e) {
if(type.isInstance(e)) {
errors.add((E) e);
} else {
throw (RuntimeException) e;
}
}
}
public static <T, E extends Throwable> Optional<T> collect(Class<E> type, Collection<? super E> errors, ThrowingSupplier<T, ? extends E> block) {
try {
return Optional.ofNullable(block.getThrows());
} catch(Throwable e) {
if(type.isInstance(e)) {
errors.add((E) e);
return Optional.empty();
} else {
throw (RuntimeException) e;
}
}
}
public static <T, E extends Throwable> Optional<T> flatCollect(Class<E> type, Collection<? super E> errors, ThrowingSupplier<Optional<T>, ? extends E> block) {
try {
return block.getThrows();
} catch(Throwable e) {
if(type.isInstance(e)) {
errors.add((E) e);
return Optional.empty();
} else {
throw (RuntimeException) e;
}
}
}
}