/** * Returns the current top of the thread-local logger stack or the static Logger instance scoped * to Logger.class if the stack is empty. * * @return current logger [never null] */ public static Logger getLogger() { final LinkedList stack = (LinkedList) THREAD_LOCAL_STACK.get(); // [assertion: stack != null] if (stack.isEmpty()) { return STATIC_LOGGER; } else { return (Logger) stack.getLast(); } }
/** * Requiring a context parameter here helps enforce correct push/pop nesting in the caller code. * * @param ctx [may not be null] */ public static void pop(final Logger ctx) { // TODO: add guards for making sure only the pushing thread is allowed to // execute this final LinkedList stack = (LinkedList) THREAD_LOCAL_STACK.get(); try { final Logger current = (Logger) stack.getLast(); if (current != ctx) throw new IllegalStateException("invalid context being popped: " + ctx); stack.removeLast(); current.cleanup(); } catch (NoSuchElementException nsee) { throw new IllegalStateException( "empty logger context stack on thread [" + Thread.currentThread() + "]: " + nsee); } }
/** @param ctx [may not be null] */ public static void push(final Logger ctx) { if (ctx == null) throw new IllegalArgumentException("null input: ctx"); final LinkedList stack = (LinkedList) THREAD_LOCAL_STACK.get(); stack.addLast(ctx); }