org.jboss.weld.bean.AbstractProducerBean Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, 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.bean;
import static org.jboss.weld.util.reflection.Reflections.cast;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Type;
import java.util.Set;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.BeanAttributes;
import javax.enterprise.inject.spi.InjectionPoint;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMember;
import org.jboss.weld.bootstrap.BeanDeployerEnvironment;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.injection.CurrentInjectionPoint;
import org.jboss.weld.logging.BeanLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.serialization.spi.BeanIdentifier;
import org.jboss.weld.util.Beans;
import org.jboss.weld.util.Defaults;
import org.jboss.weld.util.reflection.Formats;
import org.jboss.weld.util.reflection.Reflections;
/**
* The implicit producer bean
*
* @param
* @param
* @param
* @author Gavin King
* @author David Allen
* @author Jozef Hartinger
*/
public abstract class AbstractProducerBean extends AbstractBean {
private final AbstractClassBean declaringBean;
// Passivation flags
private boolean passivationCapableBean;
private boolean passivationCapableDependency;
/**
* Constructor
*
* @param declaringBean The declaring bean
* @param beanManager The Bean manager
*/
public AbstractProducerBean(BeanAttributes attributes, BeanIdentifier identifier, AbstractClassBean declaringBean, BeanManagerImpl beanManager, ServiceRegistry services) {
super(attributes, identifier, beanManager);
this.declaringBean = declaringBean;
}
@Override
// Overridden to provide the class of the bean that declares the producer
// method/field
public Class> getBeanClass() {
return getDeclaringBean().getBeanClass();
}
/**
* Initializes the type
*/
protected void initType() {
try {
this.type = getEnhancedAnnotated().getJavaClass();
} catch (ClassCastException e) {
Type type = Beans.getDeclaredBeanType(getClass());
throw BeanLogger.LOG.producerCastError(getEnhancedAnnotated().getJavaClass(), (type == null ? " unknown " : type), e);
}
}
/**
* Initializes the bean and its metadata
*/
@Override
public void internalInitialize(BeanDeployerEnvironment environment) {
getDeclaringBean().initialize(environment);
super.internalInitialize(environment);
initPassivationCapable();
}
private void initPassivationCapable() {
this.passivationCapableBean = !Reflections.isFinal(getEnhancedAnnotated().getJavaClass()) || Reflections.isSerializable(getEnhancedAnnotated().getJavaClass());
if (isNormalScoped()) {
this.passivationCapableDependency = true;
} else if (getScope().equals(Dependent.class) && passivationCapableBean) {
this.passivationCapableDependency = true;
} else {
this.passivationCapableDependency = false;
}
}
@Override
public boolean isPassivationCapableBean() {
return passivationCapableBean;
}
@Override
public boolean isPassivationCapableDependency() {
return passivationCapableDependency;
}
@Override
public Set getInjectionPoints() {
return getProducer().getInjectionPoints();
}
/**
* Validates the return value
*
* @param instance The instance to validate
*/
protected T checkReturnValue(T instance) {
if (instance == null && !isDependent()) {
throw BeanLogger.LOG.nullNotAllowedFromProducer(getProducer(), Formats.formatAsStackTraceElement(getAnnotated().getJavaMember()));
}
if (instance == null) {
InjectionPoint injectionPoint = beanManager.getServices().get(CurrentInjectionPoint.class).peek();
if (injectionPoint != null) {
Class> injectionPointRawType = Reflections.getRawType(injectionPoint.getType());
if (injectionPointRawType.isPrimitive()) {
return cast(Defaults.getJlsDefaultValue(injectionPointRawType));
}
}
}
if (instance != null && !(instance instanceof Serializable)) {
if (beanManager.isPassivatingScope(getScope())) {
throw BeanLogger.LOG.nonSerializableProductError(getProducer(), Formats.formatAsStackTraceElement(getAnnotated().getJavaMember()));
}
InjectionPoint injectionPoint = beanManager.getServices().get(CurrentInjectionPoint.class).peek();
if (injectionPoint != null && injectionPoint.getBean() != null && Beans.isPassivatingScope(injectionPoint.getBean(), beanManager)) {
// Transient field is passivation capable injection point
if (!(injectionPoint.getMember() instanceof Field) || !injectionPoint.isTransient()) {
throw BeanLogger.LOG.unserializableProductInjectionError(this, Formats.formatAsStackTraceElement(getAnnotated().getJavaMember()),
injectionPoint, Formats.formatAsStackTraceElement(injectionPoint.getMember()));
}
}
}
return instance;
}
@Override
protected void checkType() {
if (beanManager.isPassivatingScope(getScope()) && !isPassivationCapableBean()) {
throw BeanLogger.LOG.passivatingBeanNeedsSerializableImpl(this);
}
}
protected boolean isTypeSerializable(final Object instance) {
return instance instanceof Serializable;
}
/**
* Creates an instance of the bean
*
* @returns The instance
*/
public T create(final CreationalContext creationalContext) {
T instance = getProducer().produce(creationalContext);
instance = checkReturnValue(instance);
return instance;
}
public void destroy(T instance, CreationalContext creationalContext) {
super.destroy(instance, creationalContext);
try {
getProducer().dispose(instance);
} catch (Exception e) {
BeanLogger.LOG.errorDestroying(instance, this);
BeanLogger.LOG.catchingDebug(e);
} finally {
if (getDeclaringBean().isDependent()) {
creationalContext.release();
}
}
}
/**
* Returns the declaring bean
*
* @return The bean representation
*/
public AbstractClassBean getDeclaringBean() {
return declaringBean;
}
@Override
public abstract AnnotatedMember super X> getAnnotated();
@Override
public abstract EnhancedAnnotatedMember getEnhancedAnnotated();
}