package org.jboss.seam.security.external.virtualapplications;
import java.lang.annotation.Annotation;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.servlet.ServletContext;
import org.jboss.seam.security.external.contexts.ContextualInstance;
import org.jboss.seam.security.external.contexts.HashMapBeanStore;
import org.jboss.seam.security.external.virtualapplications.api.VirtualApplicationScoped;
/**
* @author Marcel Kolsteren
*/
public class VirtualApplicationContext implements Context {
private static final String BEAN_STORE_ATTRIBUTE_NAME_PREFIX = "virtualApplicationContextBeanStore";
private ServletContext servletContext;
private final ThreadLocal<String> hostNameThreadLocal;
public VirtualApplicationContext() {
hostNameThreadLocal = new ThreadLocal<String>();
}
protected HashMapBeanStore getBeanStore() {
return getBeanStore(hostNameThreadLocal.get());
}
private HashMapBeanStore getBeanStore(String hostName) {
HashMapBeanStore beanStore = (HashMapBeanStore) servletContext.getAttribute(getAttributeName(hostName));
return beanStore;
}
private void createBeanStore(String hostName) {
HashMapBeanStore beanStore = new HashMapBeanStore();
servletContext.setAttribute(getAttributeName(hostName), beanStore);
}
private void removeBeanStore(String hostName) {
servletContext.removeAttribute(getAttributeName(hostName));
}
private String getAttributeName(String hostName) {
return BEAN_STORE_ATTRIBUTE_NAME_PREFIX + "_" + hostName;
}
public void initialize(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void destroy() {
this.servletContext = null;
}
public void create(String hostName) {
createBeanStore(hostName);
attach(hostName);
}
public void remove() {
getBeanStore().clear();
removeBeanStore(this.hostNameThreadLocal.get());
detach();
}
public boolean isExistingVirtualApplication(String hostName) {
return servletContext != null && getBeanStore(hostName) != null;
}
public void attach(String hostName) {
this.hostNameThreadLocal.set(hostName);
}
public void detach() {
this.hostNameThreadLocal.set(null);
}
public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext) {
if (!isActive()) {
throw new ContextNotActiveException();
}
ContextualInstance<T> beanInstance = getBeanStore().get(contextual);
if (beanInstance != null) {
return beanInstance.getInstance();
} else if (creationalContext != null) {
T instance = contextual.create(creationalContext);
if (instance != null) {
beanInstance = new ContextualInstance<T>(contextual, creationalContext, instance);
getBeanStore().put(contextual, beanInstance);
}
return instance;
} else {
return null;
}
}
public <T> T get(Contextual<T> contextual) {
return get(contextual, null);
}
public Class<? extends Annotation> getScope() {
return VirtualApplicationScoped.class;
}
public boolean isActive() {
return hostNameThreadLocal.get() != null;
}
}