package ilarkesto.di; import java.util.Set; /** * Represents a context in which a thread is running. Contexts can be nested. */ public final class Context { private static final ThreadLocal<Context> THREAD_LOCAL = new ThreadLocal<Context>(); private static Context rootContext; private Context parent; private String name; private MultiBeanProvider beanProvider; private Context(Context parent, String name) { this.parent = parent; this.name = name; beanProvider = new MultiBeanProvider(); if (parent != null) beanProvider.addBeanProvider(parent.beanProvider); } public final void setName(String name) { this.name = name; } public final String getName() { return name; } public final void addBeanProvider(Object heanProvider) { this.beanProvider.addBeanProvider(heanProvider); } public final BeanProvider getBeanProvider() { return this.beanProvider; } public final Context getParentContext() { return parent; } public final Context createSubContext(String name) { Context context = new Context(this, name); // LOG.debug("Context created:", context); context.bindCurrentThread(); return context; } public final void destroy() { releaseCurrentThread(); if (parent != null) { parent.bindCurrentThread(); } } public final void bindCurrentThread() { THREAD_LOCAL.set(this); Thread.currentThread().setName(toString()); } private final void releaseCurrentThread() { THREAD_LOCAL.set(null); Thread.currentThread().setName("<no context>"); } @Override public final String toString() { return parent == null ? name : parent + " > " + name; } public static Context getRootContext() { if (rootContext == null) throw new RuntimeException("Root context does not exist. Call createRootContext()"); return rootContext; } public static synchronized Context createRootContext(String name) { if (rootContext != null) throw new RuntimeException("Root context already exists: " + rootContext); rootContext = new Context(null, name); rootContext.bindCurrentThread(); return rootContext; } public static Context get() { Context context = THREAD_LOCAL.get(); if (context == null) context = getRootContext(); return context; } // --- helper --- public final <T> T autowire(T target) { return beanProvider.autowire(target); } public final void autowireClass(Class type) { beanProvider.autowireClass(type); } /** * Gets all beans by their type. All beans instanceof the given type are returned. */ public final <T> Set<T> getBeansByType(Class<T> type) { return beanProvider.getBeansByType(type); } /** * Provides a set of all existing bean names. */ public final Set<String> getBeanNames() { return beanProvider.beanNames(); } /** * Gets a bean by name. */ public final <T> Object getBean(String beanName) { return beanProvider.getBean(beanName); } }