/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.flex.utils; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Method; import java.util.NoSuchElementException; import java.util.StringTokenizer; // exceptions that are known to wrap other exceptions import java.lang.reflect.InvocationTargetException; /** * A utility for wrapping exceptions. */ public class ExceptionUtil { /** * List of no-arg methods that are known to return a wrapped throwable **/ private static final String[] unwrapMethods = { "getRootCause", "getTargetException", "getTargetError", "getException", "getCausedByException", "getLinkedException" }; public static Throwable wrappedException(Throwable t) { // handle these statically since they are core to Java if (t instanceof InvocationTargetException) { return ((InvocationTargetException)t).getTargetException(); } return getRootCauseWithReflection(t); } /** * Get to the base exception (if any) */ public static Throwable baseException(Throwable t) { Throwable wrapped = wrappedException(t); if (wrapped != null) return baseException(wrapped); else return t; } /** * return the stack trace in a String */ public static String toString(Throwable t) { StringWriter strWrt = new StringWriter(); t.printStackTrace(new PrintWriter(strWrt)); return strWrt.toString(); } /** * return the stack trace up to the first line that starts with prefix * * Example: ExceptionUtil.getStackTraceUpTo(exception, "jrunx."); */ public static String getStackTraceUpTo(Throwable t, String prefix) { StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r"); StringBuilder trace = new StringBuilder(); boolean done = false; String lookingFor = "at " + prefix; while (!done && tokens.hasMoreElements()) { String token = tokens.nextToken(); if (token.indexOf(lookingFor) == -1) trace.append(token); else done = true; trace.append("\n"); } return trace.toString(); } /** * return the top n lines of this stack trace * * Example: ExceptionUtil.getStackTraceLines(exception, 10); */ public static String getStackTraceLines(Throwable t, int numLines) { StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r"); StringBuilder trace = new StringBuilder(); for (int i=0; i<numLines; i++) { String token = tokens.nextToken(); trace.append(token); trace.append("\n"); } return trace.toString(); } /** * Return the "nth" method call from the stack trace of "t", where 0 is * the top. */ public static String getCallAt(Throwable t, int nth) { StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r"); try { // Skip the first line - the exception message for(int i = 0; i <= nth; ++i) tokens.nextToken(); // get the method name from the next token String token = tokens.nextToken(); int index1 = token.indexOf(' '); int index2 = token.indexOf('('); StringBuilder call = new StringBuilder(); call.append(token.substring(index1 < 0 ? 0 : index1 + 1, index2 < 0 ? call.length() : index2)); int index3 = token.indexOf(':', index2 < 0 ? 0 : index2); if(index3 >= 0) { int index4 = token.indexOf(')', index3); call.append(token.substring(index3, index4 < 0 ? token.length() : index4)); } return call.toString(); } catch(NoSuchElementException e) {} return "unknown"; } /** * Utility method for converting an exception into a string. This * method unwinds all wrapped exceptions * @param t The throwable exception * @return The printable exception */ public static String exceptionToString(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); //print out the exception stack. printExceptionStack(t, out, 0); return sw.toString(); } /** * Recursively prints out a stack of wrapped exceptions. */ protected static void printExceptionStack(Throwable th, PrintWriter out, int depth){ //only print the stack depth if the depth is greater than 0 boolean printStackDepth = depth>0; Throwable wrappedException = ExceptionUtil.wrappedException(th); if (wrappedException != null) { printStackDepth = true; printExceptionStack(wrappedException, out, depth + 1); } if(printStackDepth){ out.write("[" + depth + "]"); } th.printStackTrace(out); } private static Throwable getRootCauseWithReflection(Throwable t) { for(int i = 0; i < unwrapMethods.length; i++) { Method m = null; try { m = t.getClass().getMethod(unwrapMethods[i], (Class[])null); return (Throwable) m.invoke(t, (Object[])null); } catch(Exception nsme) { // ignore } } return null; } }