一、前言
关于apache的commons-lang包中对org.apache.commons.lang3.exception.ExceptionUtils异常工具类对获取默认异常方法数组getDefaultCauseMethodNames、获取异常发生次数getThrowableCount、查询位置indexOfThrowable、打印流输出printRootCauseStackTrace、将异常Throwable转为字符串getStackTrace、获取根节点异常轨迹错误字符串getRootCauseMessage等。
二、源码说明
源码中 org.apache.commons.lang3.ArrayUtils 、org.apache.commons.lang3.ClassUtils、org.apache.commons.lang3.Validate>分别参加其他更多文章
package org.apache.commons.lang3.exception;@b@@b@import java.io.PrintStream;@b@import java.io.PrintWriter;@b@import java.io.StringWriter;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import java.util.ArrayList;@b@import java.util.List;@b@import java.util.StringTokenizer;@b@import org.apache.commons.lang3.ArrayUtils;@b@import org.apache.commons.lang3.ClassUtils;@b@import org.apache.commons.lang3.StringUtils;@b@import org.apache.commons.lang3.SystemUtils;@b@@b@public class ExceptionUtils@b@{@b@ static final String WRAPPED_MARKER = " [wrapped] ";@b@ private static final String[] CAUSE_METHOD_NAMES = { "getCause", "getNextException", "getTargetException", "getException", "getSourceException", "getRootCause", "getCausedByException", "getNested", "getLinkedException", "getNestedException", "getLinkedCause", "getThrowable" };@b@@b@ @Deprecated@b@ public static String[] getDefaultCauseMethodNames()@b@ {@b@ return ((String[])ArrayUtils.clone(CAUSE_METHOD_NAMES));@b@ }@b@@b@ @Deprecated@b@ public static Throwable getCause(Throwable throwable)@b@ {@b@ return getCause(throwable, CAUSE_METHOD_NAMES);@b@ }@b@@b@ @Deprecated@b@ public static Throwable getCause(Throwable throwable, String[] methodNames)@b@ {@b@ if (throwable == null) {@b@ return null;@b@ }@b@@b@ if (methodNames == null) {@b@ methodNames = CAUSE_METHOD_NAMES;@b@ }@b@@b@ String[] arr$ = methodNames; int len$ = arr$.length; for (int i$ = 0; i$ < len$; ++i$) { String methodName = arr$[i$];@b@ if (methodName != null) {@b@ Throwable cause = getCauseUsingMethodName(throwable, methodName);@b@ if (cause != null)@b@ return cause;@b@ }@b@@b@ }@b@@b@ return null;@b@ }@b@@b@ public static Throwable getRootCause(Throwable throwable)@b@ {@b@ List list = getThrowableList(throwable);@b@ return ((list.size() < 2) ? null : (Throwable)list.get(list.size() - 1));@b@ }@b@@b@ private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName)@b@ {@b@ Method method = null;@b@ try {@b@ method = throwable.getClass().getMethod(methodName, new Class[0]);@b@ }@b@ catch (NoSuchMethodException ignored)@b@ {@b@ }@b@ catch (SecurityException ignored) {@b@ }@b@ if ((method != null) && (Throwable.class.isAssignableFrom(method.getReturnType())))@b@ try {@b@ return ((Throwable)method.invoke(throwable, new Object[0]));@b@ }@b@ catch (IllegalAccessException ignored)@b@ {@b@ }@b@ catch (IllegalArgumentException ignored) {@b@ }@b@ catch (InvocationTargetException ignored) {@b@ }@b@ return null;@b@ }@b@@b@ public static int getThrowableCount(Throwable throwable)@b@ {@b@ return getThrowableList(throwable).size();@b@ }@b@@b@ public static Throwable[] getThrowables(Throwable throwable)@b@ {@b@ List list = getThrowableList(throwable);@b@ return ((Throwable[])list.toArray(new Throwable[list.size()]));@b@ }@b@@b@ public static List<Throwable> getThrowableList(Throwable throwable)@b@ {@b@ List list = new ArrayList();@b@ while ((throwable != null) && (!(list.contains(throwable)))) {@b@ list.add(throwable);@b@ throwable = getCause(throwable);@b@ }@b@ return list;@b@ }@b@@b@ public static int indexOfThrowable(Throwable throwable, Class<?> clazz)@b@ {@b@ return indexOf(throwable, clazz, 0, false);@b@ }@b@@b@ public static int indexOfThrowable(Throwable throwable, Class<?> clazz, int fromIndex)@b@ {@b@ return indexOf(throwable, clazz, fromIndex, false);@b@ }@b@@b@ public static int indexOfType(Throwable throwable, Class<?> type)@b@ {@b@ return indexOf(throwable, type, 0, true);@b@ }@b@@b@ public static int indexOfType(Throwable throwable, Class<?> type, int fromIndex)@b@ {@b@ return indexOf(throwable, type, fromIndex, true);@b@ }@b@@b@ private static int indexOf(Throwable throwable, Class<?> type, int fromIndex, boolean subclass)@b@ {@b@ int i;@b@ if ((throwable == null) || (type == null))@b@ return -1;@b@@b@ if (fromIndex < 0)@b@ fromIndex = 0;@b@@b@ Throwable[] throwables = getThrowables(throwable);@b@ if (fromIndex >= throwables.length)@b@ return -1;@b@@b@ if (subclass)@b@ for (i = fromIndex; i < throwables.length; ++i)@b@ if (type.isAssignableFrom(throwables[i].getClass()))@b@ return i;@b@@b@@b@ else@b@ for (i = fromIndex; i < throwables.length; ++i)@b@ if (type.equals(throwables[i].getClass()))@b@ return i;@b@@b@@b@@b@ return -1;@b@ }@b@@b@ public static void printRootCauseStackTrace(Throwable throwable)@b@ {@b@ printRootCauseStackTrace(throwable, System.err);@b@ }@b@@b@ public static void printRootCauseStackTrace(Throwable throwable, PrintStream stream)@b@ {@b@ if (throwable == null)@b@ return;@b@@b@ if (stream == null)@b@ throw new IllegalArgumentException("The PrintStream must not be null");@b@@b@ String[] trace = getRootCauseStackTrace(throwable);@b@ String[] arr$ = trace; int len$ = arr$.length; for (int i$ = 0; i$ < len$; ++i$) { String element = arr$[i$];@b@ stream.println(element);@b@ }@b@ stream.flush();@b@ }@b@@b@ public static void printRootCauseStackTrace(Throwable throwable, PrintWriter writer)@b@ {@b@ if (throwable == null)@b@ return;@b@@b@ if (writer == null)@b@ throw new IllegalArgumentException("The PrintWriter must not be null");@b@@b@ String[] trace = getRootCauseStackTrace(throwable);@b@ String[] arr$ = trace; int len$ = arr$.length; for (int i$ = 0; i$ < len$; ++i$) { String element = arr$[i$];@b@ writer.println(element);@b@ }@b@ writer.flush();@b@ }@b@@b@ public static String[] getRootCauseStackTrace(Throwable throwable)@b@ {@b@ List trace;@b@ int j;@b@ if (throwable == null)@b@ return ArrayUtils.EMPTY_STRING_ARRAY;@b@@b@ Throwable[] throwables = getThrowables(throwable);@b@ int count = throwables.length;@b@ List frames = new ArrayList();@b@ List nextTrace = getStackFrameList(throwables[(count - 1)]);@b@ for (int i = count; --i >= 0; ) {@b@ trace = nextTrace;@b@ if (i != 0) {@b@ nextTrace = getStackFrameList(throwables[(i - 1)]);@b@ removeCommonFrames(trace, nextTrace);@b@ }@b@ if (i == count - 1)@b@ frames.add(throwables[i].toString());@b@ else@b@ frames.add(" [wrapped] " + throwables[i].toString());@b@@b@ for (j = 0; j < trace.size(); ++j)@b@ frames.add(trace.get(j));@b@ }@b@@b@ return ((String[])frames.toArray(new String[frames.size()]));@b@ }@b@@b@ public static void removeCommonFrames(List<String> causeFrames, List<String> wrapperFrames)@b@ {@b@ if ((causeFrames == null) || (wrapperFrames == null))@b@ throw new IllegalArgumentException("The List must not be null");@b@@b@ int causeFrameIndex = causeFrames.size() - 1;@b@ int wrapperFrameIndex = wrapperFrames.size() - 1;@b@ while ((causeFrameIndex >= 0) && (wrapperFrameIndex >= 0))@b@ {@b@ String causeFrame = (String)causeFrames.get(causeFrameIndex);@b@ String wrapperFrame = (String)wrapperFrames.get(wrapperFrameIndex);@b@ if (causeFrame.equals(wrapperFrame))@b@ causeFrames.remove(causeFrameIndex);@b@@b@ --causeFrameIndex;@b@ --wrapperFrameIndex;@b@ }@b@ }@b@@b@ public static String getStackTrace(Throwable throwable)@b@ {@b@ StringWriter sw = new StringWriter();@b@ PrintWriter pw = new PrintWriter(sw, true);@b@ throwable.printStackTrace(pw);@b@ return sw.getBuffer().toString();@b@ }@b@@b@ public static String[] getStackFrames(Throwable throwable)@b@ {@b@ if (throwable == null)@b@ return ArrayUtils.EMPTY_STRING_ARRAY;@b@@b@ return getStackFrames(getStackTrace(throwable));@b@ }@b@@b@ static String[] getStackFrames(String stackTrace)@b@ {@b@ String linebreak = SystemUtils.LINE_SEPARATOR;@b@ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);@b@ List list = new ArrayList();@b@ while (frames.hasMoreTokens())@b@ list.add(frames.nextToken());@b@@b@ return ((String[])list.toArray(new String[list.size()]));@b@ }@b@@b@ static List<String> getStackFrameList(Throwable t)@b@ {@b@ String stackTrace = getStackTrace(t);@b@ String linebreak = SystemUtils.LINE_SEPARATOR;@b@ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);@b@ List list = new ArrayList();@b@ boolean traceStarted = false;@b@ while (frames.hasMoreTokens()) {@b@ String token = frames.nextToken();@b@@b@ int at = token.indexOf("at");@b@ if ((at != -1) && (token.substring(0, at).trim().isEmpty())) {@b@ traceStarted = true;@b@ list.add(token);@b@ } else if (traceStarted) {@b@ break;@b@ }@b@ }@b@ return list;@b@ }@b@@b@ public static String getMessage(Throwable th)@b@ {@b@ if (th == null)@b@ return "";@b@@b@ String clsName = ClassUtils.getShortClassName(th, null);@b@ String msg = th.getMessage();@b@ return clsName + ": " + StringUtils.defaultString(msg);@b@ }@b@@b@ public static String getRootCauseMessage(Throwable th)@b@ {@b@ Throwable root = getRootCause(th);@b@ root = (root == null) ? th : root;@b@ return getMessage(root);@b@ }@b@}