/* * JBoss, Home of Professional Open Source * Copyright 2012, 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.lang.reflect.Field; import java.lang.reflect.Type; import java.security.AccessController; import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.InjectionTarget; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType; import org.jboss.weld.bean.DecoratorImpl; import org.jboss.weld.bean.proxy.DecoratorProxy; import org.jboss.weld.bean.proxy.DecoratorProxyFactory; import org.jboss.weld.bean.proxy.ProxyMethodHandler; import org.jboss.weld.bean.proxy.ProxyObject; import org.jboss.weld.bean.proxy.TargetBeanInstance; import org.jboss.weld.injection.ConstructorInjectionPoint; import org.jboss.weld.injection.FieldInjectionPoint; import org.jboss.weld.injection.InjectionPointFactory; import org.jboss.weld.injection.attributes.WeldInjectionPointAttributes; import org.jboss.weld.logging.UtilLogger; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.security.GetAccessibleCopyOfMember; import org.jboss.weld.util.Decorators; /** * {@link InjectionTarget} implementation used for decorators. * * @author Jozef Hartinger * * @param <T> */ public class DecoratorInjectionTarget<T> extends BeanInjectionTarget<T> { private final WeldInjectionPointAttributes<?, ?> delegateInjectionPoint; private final Field accessibleField; public DecoratorInjectionTarget(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager) { super(type, bean, beanManager); this.delegateInjectionPoint = Decorators.findDelegateInjectionPoint(type, getInjectionPoints()); if (delegateInjectionPoint instanceof FieldInjectionPoint<?, ?>) { FieldInjectionPoint<?, ?> fip = (FieldInjectionPoint<?, ?>) delegateInjectionPoint; this.accessibleField = AccessController.doPrivileged(new GetAccessibleCopyOfMember<Field>(fip.getAnnotated().getJavaMember())); } else { this.accessibleField = null; } checkAbstractMethods(type); } @Override protected Instantiator<T> initInstantiator(EnhancedAnnotatedType<T> type, Bean<T> bean, BeanManagerImpl beanManager, Set<InjectionPoint> injectionPoints) { if (type.isAbstract()) { ConstructorInjectionPoint<T> originalConstructor = InjectionPointFactory.instance().createConstructorInjectionPoint(bean, type, beanManager); injectionPoints.addAll(originalConstructor.getParameterInjectionPoints()); final WeldInjectionPointAttributes<?, ?> delegateInjectionPoint = Decorators.findDelegateInjectionPoint(type, injectionPoints); return new SubclassedComponentInstantiator<T>(type, bean, originalConstructor, beanManager) { @Override protected Class<T> createEnhancedSubclass(EnhancedAnnotatedType<T> type, Bean<?> bean, BeanManagerImpl manager) { return new DecoratorProxyFactory<T>(manager.getContextId(), type.getJavaClass(), delegateInjectionPoint, bean).getProxyClass(); } }; } else { DefaultInstantiator<T> instantiator = new DefaultInstantiator<T>(type, bean, beanManager); injectionPoints.addAll(instantiator.getConstructorInjectionPoint().getParameterInjectionPoints()); return instantiator; } } @Override protected void checkDelegateInjectionPoints() { // noop, delegate injection points are checked in Decorators#findDelegateInjectionPoint() called within the constructor } @Override public void inject(T instance, CreationalContext<T> ctx) { super.inject(instance, ctx); if (accessibleField != null && instance instanceof DecoratorProxy) { // this code is only applicable if the delegate is injected into a field // as the proxy can't intercept the delegate when setting the field // we need to now read the delegate from the field // this is only needed for fields, as constructor and method injection are handed // at injection time Object delegate; try { delegate = accessibleField.get(instance); } catch (IllegalAccessException e) { throw UtilLogger.LOG.accessErrorOnField(accessibleField.getName(), accessibleField.getDeclaringClass(), e); } final ProxyMethodHandler handler = new ProxyMethodHandler(beanManager.getContextId(), new TargetBeanInstance(delegate), getBean()); ((ProxyObject) instance).setHandler(handler); } } @Override public void initializeAfterBeanDiscovery(EnhancedAnnotatedType<T> annotatedType) { // noop } @SuppressWarnings("unchecked") private void checkAbstractMethods(EnhancedAnnotatedType<T> type) { if(!type.isAbstract()) { return; } Set<Type> decoratedTypes = null; Bean<?> bean = getBean(); if(bean != null && (bean instanceof DecoratorImpl)) { decoratedTypes = ((DecoratorImpl<T>)bean).getDecoratedTypes(); } Decorators.checkAbstractMethods(decoratedTypes, type, beanManager); } }