package org.sdif4j.testing;
import org.sdif4j.InjectContext;
import javax.annotation.Nonnull;
import java.util.LinkedList;
/**
* TODO javadoc
*/
public class ThreadLocalInjectContext {
private static final ThreadLocal<LinkedList<Pair<Object, InjectContext>>> threadLocalInjectContextStack =
new InheritableThreadLocal<LinkedList<Pair<Object, InjectContext>>>();
private ThreadLocalInjectContext() {
}
/**
* Get thread local injector from stack tail
*
* @return
* @throws IllegalStateException if not set
*/
@Nonnull
public static InjectContext getInjectContext() throws IllegalStateException {
final LinkedList<Pair<Object, InjectContext>> stack = threadLocalInjectContextStack.get();
final Pair<Object, InjectContext> entry;
if (stack == null || (entry = stack.peekLast()) == null) {
throw new IllegalStateException("InjectContext not set in scope");
}
return entry.value;
}
/**
* Push injectContext to thread local stack
*
* @param injectContext
* @return pop key for popInjectContext to prevent illegal pop
*/
public static Object pushInjectContext(@Nonnull InjectContext injectContext) {
if (injectContext == null) {
throw new NullPointerException();
}
final Object popKey = new Object();
final Pair<Object, InjectContext> entry = new Pair<Object, InjectContext>(popKey, injectContext);
LinkedList<Pair<Object, InjectContext>> stack = threadLocalInjectContextStack.get();
if (stack == null) {
threadLocalInjectContextStack.set(stack = new LinkedList<Pair<Object, InjectContext>>());
}
stack.add(entry);
return popKey;
}
/**
* Pop injectContext from thread local stack
*
* @param popKey
* @return injectContext
* @throws IllegalArgumentException key is not of stack tail
* @throws IllegalStateException if no injectContext set
*/
public static InjectContext popInjectContext(Object popKey) throws IllegalStateException, IllegalArgumentException {
final LinkedList<Pair<Object, InjectContext>> stack = threadLocalInjectContextStack.get();
// fetch only
final Pair<Object, InjectContext> entry;
if (stack == null || (entry = stack.peekLast()) == null) {
throw new IllegalStateException("InjectContext not set in scope");
}
if (entry.key != popKey) {
throw new IllegalArgumentException("Illegal key");
}
// remove from stack
final Pair<Object, InjectContext> entry2 = stack.pollLast();
assert entry == entry2;
return entry2.value;
}
private static class Pair<K, V> {
final K key;
final V value;
Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
}