1 package net.sf.openrocket.logging;
6 * An exception that is used to store a stack trace. On modern computers
7 * instantiation of an exception takes on the order of one microsecond, while
8 * examining the trace typically takes several times longer. Therefore the
9 * exception should be stored and the stack trace examined only when necessary.
11 * The {@link #getMessage()} method returns a description of the position
12 * where this exception has been instantiated. The position is provided
13 * as many levels upwards from the instantiation position as provided to the
16 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
18 public class TraceException extends Exception {
20 private static final String STANDARD_PACKAGE_PREFIX = "net.sf.openrocket.";
22 private final int minLevel;
23 private final int maxLevel;
24 private volatile String message = null;
28 * Instantiate exception that provides the line of instantiation as a message.
30 public TraceException() {
35 * Instantiate exception that provides the provided number of levels upward
36 * from the instantiation location as a message. The level provided
37 * is how many levels upward should be examined to find the stack trace
38 * position for the exception message.
40 * @param level how many levels upward to examine the stack trace to find
41 * the correct message.
43 public TraceException(int level) {
49 * Instantiate exception that provides a range of levels upward from the
50 * instantiation location as a message. This is useful to identify the
51 * next level of callers upward.
53 * @param minLevel the first level which to include.
54 * @param maxLevel the last level which to include.
56 public TraceException(int minLevel, int maxLevel) {
57 if (minLevel > maxLevel || minLevel < 0) {
58 throw new IllegalArgumentException("minLevel=" + minLevel + " maxLevel=" + maxLevel);
60 this.minLevel = minLevel;
61 this.maxLevel = maxLevel;
66 * Construct an exception with the specified message.
68 * @param message the message for the exception.
70 public TraceException(String message) {
72 this.message = message;
77 * Construct an exception with the specified message and cause.
79 * @param message the message for the exception.
80 * @param cause the cause for this exception.
82 public TraceException(String message, Throwable cause) {
84 this.message = message;
85 this.initCause(cause);
90 * Get the description of the code position as provided in the constructor.
93 public String getMessage() {
94 if (message == null) {
95 StackTraceElement[] elements = this.getStackTrace();
97 StringBuilder sb = new StringBuilder();
100 if (elements == null || elements.length == 0) {
101 sb.append("no stack trace");
105 int position = minLevel;
106 while (levelCount <= (maxLevel - minLevel) && position < elements.length) {
108 // Ignore synthetic "access$0" methods generated by the JRE
109 if (elements[position].getMethodName().contains("$")) {
114 if (levelCount > 0) {
117 sb.append(toString(elements[position]));
125 message = sb.toString();
131 private static String toString(StackTraceElement element) {
132 if (element.getClassName().startsWith(STANDARD_PACKAGE_PREFIX)) {
133 return element.getFileName() + ":" + element.getLineNumber();
135 return element.toString();