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(); } } }