/* * 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.injection.producer; import java.util.HashSet; import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.InjectionTarget; import javax.enterprise.inject.spi.Interceptor; import javax.interceptor.Interceptors; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType; import org.jboss.weld.annotated.slim.SlimAnnotatedType; import org.jboss.weld.logging.BeanLogger; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.manager.api.WeldInjectionTarget; import org.jboss.weld.util.collections.ImmutableSet; import org.jboss.weld.util.reflection.Reflections; /** * Basic {@link InjectionTarget} implementation. The implementation supports: * <ul> * <li>@Inject injection + initializers</li> * <li>@PostConstruct/@PreDestroy callbacks</li> * </ul> * * Interception and decoration is not supported but can be added using extension points. * * @author Pete Muir * @author Jozef Hartinger */ public class BasicInjectionTarget<T> extends AbstractProducer<T> implements WeldInjectionTarget<T> { public static <T> BasicInjectionTarget<T> create(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Injector<T> injector, LifecycleCallbackInvoker<T> invoker) { return new BasicInjectionTarget<T>(type, bean, beanManager, injector, invoker); } public static <T> BasicInjectionTarget<T> createDefault(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Instantiator<T> instantiator) { return new BasicInjectionTarget<T>(type, bean, beanManager, instantiator); } /** * Creates {@link InjectionTarget} for interceptors which do not have associated {@link Interceptor}. These interceptors are a * result of using {@link Interceptors} annotation directly on the target class. */ public static <T> BasicInjectionTarget<T> createNonCdiInterceptor(EnhancedAnnotatedType<T> type, BeanManagerImpl beanManager) { return new BasicInjectionTarget<T>(type, null, beanManager, DefaultInjector.of(type, null, beanManager), NoopLifecycleCallbackInvoker.<T>getInstance()); } protected final BeanManagerImpl beanManager; private final SlimAnnotatedType<T> type; private final Set<InjectionPoint> injectionPoints; // Instantiation private Instantiator<T> instantiator; private final Injector<T> injector; private final LifecycleCallbackInvoker<T> invoker; protected BasicInjectionTarget(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Injector<T> injector, LifecycleCallbackInvoker<T> invoker) { this(type, bean, beanManager, injector, invoker, null); } protected BasicInjectionTarget(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Injector<T> injector, LifecycleCallbackInvoker<T> invoker, Instantiator<T> instantiator) { this.beanManager = beanManager; this.type = type.slim(); this.injector = injector; this.invoker = invoker; final Set<InjectionPoint> injectionPoints = new HashSet<InjectionPoint>(); checkType(type); this.injector.registerInjectionPoints(injectionPoints); if (instantiator != null) { this.instantiator = instantiator; } else { this.instantiator = initInstantiator(type, bean, beanManager, injectionPoints); } this.injectionPoints = ImmutableSet.copyOf(injectionPoints); checkDelegateInjectionPoints(); } protected BasicInjectionTarget(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Instantiator<T> instantiator) { this(type, bean, beanManager, DefaultInjector.of(type, bean, beanManager), DefaultLifecycleCallbackInvoker.of(type), instantiator); } protected void checkType(EnhancedAnnotatedType<T> type) { if (!Reflections.isTopLevelOrStaticNestedClass(type.getJavaClass())) { throw BeanLogger.LOG.simpleBeanAsNonStaticInnerClassNotAllowed(type); } } @Override public T produce(CreationalContext<T> ctx) { return instantiator.newInstance(ctx, beanManager); } @Override public void inject(T instance, CreationalContext<T> ctx) { injector.inject(instance, ctx, beanManager, type, this); } @Override public void postConstruct(T instance) { invoker.postConstruct(instance, instantiator); } @Override public void preDestroy(T instance) { invoker.preDestroy(instance, instantiator); } @Override public void dispose(T instance) { // No-op } @Override public Set<InjectionPoint> getInjectionPoints() { return injectionPoints; } protected SlimAnnotatedType<T> getType() { return type; } public BeanManagerImpl getBeanManager() { return beanManager; } public Instantiator<T> getInstantiator() { return instantiator; } public void setInstantiator(Instantiator<T> instantiator) { this.instantiator = instantiator; } public boolean hasInterceptors() { return instantiator.hasInterceptorSupport(); } public boolean hasDecorators() { return instantiator.hasDecoratorSupport(); } protected void initializeAfterBeanDiscovery(EnhancedAnnotatedType<T> annotatedType) { } /** * Returns an instantiator that will be used to create a new instance of a given component. If the instantiator uses a * constructor with injection points, the implementation of the * {@link #initInstantiator(EnhancedAnnotatedType, Bean, BeanManagerImpl, Set)} method is supposed to register all these * injection points within the injectionPoints set passed in as a parameter. */ protected Instantiator<T> initInstantiator(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Set<InjectionPoint> injectionPoints) { DefaultInstantiator<T> instantiator = new DefaultInstantiator<T>(type, bean, beanManager); injectionPoints.addAll(instantiator.getParameterInjectionPoints()); return instantiator; } @Override public AnnotatedType<T> getAnnotated() { return type; } @Override public AnnotatedType<T> getAnnotatedType() { return getAnnotated(); } public Injector<T> getInjector() { return injector; } public LifecycleCallbackInvoker<T> getLifecycleCallbackInvoker() { return invoker; } @Override public String toString() { StringBuilder result = new StringBuilder("InjectionTarget for "); if (getBean() == null) { result.append(getAnnotated()); } else { result.append(getBean()); } return result.toString(); } @Override public Bean<T> getBean() { return null; } }