org.test4j.mock.faking.util.StackTrace Maven / Gradle / Ivy
package org.test4j.mock.faking.util;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.test4j.mock.faking.util.ReflectUtility.doThrow;
/**
* Provides utility methods to extract and filter stack trace information.
*
* @author wudarui
*/
@SuppressWarnings({"unused"})
public final class StackTrace {
private final Throwable throwable;
private StackTrace(Throwable throwable) {
this.throwable = throwable;
}
public static void filterStackTrace(Throwable t) {
if (t == null) {
return;
}
try {
new StackTrace(t).filter(new HashSet<>());
} catch (Exception e) {
doThrow(t);
}
}
/**
* 过滤异常栈
*
* @param hasFilters 已过滤异常
*/
void filter(Set hasFilters) {
int objId = System.identityHashCode(this.throwable);
if (hasFilters.contains(objId) || this.throwable == null) {
return;
} else {
hasFilters.add(objId);
}
StackTraceElement[] elements = this.throwable.getStackTrace();
StackTraceElement[] filtered = new StackTraceElement[elements.length];
int index = 0;
for (StackTraceElement ste : elements) {
if (filter(ste)) {
continue;
}
filtered[index] = ste;
index++;
}
StackTraceElement[] newStackTrace = new StackTraceElement[index];
System.arraycopy(filtered, 0, newStackTrace, 0, index);
throwable.setStackTrace(newStackTrace);
new StackTrace(throwable.getCause()).filter(hasFilters);
}
/**
* 是否被过滤掉
*
* @param ste StackTraceElement
* @return ignore
*/
private boolean filter(StackTraceElement ste) {
if (ste.getFileName() == null) {
return true;
}
String className = ste.getClassName();
return isJDK(ste) || is3rdInternalMethod(className);
}
/**
* JDK
*
* @param ste StackTraceElement
* @return ignore
*/
private static boolean isJDK(StackTraceElement ste) {
String className = ste.getClassName();
return className.startsWith("sun.") && !ste.isNativeMethod() ||
className.startsWith("jdk.") ||
className.startsWith("java.util.");
}
/**
* 部分三方工具内部方法
*
* @param className class name
* @return ignore
*/
private static boolean is3rdInternalMethod(String className) {
for (String pack : Start_Filters) {
if (className.startsWith(pack)) {
return true;
}
}
for (String pack : Contain_Filters) {
if (className.contains(pack)) {
return true;
}
}
return false;
}
/**
* package以下列开头的过滤掉
*/
private static final List Start_Filters = Arrays.asList(
"org.junit.",
"org.testng.",
"junit.framework",
"org.test4j.integration.",
"org.test4j.mock.faking.",
"org.test4j.exception.Exceptions",
"org.test4j.module.database.operator.",
"org.test4j.module.spec.internal."
);
/**
* package包含下列路径的过滤掉
*/
private static final List Contain_Filters = Arrays.asList(
"$$EnhancerByCGLIB$$",
".reflect.",
".surefire.",
".gradle.",
".intellij.",
".eclipse.",
".jdt."
);
/**
* 将异常日志转换为字符串
*
* @param e Throwable
* @return ignore
*/
public static String toString(Throwable e) {
if (e == null) {
return "";
}
try (StringWriter writer = new StringWriter(); PrintWriter print = new PrintWriter(writer)) {
e.printStackTrace(print);
return writer.toString();
} catch (IOException ex) {
ex.printStackTrace();
return e.getMessage();
}
}
}