
Author: ceki Date: Wed May 14 15:27:02 2008 New Revision: 1696 Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java Log: - refactoring of ThrowableInformation. Code responsible for extracting the string array has been moved into the ThorableToStringArray class. This allows StatusPrinter code (in lb-core) to compute string representation of throwables without creating a ThrowableInformationConverter (in lb-classic). Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java Wed May 14 15:27:02 2008 @@ -44,4 +44,5 @@ * An empty Class array. */ public final static Class[] EMPTY_CLASS_ARRAY = new Class[] {}; + static public final String CAUSED_BY = "Caused by: "; } Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java Wed May 14 15:27:02 2008 @@ -0,0 +1,84 @@ +/** + * LOGBack: the reliable, fast and flexible logging library for Java. + * + * Copyright (C) 1999-2005, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.core.helpers; + +import ch.qos.logback.core.CoreGlobal; + + +public class ThrowableToStringArray { + + public static String[] extractStringRep(Throwable t, StackTraceElement[] parentSTE) { + String[] result; + + StackTraceElement[] ste = t.getStackTrace(); + final int commonFrames = findCommonFrames(ste, parentSTE); + + final String[] firstArray; + if (commonFrames == 0) { + firstArray = new String[ste.length + 1]; + } else { + firstArray = new String[ste.length - commonFrames + 2]; + } + + String prefix = ""; + if (parentSTE != null) { + prefix = CoreGlobal.CAUSED_BY; + } + + firstArray[0] = prefix + t.getClass().getName(); + if (t.getMessage() != null) { + firstArray[0] += ": " + t.getMessage(); + } + + for (int i = 0; i < (ste.length - commonFrames); i++) { + firstArray[i + 1] = ste[i].toString(); + } + + if (commonFrames != 0) { + firstArray[firstArray.length - 1] = commonFrames + + " common frames omitted"; + } + + Throwable cause = t.getCause(); + if (cause != null) { + final String[] causeArray = ThrowableToStringArray.extractStringRep(cause, ste); + String[] tmp = new String[firstArray.length + causeArray.length]; + System.arraycopy(firstArray, 0, tmp, 0, firstArray.length); + System + .arraycopy(causeArray, 0, tmp, firstArray.length, causeArray.length); + result = tmp; + } else { + result = firstArray; + } + return result; + } + + private static int findCommonFrames(StackTraceElement[] ste, + StackTraceElement[] parentSTE) { + if (parentSTE == null) { + return 0; + } + + int steIndex = ste.length - 1; + int parentIndex = parentSTE.length - 1; + int count = 0; + while (steIndex >= 0 && parentIndex >= 0) { + if (ste[steIndex].equals(parentSTE[parentIndex])) { + count++; + } else { + break; + } + steIndex--; + parentIndex--; + } + return count; + } + +} Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java Wed May 14 15:27:02 2008 @@ -16,20 +16,23 @@ import java.util.Iterator; import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreGlobal; import ch.qos.logback.core.Layout; import ch.qos.logback.core.status.Status; import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.helpers.ThrowableToStringArray; public class StatusPrinter { - + private static PrintStream ps = System.out; - static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss,SSS"); - + static SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + "HH:mm:ss,SSS"); + public static void setPrintStream(PrintStream printStream) { ps = printStream; } - + public static void print(Context context) { if (context == null) { throw new IllegalArgumentException("Context argument cannot be null"); @@ -46,53 +49,64 @@ } public static void print(StatusManager sm) { - StringBuilder sb = buildStr(sm); + StringBuilder sb = new StringBuilder(); + buildStr(sb, sm); ps.println(sb.toString()); } - public static StringBuilder buildStr(StatusManager sm) { - StringBuilder sb = new StringBuilder(); + public static void buildStr(StringBuilder sb, StatusManager sm) { + synchronized (sm) { Iterator it = sm.iterator(); while (it.hasNext()) { Status s = (Status) it.next(); buildStr(sb, "", s); } - return sb; } } - + private static void appendThrowable(StringBuilder sb, Throwable t) { - StackTraceElement[] steArray = t.getStackTrace(); - for (StackTraceElement ste : steArray) { - sb.append(ste.toString()).append(Layout.LINE_SEP); + String[] stringRep = ThrowableToStringArray.extractStringRep(t, null); + + for (String s : stringRep) { + if (s.startsWith(CoreGlobal.CAUSED_BY)) { + // nothing + } else if (Character.isDigit(s.charAt(0))) { + // if line resembles "48 common frames omitted" + sb.append("\t... "); + } else { + // most of the time. just add a tab+"at" + sb.append("\tat "); + } + sb.append(s).append(CoreGlobal.LINE_SEPARATOR); } } + private static void buildStr(StringBuilder sb, String indentation, Status s) { String prefix; - if(s.hasChildren()) { - prefix = indentation + "+ "; + if (s.hasChildren()) { + prefix = indentation + "+ "; } else { prefix = indentation + "|-"; } - - if(simpleDateFormat != null) { + + if (simpleDateFormat != null) { Date date = new Date(s.getDate()); String dateStr = simpleDateFormat.format(date); sb.append(dateStr).append(" "); - } - sb.append(prefix+s).append(Layout.LINE_SEP); - + } + sb.append(prefix + s).append(Layout.LINE_SEP); + if (s.getThrowable() != null) { appendThrowable(sb, s.getThrowable()); } - if(s.hasChildren()) { + if (s.hasChildren()) { Iterator<Status> ite = s.iterator(); - while(ite.hasNext()) { + while (ite.hasNext()) { Status child = ite.next(); - buildStr(sb, indentation+" ", child); + buildStr(sb, indentation + " ", child); } } } - + }