blob: cf4f25bb0921dc4b535c07a6f8e5c60fc60a1c72 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.deltaspike.cdise.weld;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import org.apache.deltaspike.cdise.api.ContextControl;
import org.jboss.weld.context.ApplicationContext;
import org.jboss.weld.context.bound.BoundConversationContext;
import org.jboss.weld.context.bound.BoundRequestContext;
import org.jboss.weld.context.bound.BoundSessionContext;
import org.jboss.weld.context.bound.MutableBoundRequest;
/**
* Weld specific impl of the {@link org.apache.deltaspike.cdise.api.ContextControl}
*/
@Dependent
@SuppressWarnings("UnusedDeclaration")
public class WeldContextControl implements ContextControl
{
private static ThreadLocal<RequestContextHolder> requestContexts = new ThreadLocal<RequestContextHolder>();
private static ThreadLocal<Map<String, Object>> sessionMaps = new ThreadLocal<Map<String, Object>>();
@Inject
private ApplicationContext applicationContext;
@Inject
private BoundSessionContext sessionContext;
@Inject
private Instance<BoundRequestContext> requestContextFactory;
@Inject
private BoundConversationContext conversationContext;
@Override
public void startContexts()
{
startApplicationScope();
startSessionScope();
startRequestScope();
startConversationScope(null);
}
@Override
public void startContext(Class<? extends Annotation> scopeClass)
{
if (scopeClass.isAssignableFrom(ApplicationScoped.class))
{
startApplicationScope();
}
else if (scopeClass.isAssignableFrom(SessionScoped.class))
{
startSessionScope();
}
else if (scopeClass.isAssignableFrom(RequestScoped.class))
{
startRequestScope();
}
else if (scopeClass.isAssignableFrom(ConversationScoped.class))
{
startConversationScope(null);
}
}
/**
* Stops Conversation, Request and Session contexts.
* Does NOT stop Application context, only invalidates
* App scoped beans, as in Weld this context always active and clears
* automatically on shutdown.
*
* {@inheritDoc}
*/
@Override
public void stopContexts()
{
stopConversationScope();
stopRequestScope();
stopSessionScope();
stopApplicationScope();
}
@Override
public void stopContext(Class<? extends Annotation> scopeClass)
{
if (scopeClass.isAssignableFrom(ApplicationScoped.class))
{
stopApplicationScope();
}
else if (scopeClass.isAssignableFrom(SessionScoped.class))
{
stopSessionScope();
}
else if (scopeClass.isAssignableFrom(RequestScoped.class))
{
stopRequestScope();
}
else if (scopeClass.isAssignableFrom(ConversationScoped.class))
{
stopConversationScope();
}
}
/*
* This is a no-op method. In Weld Application Context is active as soon as the container starts
*/
private void startApplicationScope()
{
// No-op, in Weld Application context is always active
}
/**
* Weld Application context is active from container start to its shutdown
* This method merely clears out all ApplicationScoped beans BUT the context
* will still be active which may result in immediate re-creation of some beans.
*/
private void stopApplicationScope()
{
// Welds ApplicationContext gets cleaned at shutdown.
// Weld App context should be always active
if (applicationContext.isActive())
{
// destroys the bean instances, but the context stays active
applicationContext.invalidate();
}
}
void startRequestScope()
{
RequestContextHolder rcHolder = requestContexts.get();
if (rcHolder == null)
{
rcHolder = new RequestContextHolder(requestContextFactory.get(), new HashMap<String, Object>());
requestContexts.set(rcHolder);
rcHolder.getBoundRequestContext().associate(rcHolder.getRequestMap());
rcHolder.getBoundRequestContext().activate();
}
}
void stopRequestScope()
{
RequestContextHolder rcHolder = requestContexts.get();
if (rcHolder != null && rcHolder.getBoundRequestContext().isActive())
{
rcHolder.getBoundRequestContext().invalidate();
rcHolder.getBoundRequestContext().deactivate();
rcHolder.getBoundRequestContext().dissociate(rcHolder.getRequestMap());
requestContexts.set(null);
requestContexts.remove();
}
}
private void startSessionScope()
{
Map<String, Object> sessionMap = sessionMaps.get();
if (sessionMap == null)
{
sessionMap = new HashMap<String, Object>();
sessionMaps.set(sessionMap);
}
sessionContext.associate(sessionMap);
sessionContext.activate();
}
private void stopSessionScope()
{
if (sessionContext.isActive())
{
sessionContext.invalidate();
sessionContext.deactivate();
sessionContext.dissociate(sessionMaps.get());
sessionMaps.set(null);
sessionMaps.remove();
}
}
void startConversationScope(String cid)
{
RequestContextHolder rcHolder = requestContexts.get();
if (rcHolder == null)
{
startRequestScope();
rcHolder = requestContexts.get();
}
conversationContext.associate(new MutableBoundRequest(rcHolder.requestMap, sessionMaps.get()));
conversationContext.activate(cid);
}
void stopConversationScope()
{
RequestContextHolder rcHolder = requestContexts.get();
if (rcHolder == null)
{
startRequestScope();
rcHolder = requestContexts.get();
}
if (conversationContext.isActive())
{
conversationContext.invalidate();
conversationContext.deactivate();
conversationContext.dissociate(new MutableBoundRequest(rcHolder.getRequestMap(), sessionMaps.get()));
}
}
private static class RequestContextHolder
{
private final BoundRequestContext boundRequestContext;
private final Map<String, Object> requestMap;
private RequestContextHolder(BoundRequestContext boundRequestContext, Map<String, Object> requestMap)
{
this.boundRequestContext = boundRequestContext;
this.requestMap = requestMap;
}
public BoundRequestContext getBoundRequestContext()
{
return boundRequestContext;
}
public Map<String, Object> getRequestMap()
{
return requestMap;
}
}
}