一、前言
关于cayenne包中org.apache.commons.lang.exception.ExceptionUtils异常处理工具类,获取白名单异常序列、将异常堆栈信息转为字符串、将异常信息匹配为名单定义格式进行输出、判断异常是否指定class对象抛出等。
二、源码说明
package org.apache.commons.lang.exception;@b@@b@import java.io.PrintStream;@b@import java.io.PrintWriter;@b@import java.io.StringWriter;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import java.sql.SQLException;@b@import java.util.ArrayList;@b@import java.util.Arrays;@b@import java.util.LinkedList;@b@import java.util.List;@b@import java.util.StringTokenizer;@b@import org.apache.commons.lang.ArrayUtils;@b@import org.apache.commons.lang.StringUtils;@b@import org.apache.commons.lang.SystemUtils;@b@@b@public class ExceptionUtils@b@{@b@ static final String WRAPPED_MARKER = " [wrapped] ";@b@ private static String[] CAUSE_METHOD_NAMES;@b@ private static final Method THROWABLE_CAUSE_METHOD;@b@@b@ static@b@ {@b@ Method getCauseMethod;@b@ CAUSE_METHOD_NAMES = new String[] { @b@ "getCause", @b@ "getNextException", @b@ "getTargetException", @b@ "getException", @b@ "getSourceException", @b@ "getRootCause", @b@ "getCausedByException", @b@ "getNested", @b@ "getLinkedException", @b@ "getNestedException", @b@ "getLinkedCause", @b@ "getThrowable" };@b@ try@b@ {@b@ getCauseMethod = Throwable.class.getMethod("getCause", null);@b@ } catch (Exception localException) {@b@ getCauseMethod = null;@b@ }@b@ THROWABLE_CAUSE_METHOD = getCauseMethod;@b@ }@b@@b@ public static void addCauseMethodName(String methodName)@b@ {@b@ if ((StringUtils.isNotEmpty(methodName)) && (!(isCauseMethodName(methodName)))) {@b@ List list = getCauseMethodNameList();@b@ if (list.add(methodName))@b@ CAUSE_METHOD_NAMES = toArray(list);@b@ }@b@ }@b@@b@ public static Throwable getCause(Throwable throwable)@b@ {@b@ return getCause(throwable, CAUSE_METHOD_NAMES);@b@ }@b@@b@ public static Throwable getCause(Throwable throwable, String[] methodNames)@b@ {@b@ if (throwable == null)@b@ return null;@b@@b@ Throwable cause = getCauseUsingWellKnownTypes(throwable);@b@ if (cause == null) {@b@ if (methodNames == null)@b@ methodNames = CAUSE_METHOD_NAMES;@b@@b@ for (int i = 0; i < methodNames.length; ++i) {@b@ String methodName = methodNames[i];@b@ if (methodName != null) {@b@ cause = getCauseUsingMethodName(throwable, methodName);@b@ if (cause != null)@b@ break;@b@ }@b@@b@ }@b@@b@ if (cause == null)@b@ cause = getCauseUsingFieldName(throwable, "detail");@b@ }@b@@b@ return cause;@b@ }@b@@b@ private static ArrayList getCauseMethodNameList()@b@ {@b@ return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));@b@ }@b@@b@ private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName)@b@ {@b@ Field field = null;@b@ try {@b@ field = throwable.getClass().getField(fieldName);@b@ } catch (NoSuchFieldException localNoSuchFieldException) {@b@ }@b@ catch (SecurityException localSecurityException) {@b@ }@b@ if ((field != null) && (Throwable.class.isAssignableFrom(field.getType())))@b@ try {@b@ return ((Throwable)field.get(throwable));@b@ } catch (IllegalAccessException localIllegalAccessException) {@b@ }@b@ catch (IllegalArgumentException localIllegalArgumentException) {@b@ }@b@ return null;@b@ }@b@@b@ private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName)@b@ {@b@ Method method = null;@b@ try {@b@ method = throwable.getClass().getMethod(methodName, null);@b@ } catch (NoSuchMethodException localNoSuchMethodException) {@b@ }@b@ catch (SecurityException localSecurityException) {@b@ }@b@ if ((method != null) && (Throwable.class.isAssignableFrom(method.getReturnType())))@b@ try {@b@ return ((Throwable)method.invoke(throwable, ArrayUtils.EMPTY_OBJECT_ARRAY));@b@ } catch (IllegalAccessException localIllegalAccessException) {@b@ } catch (IllegalArgumentException localIllegalArgumentException) {@b@ }@b@ catch (InvocationTargetException localInvocationTargetException) {@b@ }@b@ return null;@b@ }@b@@b@ private static Throwable getCauseUsingWellKnownTypes(Throwable throwable)@b@ {@b@ if (throwable instanceof Nestable)@b@ return ((Nestable)throwable).getCause();@b@ if (throwable instanceof SQLException)@b@ return ((SQLException)throwable).getNextException();@b@ if (throwable instanceof InvocationTargetException)@b@ return ((InvocationTargetException)throwable).getTargetException();@b@@b@ return null;@b@ }@b@@b@ public static String getFullStackTrace(Throwable throwable)@b@ {@b@ StringWriter sw = new StringWriter();@b@ PrintWriter pw = new PrintWriter(sw, true);@b@ Throwable[] ts = getThrowables(throwable);@b@ for (int i = 0; i < ts.length; ++i) {@b@ ts[i].printStackTrace(pw);@b@ if (isNestedThrowable(ts[i]))@b@ break;@b@ }@b@@b@ return sw.getBuffer().toString();@b@ }@b@@b@ public static Throwable getRootCause(Throwable throwable)@b@ {@b@ Throwable cause = getCause(throwable);@b@ if (cause != null) {@b@ throwable = cause;@b@ while ((throwable = getCause(throwable)) != null)@b@ cause = throwable;@b@ }@b@@b@ return cause;@b@ }@b@@b@ public static String[] getRootCauseStackTrace(Throwable throwable)@b@ {@b@ if (throwable == null)@b@ return ArrayUtils.EMPTY_STRING_ARRAY;@b@@b@ Throwable[] throwables = getThrowables(throwable);@b@ int count = throwables.length;@b@ ArrayList frames = new ArrayList();@b@ List nextTrace = getStackFrameList(throwables[(count - 1)]);@b@ int i = count; while (--i >= 0) {@b@ List 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 (int j = 0; j < trace.size(); ++j)@b@ frames.add(trace.get(j));@b@ }@b@@b@ return ((String[])frames.toArray(new String[0]));@b@ }@b@@b@ static List 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 LinkedList();@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().length() == 0)) {@b@ traceStarted = true;@b@ list.add(token);@b@ } else if (traceStarted) {@b@ break;@b@ }@b@ }@b@ return list;@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 LinkedList();@b@ while (frames.hasMoreTokens())@b@ list.add(frames.nextToken());@b@@b@ return toArray(list);@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@ 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 int getThrowableCount(Throwable throwable)@b@ {@b@ int count = 0;@b@ while (throwable != null) {@b@ ++count;@b@ throwable = getCause(throwable);@b@ }@b@ return count;@b@ }@b@@b@ public static Throwable[] getThrowables(Throwable throwable)@b@ {@b@ List list = new ArrayList();@b@ while (throwable != null) {@b@ list.add(throwable);@b@ throwable = getCause(throwable);@b@ }@b@ return ((Throwable[])list.toArray(new Throwable[list.size()]));@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 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@ public static boolean isCauseMethodName(String methodName)@b@ {@b@ return (ArrayUtils.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0);@b@ }@b@@b@ public static boolean isNestedThrowable(Throwable throwable)@b@ {@b@ if (throwable == null) {@b@ return false;@b@ }@b@@b@ if (throwable instanceof Nestable)@b@ return true;@b@ if (throwable instanceof SQLException)@b@ return true;@b@ if (throwable instanceof InvocationTargetException)@b@ return true;@b@ if (isThrowableNested()) {@b@ return true;@b@ }@b@@b@ Class cls = throwable.getClass();@b@ int i = 0; label115: for (int isize = CAUSE_METHOD_NAMES.length; i < isize; ++i)@b@ try {@b@ Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);@b@ if ((method == null) || (!(Throwable.class.isAssignableFrom(method.getReturnType())))) break label115;@b@ return true;@b@ }@b@ catch (NoSuchMethodException localNoSuchMethodException)@b@ {@b@ }@b@ catch (SecurityException localSecurityException1) {@b@ }@b@ try {@b@ Field field = cls.getField("detail");@b@ if (field == null) break label143;@b@ return true;@b@ }@b@ catch (NoSuchFieldException localNoSuchFieldException) {@b@ }@b@ catch (SecurityException localSecurityException2) {@b@ }@b@ label143: return false;@b@ }@b@@b@ public static boolean isThrowableNested()@b@ {@b@ return (THROWABLE_CAUSE_METHOD != null);@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@ for (int i = 0; i < trace.length; ++i)@b@ stream.println(trace[i]);@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@ for (int i = 0; i < trace.length; ++i)@b@ writer.println(trace[i]);@b@@b@ writer.flush();@b@ }@b@@b@ public static void removeCauseMethodName(String methodName)@b@ {@b@ if (StringUtils.isNotEmpty(methodName)) {@b@ List list = getCauseMethodNameList();@b@ if (list.remove(methodName))@b@ CAUSE_METHOD_NAMES = toArray(list);@b@ }@b@ }@b@@b@ public static void removeCommonFrames(List causeFrames, List 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@ private static String[] toArray(List list)@b@ {@b@ return ((String[])list.toArray(new String[list.size()]));@b@ }@b@}