package net.sf.openrocket.logging;
/**
* An exception that is used to store a stack trace. On modern computers
* instantiation of an exception takes on the order of one microsecond, while
* examining the trace typically takes several times longer. Therefore the
* exception should be stored and the stack trace examined only when necessary.
* <p>
* The {@link #getLocation()} method returns a description of the position
* where this exception has been instantiated.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
class TraceException {
private static final String STANDARD_PACKAGE_PREFIX = "net.sf.openrocket.";
private static final String EXCLUDED_PACKAGE_PREFIX = "net.sf.openrocket.logging";
private final Throwable t;
private volatile String location;
TraceException() {
t = new Throwable();
}
public String getLocation() {
if (location == null) {
StackTraceElement[] elements = t.getStackTrace();
StringBuilder sb = new StringBuilder();
sb.append('(');
if (elements == null || elements.length == 0) {
sb.append("no stack trace");
} else {
int found = -1;
int index = 0;
while (found < 0 && index < elements.length) {
// Ignore synthetic "access$0" methods generated by the JRE
if (elements[index].getMethodName().contains("$")) {
index++;
continue;
}
String className = elements[index].getClassName();
if (!className.startsWith(EXCLUDED_PACKAGE_PREFIX) && className.startsWith(STANDARD_PACKAGE_PREFIX)) {
sb.append(toString(elements[index]));
found = 1;
break;
}
index++;
}
if (found < 0) {
sb.append(toString(elements[0]));
}
}
sb.append(')');
location = sb.toString();
}
return location;
}
private static String toString(StackTraceElement element) {
if (element.getClassName().startsWith(STANDARD_PACKAGE_PREFIX)) {
return element.getFileName() + ":" + element.getLineNumber();
} else {
return element.toString();
}
}
}