From 3e143c4a927a3d0a8bb14b9359cb49329d919c60 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sat, 11 Mar 2023 17:00:14 +0100 Subject: [PATCH] StringFormatter: fix exception format --- .../jfronny/commons/StringFormatter.java | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/gitlab/jfronny/commons/StringFormatter.java b/src/main/java/io/gitlab/jfronny/commons/StringFormatter.java index bbfba23..f5a0bd1 100644 --- a/src/main/java/io/gitlab/jfronny/commons/StringFormatter.java +++ b/src/main/java/io/gitlab/jfronny/commons/StringFormatter.java @@ -1,7 +1,7 @@ package io.gitlab.jfronny.commons; -import java.io.*; -import java.util.Locale; +import java.util.*; +import java.util.function.Function; public class StringFormatter { public static String toString(Object o) { @@ -11,20 +11,47 @@ public class StringFormatter { else if (d > 1) return String.format(Locale.US, "%.4f", d); else return String.format(Locale.US, "%s", d); } else if (o instanceof Throwable t) { - try { - return t.getMessage() + getStackTrace(t); - } catch (IOException e) { - return t.toString(); - } + return toString(t, Objects::toString); } else return o.toString(); } - public static String getStackTrace(Throwable t) throws IOException { - try (ByteArrayOutputStream baot = new ByteArrayOutputStream()) { - try (PrintStream ps = new PrintStream(baot, true)) { - t.printStackTrace(ps); - } - return baot.toString(); + public static String toString(Throwable t, Function stringify) { + return stringify.apply(t) + "\n" + getStackTrace(t, stringify); + } + + public static String getStackTrace(Throwable t) { + return getStackTrace(t, Objects::toString); + } + + public static String getStackTrace(Throwable t, Function stringify) { + StringBuilder sb = new StringBuilder(); + getStackTrace(sb, t, new StackTraceElement[0], "", "", Objects.requireNonNull(stringify), new HashSet<>(), true); + return sb.toString(); + } + + private static void getStackTrace(StringBuilder sb, Throwable t, StackTraceElement[] enclosingTrace, String caption, String prefix, Function stringify, Set dejaVu, boolean skipHeader) { + if (!skipHeader) sb.append(prefix).append(caption); + + if (!dejaVu.add(t)) { + sb.append("[CIRCULAR REFERENCE: ").append(stringify.apply(t)).append("]\n"); + return; } + + StackTraceElement[] trace = t.getStackTrace(); + int m = trace.length - 1; + int n = enclosingTrace.length - 1; + while (m >= 0 && n >= 0 && trace[m].equals(enclosingTrace[n])) { + m--; n--; + } + int framesInCommon = trace.length - 1 - m; + + if (!skipHeader) sb.append(stringify.apply(t)).append('\n'); + for (int i = 0; i <= m; i++) sb.append(prefix).append("\tat ").append(trace[i]).append('\n'); + if (framesInCommon != 0) sb.append(prefix).append("\t... ").append(framesInCommon).append(" more").append('\n'); + for (Throwable se : t.getSuppressed()) { + getStackTrace(sb, se, trace, "Suppressed: ", prefix + "\t", stringify, dejaVu, false); + } + Throwable cause = t.getCause(); + if (cause != null) getStackTrace(sb, cause, trace, "Caused by: ", prefix, stringify, dejaVu, false); } }