001: // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
002:
003: package jodd.util;
004:
005: import java.io.StringWriter;
006: import java.io.PrintWriter;
007: import java.util.ArrayList;
008:
009: public class ExceptionUtil {
010:
011: /**
012: * Returns current stack trace in form of array of stack trace elements
013: * Since an exception is thrown internally, this method is slow.
014: */
015: public static StackTraceElement[] getCurrentStackTrace() {
016: try {
017: throw new Exception();
018: } catch (Exception ex) {
019: StackTraceElement[] ste = ex.getStackTrace();
020: if (ste.length > 1) {
021: StackTraceElement[] result = new StackTraceElement[ste.length - 1];
022: System.arraycopy(ste, 1, result, 0, ste.length - 1);
023: return result;
024: } else {
025: return ste;
026: }
027: }
028: }
029:
030: // ---------------------------------------------------------------- exception stack trace
031:
032: /**
033: * Returns stack trace filtered by classnames.
034: */
035: public static StackTraceElement[] getStackTrace(Throwable t,
036: String[] allow, String[] deny) {
037: StackTraceElement[] st = t.getStackTrace();
038: ArrayList<StackTraceElement> result = new ArrayList<StackTraceElement>(
039: st.length);
040:
041: elementLoop: for (StackTraceElement element : st) {
042: String className = element.getClassName();
043: if (allow != null) {
044: boolean validElemenet = false;
045: for (String filter : allow) {
046: if (className.indexOf(filter) != -1) {
047: validElemenet = true;
048: break;
049: }
050: }
051: if (validElemenet == false) {
052: continue;
053: }
054: }
055: if (deny != null) {
056: for (String filter : deny) {
057: if (className.indexOf(filter) != -1) {
058: continue elementLoop;
059: }
060: }
061: }
062: result.add(element);
063: }
064: st = new StackTraceElement[result.size()];
065: return result.toArray(st);
066: }
067:
068: /**
069: * Returns stack trace chain filtered by classnames.
070: */
071: public static StackTraceElement[][] getStackTraceChain(Throwable t,
072: String[] allow, String[] deny) {
073: ArrayList<StackTraceElement[]> result = new ArrayList<StackTraceElement[]>();
074: while (t != null) {
075: StackTraceElement[] stack = getStackTrace(t, allow, deny);
076: result.add(stack);
077: t = t.getCause();
078: }
079: StackTraceElement[][] allStacks = new StackTraceElement[result
080: .size()][];
081: for (int i = 0; i < allStacks.length; i++) {
082: allStacks[i] = result.get(i);
083: }
084: return allStacks;
085: }
086:
087: /**
088: * Returns exception chain starting from top up to root cause.
089: */
090: public static Throwable[] getExceptionChain(Throwable throwable) {
091: ArrayList<Throwable> list = new ArrayList<Throwable>();
092: list.add(throwable);
093: while ((throwable = throwable.getCause()) != null) {
094: list.add(throwable);
095: }
096: Throwable[] result = new Throwable[list.size()];
097: return list.toArray(result);
098: }
099:
100: // ---------------------------------------------------------------- exception to string
101:
102: /**
103: * Prints stack trace into a String.
104: */
105: public static String exceptionToString(Throwable t) {
106: StringWriter sw = new StringWriter();
107: PrintWriter pw = new PrintWriter(sw, true);
108: t.printStackTrace(pw);
109: pw.flush();
110: sw.flush();
111: return sw.toString();
112: }
113:
114: /**
115: * Prints full exception stack trace, from top to root cause, into a String.
116: */
117: public static String exceptionChainToString(Throwable t) {
118: StringWriter sw = new StringWriter();
119: PrintWriter pw = new PrintWriter(sw, true);
120: while (t != null) {
121: t.printStackTrace(pw);
122: t = t.getCause();
123: }
124: pw.flush();
125: sw.flush();
126: return sw.toString();
127: }
128:
129: // ---------------------------------------------------------------- root cause
130:
131: /**
132: * Introspects the <code>Throwable</code> to obtain the root cause.
133: * <p>
134: * This method walks through the exception chain to the last element,
135: * "root" of the tree, and returns that exception. If no root cause faund
136: * returns <code>null</code>.
137: */
138: public static Throwable getRootCause(Throwable throwable) {
139: Throwable cause = throwable.getCause();
140: if (cause != null) {
141: throwable = cause;
142: while ((throwable = throwable.getCause()) != null) {
143: cause = throwable;
144: }
145: }
146: return cause;
147: }
148: }
|