/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.weld;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.jboss.weld.bean.builtin.BeanManagerProxy;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.logging.BeanManagerLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.cache.ComputingCache;
import org.jboss.weld.util.cache.ComputingCacheBuilder;
/**
* Provides convenient way to access the CDI container.
*
* @author Jozef Hartinger
*
*/
public class SimpleCDI extends AbstractCDI<Object> {
private class ClassNameToBeanManager implements Function<String, BeanManagerProxy> {
/**
* Determines the correct {@link BeanManagerImpl} based on a class name of the caller.
*/
@Override
public BeanManagerProxy apply(String callerClassName) {
return new BeanManagerProxy(findBeanManager(callerClassName));
}
public BeanManagerImpl findBeanManager(String callerClassName) {
if (callerClassName == null) {
throw BeanManagerLogger.LOG.unableToIdentifyBeanManager();
}
Set<BeanManagerImpl> managers = new HashSet<BeanManagerImpl>();
for (Map.Entry<BeanDeploymentArchive, BeanManagerImpl> entry : container.beanDeploymentArchives().entrySet()) {
for (String className : entry.getKey().getBeanClasses()) {
if (className.equals(callerClassName)) {
managers.add(entry.getValue());
}
}
}
if (managers.size() == 1) {
return managers.iterator().next();
}
if (managers.size() == 0) {
return unsatisfiedBeanManager(callerClassName);
}
return ambiguousBeanManager(callerClassName, managers);
}
}
private final ComputingCache<String, BeanManagerProxy> beanManagers;
private final Container container;
public SimpleCDI() {
this(Container.instance());
}
public SimpleCDI(Container container) {
this.container = container;
beanManagers = ComputingCacheBuilder.newBuilder().setWeakValues().build(new ClassNameToBeanManager());
}
/**
* Callback that allows to override the behavior when CDI.current() is not called from within a bean archive.
*/
protected BeanManagerImpl unsatisfiedBeanManager(String callerClassName) {
throw BeanManagerLogger.LOG.unsatisfiedBeanManager(callerClassName);
}
/**
* Callback that allows to override the behavior when class that invoked CDI.current() is placed in multiple bean archives.
*/
protected BeanManagerImpl ambiguousBeanManager(String callerClassName, Set<BeanManagerImpl> managers) {
throw BeanManagerLogger.LOG.ambiguousBeanManager(callerClassName);
}
@Override
public BeanManagerProxy getBeanManager() {
ContainerState state = container.getState();
if (state.equals(ContainerState.STOPPED) || state.equals(ContainerState.SHUTDOWN)) {
throw BeanManagerLogger.LOG.beanManagerNotAvailable();
}
return beanManagers.getValue(getCallingClassName());
}
@Override
public String toString() {
return "Weld";
}
protected Container getContainer() {
return container;
}
public void cleanup() {
beanManagers.clear();
}
}