ch.qos.logback.classic.spi.CallerData Maven / Gradle / Ivy
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.classic.spi;
import ch.qos.logback.core.CoreConstants;
import java.util.List;
import static ch.qos.logback.core.CoreConstants.NA;
/**
* This class computes caller data returning the result in the form of a
* StackTraceElement array.
*
* @author Ceki Gülcü
*/
public class CallerData {
// All logger call's in log4j-over-slf4j use the Category class
private static final String LOG4J_CATEGORY = "org.apache.log4j.Category";
private static final String SLF4J_BOUNDARY = "org.slf4j.Logger";
/**
* When caller information is not available this constant is used for the line
* number.
*/
public static final int LINE_NA = -1;
public static final String CALLER_DATA_NA = "?#?:?" + CoreConstants.LINE_SEPARATOR;
/**
* This value is returned in case no caller data could be extracted.
*/
public static final StackTraceElement[] EMPTY_CALLER_DATA_ARRAY = new StackTraceElement[0];
/**
* Extract caller data information as an array based on a Throwable passed as
* parameter
*/
public static StackTraceElement[] extract(Throwable t, String fqnOfInvokingClass, final int maxDepth,
List frameworkPackageList) {
if (t == null) {
return null;
}
StackTraceElement[] steArray = t.getStackTrace();
StackTraceElement[] callerDataArray;
int found = LINE_NA;
for (int i = 0; i < steArray.length; i++) {
if (isInFrameworkSpace(steArray[i].getClassName(), fqnOfInvokingClass, frameworkPackageList)) {
// the caller is assumed to be the next stack frame, hence the +1.
found = i + 1;
} else {
if (found != LINE_NA) {
break;
}
}
}
// we failed to extract caller data
if (found == LINE_NA) {
return EMPTY_CALLER_DATA_ARRAY;
}
int availableDepth = steArray.length - found;
int desiredDepth = maxDepth < (availableDepth) ? maxDepth : availableDepth;
callerDataArray = new StackTraceElement[desiredDepth];
for (int i = 0; i < desiredDepth; i++) {
callerDataArray[i] = steArray[found + i];
}
return callerDataArray;
}
static boolean isInFrameworkSpace(String currentClass, String fqnOfInvokingClass,
List frameworkPackageList) {
// the check for org.apache.log4j.Category class is intended to support
// log4j-over-slf4j. it solves http://bugzilla.slf4j.org/show_bug.cgi?id=66
if (currentClass.equals(fqnOfInvokingClass) || currentClass.equals(LOG4J_CATEGORY)
|| currentClass.startsWith(SLF4J_BOUNDARY)
|| isInFrameworkSpaceList(currentClass, frameworkPackageList)) {
return true;
} else {
return false;
}
}
/**
* Is currentClass present in the list of packages considered part of the
* logging framework?
*/
private static boolean isInFrameworkSpaceList(String currentClass, List frameworkPackageList) {
if (frameworkPackageList == null)
return false;
for (String s : frameworkPackageList) {
if (currentClass.startsWith(s))
return true;
}
return false;
}
/**
* Returns a StackTraceElement where all string fields are set to {@link CoreConstants#NA}
* and line number is set to {@link #LINE_NA}.
*
* @return StackTraceElement with values set to NA constants.
* @since 1.0.10
*/
public static StackTraceElement naInstance() {
return new StackTraceElement(NA, NA, NA, LINE_NA);
}
}