/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.toolkit.modules.concurrency.api.threadcontext; /** * A static holder to set or access the {@link ThreadContext} of the current thread. * * @author Robert Mischke */ public final class ThreadContextHolder { private static final ThreadLocal<ThreadContext> sharedThreadLocal = new ThreadLocal<>(); /** * Internal {@link ThreadContextMemento} implementation. * * @author Robert Mischke */ private static final class ThreadContextMementoImpl implements ThreadContextMemento { private final ThreadContext savedContext; private final ThreadContext newContext; ThreadContextMementoImpl(ThreadContext previous, ThreadContext newContext) { this.savedContext = previous; this.newContext = newContext; } @Override public void restore() { if (sharedThreadLocal.get() != newContext) { throw new IllegalStateException( "Consistency violation: Found a different " + ThreadContext.class.getSimpleName() + " instance than the one that was set when this " + ThreadContextMemento.class.getSimpleName() + " was created. Most likely, a subsequent context change operation was not unwound " + "after its nested operation was finished."); } sharedThreadLocal.set(savedContext); } } private ThreadContextHolder() {} /** * @return the {@link ThreadContext} of the current thread, or null if none exist */ public static ThreadContext getCurrentContext() { return sharedThreadLocal.get(); // may be null } /** * Convenience method equivalent to {@link #getCurrentContext()}.{@link #getAspect(Class)}. * * @param <T> the type of the aspect object to retrieve * @param aspectClass the type of the aspect object to retrieve * @return the selected aspect of the current thread's {@link ThreadContext}, or null if no context exists at all, or if it does not * contain the selected aspect */ public static <T> T getCurrentContextAspect(Class<T> aspectClass) { final ThreadContext threadContext = sharedThreadLocal.get(); if (threadContext == null) { return null; } return threadContext.getAspect(aspectClass); // may be null } /** * @param newContext the new {@link ThreadContext} to attach to the current thread * @return the previous {@link ThreadContext} of the current thread, or null if none existed */ public static ThreadContextMemento setCurrentContext(ThreadContext newContext) { final ThreadContext savedContext = sharedThreadLocal.get(); // may be null sharedThreadLocal.set(newContext); return new ThreadContextMementoImpl(savedContext, newContext); } }