001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.helpers;
015
016import java.util.LinkedList;
017import java.util.List;
018
019import ch.qos.logback.core.CoreConstants;
020
021public class ThrowableToStringArray {
022
023    public static String[] convert(Throwable t) {
024        List<String> strList = new LinkedList<String>();
025        extract(strList, t, null);
026        return strList.toArray(new String[0]);
027
028    }
029
030    private static void extract(List<String> strList, Throwable t, StackTraceElement[] parentSTE) {
031
032        StackTraceElement[] ste = t.getStackTrace();
033        final int numberOfcommonFrames = findNumberOfCommonFrames(ste, parentSTE);
034
035        strList.add(formatFirstLine(t, parentSTE));
036        for (int i = 0; i < (ste.length - numberOfcommonFrames); i++) {
037            strList.add("\tat " + ste[i].toString());
038        }
039
040        if (numberOfcommonFrames != 0) {
041            strList.add("\t... " + numberOfcommonFrames + " common frames omitted");
042        }
043
044        Throwable cause = t.getCause();
045        if (cause != null) {
046            ThrowableToStringArray.extract(strList, cause, ste);
047        }
048    }
049
050    private static String formatFirstLine(Throwable t, StackTraceElement[] parentSTE) {
051        String prefix = "";
052        if (parentSTE != null) {
053            prefix = CoreConstants.CAUSED_BY;
054        }
055
056        String result = prefix + t.getClass().getName();
057        if (t.getMessage() != null) {
058            result += ": " + t.getMessage();
059        }
060        return result;
061    }
062
063    private static int findNumberOfCommonFrames(StackTraceElement[] ste, StackTraceElement[] parentSTE) {
064        if (parentSTE == null) {
065            return 0;
066        }
067
068        int steIndex = ste.length - 1;
069        int parentIndex = parentSTE.length - 1;
070        int count = 0;
071        while (steIndex >= 0 && parentIndex >= 0) {
072            if (ste[steIndex].equals(parentSTE[parentIndex])) {
073                count++;
074            } else {
075                break;
076            }
077            steIndex--;
078            parentIndex--;
079        }
080        return count;
081    }
082
083}