view src/nabble/naml/compiler/StackTrace.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.naml.compiler;

import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
import java.util.WeakHashMap;
import java.util.EmptyStackException;
import fschmidt.util.java.ArrayUtils;
import fschmidt.util.java.ArrayStack;
import fschmidt.util.java.Stack;
import fschmidt.util.java.Interner;


public class StackTrace extends ArrayStack<StackTraceElement> {

	private static final ThreadLocal<Stack<StackTrace>> stack = new ThreadLocal<Stack<StackTrace>>() {
		protected Stack<StackTrace> initialValue() {
			Stack<StackTrace> stack = new ArrayStack<StackTrace>();
			allStacks.put( Thread.currentThread(), stack );
			return stack;
		}
	};

	private static final Map<Thread,Stack<StackTrace>> allStacks = Collections.synchronizedMap(new WeakHashMap<Thread,Stack<StackTrace>>());

	private static final Interner<StackTrace> interner = new Interner<StackTrace>();

	public StackTrace() {}

	StackTrace(StackTrace st) {
		super(st);
	}

	StackTrace intern() {
		trimToSize();
		return interner.intern(this);
	}

	public String toString() {
		StringBuilder buf = new StringBuilder();
		for( int i=size()-1; i>=0; i-- ) {
			StackTraceElement stackTraceElement = get(i);
			buf.append( "\n\tin " ).append( stackTraceElement );
		}
		return buf.toString();
	}
/*
	public boolean containsSourceStartingWith(String s) {
		for( StackTraceElement ste : this ) {
			if( ste.source.id.startsWith(s) )
				return true;
		}
		return false;
	}
*/
	static Stack<StackTrace> stack() {
		return stack.get();
	}

	private static StackTrace stackTrace(Stack<StackTrace> stack) {
		StackTrace stackTrace = new StackTrace();
		for( StackTrace st : stack ) {
			stackTrace.addAll(st);
		}
		return stackTrace;
	}

	public static StackTrace current() {
		return stackTrace(stack());
	}

	public static Map<Thread,String[]> getAllStackTraces() {
		Map<Thread,Stack<StackTrace>> mapCopy;
		synchronized(allStacks) {
			mapCopy = new HashMap<Thread,Stack<StackTrace>>(allStacks);
		}
		Map<Thread,String[]> rtn = new HashMap<Thread,String[]>();
		for( Map.Entry<Thread,Stack<StackTrace>> entry : mapCopy.entrySet() ) {
			Thread thread = entry.getKey();
			try {
				Stack<StackTrace> stack = new ArrayStack<StackTrace>(entry.getValue());  // not thread-safe but the best I can do
				StackTrace stackTrace = stackTrace(stack);
				if( stackTrace.isEmpty() )
					continue;
				String[] aStr = new String[stackTrace.size()];
				for( int i=0; i<aStr.length; i++ ) {
					aStr[i] = stackTrace.get(i).toString();
				}
				ArrayUtils.reverse(aStr);
				rtn.put(thread,aStr);
			} catch(EmptyStackException e) {}
		}
		return rtn;
	}

}