release 0.9.6
[debian/openrocket] / src / net / sf / openrocket / logging / TraceException.java
1 package net.sf.openrocket.logging;
2
3
4
5 /**
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 longer.  Therefore the exception should
9  * be stored and the stack trace examined only when necessary.
10  * <p>
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
14  * constructor.
15  * 
16  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
17  */
18 public class TraceException extends Exception {
19         
20         private static final String STANDARD_PACKAGE_PREFIX = "net.sf.openrocket.";
21
22         private final int minLevel;
23         private final int maxLevel;
24         private String message = null;
25         
26         
27         /**
28          * Instantiate exception that provides the line of instantiation as a message.
29          */
30         public TraceException() {
31                 this(0, 0);
32         }
33         
34         /**
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.
39          * 
40          * @param level         how many levels upward to examine the stack trace to find
41          *                                      the correct message.
42          */
43         public TraceException(int level) {
44                 this(level, level);
45         }
46         
47         
48         /**
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.
52          * 
53          * @param minLevel      the first level which to include.
54          * @param maxLevel      the last level which to include.
55          */
56         public TraceException(int minLevel, int maxLevel) {
57                 if (minLevel > maxLevel || minLevel < 0) {
58                         throw new IllegalArgumentException("minLevel="+minLevel+" maxLevel="+maxLevel);
59                 }
60                 this.minLevel = minLevel;
61                 this.maxLevel = maxLevel;
62         }
63
64
65         /**
66          * Get the description of the code position as provided in the constructor.
67          */
68         @Override
69         public String getMessage() {
70                 if (message == null) {
71                         StackTraceElement[] elements = this.getStackTrace();
72
73                         StringBuilder sb = new StringBuilder();
74                         if (minLevel < elements.length) {
75                                 
76                                 sb.append("(");
77                                 sb.append(toString(elements[minLevel]));
78                                 for (int i=minLevel+1; i <= maxLevel; i++) {
79                                         if (i < elements.length) {
80                                                 sb.append(' ').append(toString(elements[i]));
81                                         }
82                                 }
83                                 sb.append(')');
84                                 
85                         } else if (elements.length == 0) {
86                                 
87                                 sb.append("(no stack trace)");
88                                 
89                         } else {
90
91                                 sb.append('(');
92                                 sb.append(toString(elements[0]));
93                                 for (int i=1; i < elements.length; i++) {
94                                         sb.append(' ').append(toString(elements[i]));
95                                 }
96                                 sb.append(" level=").append(minLevel).append(')');
97                                 
98                         }
99                         message = sb.toString();
100                 }
101                 return message;
102         }
103         
104         
105         private static String toString(StackTraceElement element) {
106                 if (element.getClassName().startsWith(STANDARD_PACKAGE_PREFIX)) {
107                         return element.getFileName() + ":" + element.getLineNumber();
108                 } else {
109                         return element.toString();
110                 }
111         }
112         
113 }