0
|
1 package nabble.naml.compiler;
|
|
2
|
|
3 import java.util.Collections;
|
|
4 import java.util.Map;
|
|
5 import java.util.HashMap;
|
|
6 import java.util.WeakHashMap;
|
|
7 import java.util.EmptyStackException;
|
|
8 import fschmidt.util.java.ArrayUtils;
|
|
9 import fschmidt.util.java.ArrayStack;
|
|
10 import fschmidt.util.java.Stack;
|
|
11 import fschmidt.util.java.Interner;
|
|
12
|
|
13
|
|
14 public class StackTrace extends ArrayStack<StackTraceElement> {
|
|
15
|
|
16 private static final ThreadLocal<Stack<StackTrace>> stack = new ThreadLocal<Stack<StackTrace>>() {
|
|
17 protected Stack<StackTrace> initialValue() {
|
|
18 Stack<StackTrace> stack = new ArrayStack<StackTrace>();
|
|
19 allStacks.put( Thread.currentThread(), stack );
|
|
20 return stack;
|
|
21 }
|
|
22 };
|
|
23
|
|
24 private static final Map<Thread,Stack<StackTrace>> allStacks = Collections.synchronizedMap(new WeakHashMap<Thread,Stack<StackTrace>>());
|
|
25
|
|
26 private static final Interner<StackTrace> interner = new Interner<StackTrace>();
|
|
27
|
|
28 public StackTrace() {}
|
|
29
|
|
30 StackTrace(StackTrace st) {
|
|
31 super(st);
|
|
32 }
|
|
33
|
|
34 StackTrace intern() {
|
|
35 trimToSize();
|
|
36 return interner.intern(this);
|
|
37 }
|
|
38
|
|
39 public String toString() {
|
|
40 StringBuilder buf = new StringBuilder();
|
|
41 for( int i=size()-1; i>=0; i-- ) {
|
|
42 StackTraceElement stackTraceElement = get(i);
|
|
43 buf.append( "\n\tin " ).append( stackTraceElement );
|
|
44 }
|
|
45 return buf.toString();
|
|
46 }
|
|
47 /*
|
|
48 public boolean containsSourceStartingWith(String s) {
|
|
49 for( StackTraceElement ste : this ) {
|
|
50 if( ste.source.id.startsWith(s) )
|
|
51 return true;
|
|
52 }
|
|
53 return false;
|
|
54 }
|
|
55 */
|
|
56 static Stack<StackTrace> stack() {
|
|
57 return stack.get();
|
|
58 }
|
|
59
|
|
60 private static StackTrace stackTrace(Stack<StackTrace> stack) {
|
|
61 StackTrace stackTrace = new StackTrace();
|
|
62 for( StackTrace st : stack ) {
|
|
63 stackTrace.addAll(st);
|
|
64 }
|
|
65 return stackTrace;
|
|
66 }
|
|
67
|
|
68 public static StackTrace current() {
|
|
69 return stackTrace(stack());
|
|
70 }
|
|
71
|
|
72 public static Map<Thread,String[]> getAllStackTraces() {
|
|
73 Map<Thread,Stack<StackTrace>> mapCopy;
|
|
74 synchronized(allStacks) {
|
|
75 mapCopy = new HashMap<Thread,Stack<StackTrace>>(allStacks);
|
|
76 }
|
|
77 Map<Thread,String[]> rtn = new HashMap<Thread,String[]>();
|
|
78 for( Map.Entry<Thread,Stack<StackTrace>> entry : mapCopy.entrySet() ) {
|
|
79 Thread thread = entry.getKey();
|
|
80 try {
|
|
81 Stack<StackTrace> stack = new ArrayStack<StackTrace>(entry.getValue()); // not thread-safe but the best I can do
|
|
82 StackTrace stackTrace = stackTrace(stack);
|
|
83 if( stackTrace.isEmpty() )
|
|
84 continue;
|
|
85 String[] aStr = new String[stackTrace.size()];
|
|
86 for( int i=0; i<aStr.length; i++ ) {
|
|
87 aStr[i] = stackTrace.get(i).toString();
|
|
88 }
|
|
89 ArrayUtils.reverse(aStr);
|
|
90 rtn.put(thread,aStr);
|
|
91 } catch(EmptyStackException e) {}
|
|
92 }
|
|
93 return rtn;
|
|
94 }
|
|
95
|
|
96 }
|