diff --git a/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java b/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java index cce12c9ae64..3e2111c8fbf 100644 --- a/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java +++ b/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java @@ -16,10 +16,32 @@ */ package org.jboss.weld.bean; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.AnnotatedMethod; +import javax.enterprise.inject.spi.Decorator; +import javax.enterprise.inject.spi.InjectionTarget; +import javax.inject.Inject; + +import javassist.util.proxy.ProxyObject; +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.TargetBeanInstance; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.bootstrap.api.ServiceRegistry; import org.jboss.weld.exceptions.DefinitionException; +import org.jboss.weld.injection.FieldInjectionPoint; +import org.jboss.weld.injection.ForwardingInjectionTarget; import org.jboss.weld.injection.MethodInjectionPoint; import org.jboss.weld.injection.WeldInjectionPoint; import org.jboss.weld.introspector.MethodSignature; @@ -31,19 +53,6 @@ import org.jboss.weld.util.reflection.Formats; import org.jboss.weld.util.reflection.Reflections; -import javax.enterprise.inject.spi.AnnotatedMethod; -import javax.enterprise.inject.spi.Decorator; -import javax.inject.Inject; -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - import static org.jboss.weld.logging.messages.BeanMessage.ABSTRACT_METHOD_MUST_MATCH_DECORATED_TYPE; import static org.jboss.weld.logging.messages.BeanMessage.DECORATED_TYPE_PARAMETERIZED_DELEGATE_NOT; import static org.jboss.weld.logging.messages.BeanMessage.DELEGATE_MUST_SUPPORT_EVERY_DECORATED_TYPE; @@ -91,6 +100,7 @@ public static DecoratorImpl of(WeldClass clazz, BeanManagerImpl beanMa private WeldClass annotatedDelegateItem; private Map> decoratorMethods; private WeldInjectionPoint delegateInjectionPoint; + private FieldInjectionPoint delegateFieldInjectionPoint; private Set delegateBindings; private Type delegateType; private Set delegateTypes; @@ -122,6 +132,9 @@ protected void initDecoratedTypes() { protected void initDelegateInjectionPoint() { this.delegateInjectionPoint = getDelegateInjectionPoints().iterator().next(); + if(delegateInjectionPoint instanceof FieldInjectionPoint) { + this.delegateFieldInjectionPoint = (FieldInjectionPoint) delegateInjectionPoint; + } } @@ -197,6 +210,39 @@ private void checkAbstractMethods() { } } + @Override + public InjectionTarget getInjectionTarget() { + final InjectionTarget delegate = super.getInjectionTarget(); + if(delegateFieldInjectionPoint != null) { + return new ForwardingInjectionTarget() { + @Override + protected InjectionTarget delegate() { + return delegate; + } + + @Override + public void inject(final T instance, final CreationalContext ctx) { + super.inject(instance, ctx); + + if(delegateFieldInjectionPoint != null) { + if(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 + final Object delegate = delegateFieldInjectionPoint.getWeldField().get(instance); + final ProxyMethodHandler handler = new ProxyMethodHandler(new TargetBeanInstance(delegate), DecoratorImpl.this); + ((ProxyObject)instance).setHandler(handler); + } + } + } + }; + } + return delegate; + } public Set getDelegateQualifiers() { return delegateBindings; diff --git a/impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java b/impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java index 66ea2a97cf5..7c0a7804467 100644 --- a/impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java +++ b/impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java @@ -16,6 +16,24 @@ */ package org.jboss.weld.injection; +import java.io.ObjectInputStream; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Type; +import java.util.Set; + +import javax.decorator.Delegate; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.Instance; +import javax.enterprise.inject.spi.Annotated; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.Decorator; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.inject.Inject; + import edu.umd.cs.findbugs.annotations.SuppressWarnings; import org.jboss.interceptor.util.proxy.TargetInstanceProxy; import org.jboss.weld.bean.proxy.DecoratorProxy; @@ -28,23 +46,6 @@ import org.jboss.weld.util.AnnotatedTypes; import org.jboss.weld.util.reflection.Reflections; -import javax.decorator.Delegate; -import javax.enterprise.context.spi.CreationalContext; -import javax.enterprise.inject.Instance; -import javax.enterprise.inject.spi.Annotated; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.Decorator; -import javax.enterprise.inject.spi.InjectionPoint; -import javax.inject.Inject; -import java.io.ObjectInputStream; -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Type; -import java.util.Set; - import static org.jboss.weld.injection.Exceptions.rethrowException; import static org.jboss.weld.logging.messages.BeanMessage.PROXY_REQUIRED; @@ -94,6 +95,10 @@ public Bean getBean() { return declaringBean; } + public WeldField getWeldField() { + return field; + } + @Override public Set getQualifiers() { return delegate().getQualifiers(); diff --git a/impl/src/main/java/org/jboss/weld/injection/ForwardingInjectionTarget.java b/impl/src/main/java/org/jboss/weld/injection/ForwardingInjectionTarget.java new file mode 100644 index 00000000000..a0121539d02 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/injection/ForwardingInjectionTarget.java @@ -0,0 +1,39 @@ +package org.jboss.weld.injection; + +import java.util.Set; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.InjectionTarget; + +/** + * @author Stuart Douglas + */ +public abstract class ForwardingInjectionTarget implements InjectionTarget{ + + protected abstract InjectionTarget delegate(); + + public void inject(final T instance, final CreationalContext ctx) { + delegate().inject(instance, ctx); + } + + public void postConstruct(final T instance) { + delegate().postConstruct(instance); + } + + public void preDestroy(final T instance) { + delegate().preDestroy(instance); + } + + public T produce(final CreationalContext ctx) { + return delegate().produce(ctx); + } + + public void dispose(final T instance) { + delegate().dispose(instance); + } + + public Set getInjectionPoints() { + return delegate().getInjectionPoints(); + } +} diff --git a/impl/src/main/java/org/jboss/weld/injection/OnDemandBeanInstance.java b/impl/src/main/java/org/jboss/weld/injection/OnDemandBeanInstance.java deleted file mode 100644 index 970d6a475d2..00000000000 --- a/impl/src/main/java/org/jboss/weld/injection/OnDemandBeanInstance.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2011, Red Hat, Inc., and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.jboss.weld.injection; - -import java.io.Serializable; - -import org.jboss.weld.bean.proxy.AbstractBeanInstance; - -/** - * Create instance on demand / lazy. - * - * @author Ales Justin - */ -class OnDemandBeanInstance extends AbstractBeanInstance implements Serializable { - private InstanceProvider provider; - private volatile Object instance; - - public OnDemandBeanInstance(InstanceProvider provider) { - this.provider = provider; - } - - public Object getInstance() { - if (instance == null) { - synchronized (this) { - if (instance == null) { - instance = provider.provideInstance(); - provider = null; - } - } - } - return instance; - } - - public Class getInstanceType() { - return getInstance().getClass(); - } - - static interface InstanceProvider extends Serializable { - Object provideInstance(); - } -} diff --git a/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java b/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java index f3bdd2887f0..68825eef41b 100644 --- a/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java +++ b/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java @@ -24,7 +24,6 @@ import javax.enterprise.inject.spi.Bean; import javassist.util.proxy.ProxyObject; -import org.jboss.weld.bean.DecoratorImpl; import org.jboss.weld.bean.proxy.BeanInstance; import org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler; import org.jboss.weld.bean.proxy.ProxyFactory; @@ -84,18 +83,6 @@ public T newInstance(final BeanManagerImpl manager, final CreationalContext c BeanInstance beanInstance = null; if (decoratorDelegate != null) { beanInstance = new TargetBeanInstance(decoratorDelegate); - } else if (bean instanceof DecoratorImpl) { - DecoratorImpl di = (DecoratorImpl) bean; - final WeldInjectionPoint ip = di.getDelegateInjectionPoint(); - if (ip instanceof FieldInjectionPoint) { - beanInstance = new OnDemandBeanInstance(new FieldInstanceProvider(ip, instance)); - } else if (ip instanceof MethodInjectionPoint) { - beanInstance = new OnDemandBeanInstance(new MethodInstanceProvider(ip, instance)); - } else if (ip instanceof ParameterInjectionPoint) { - beanInstance = new OnDemandBeanInstance(new ParameterInstanceProvider(ip, manager, creationalContext)); - } else { - throw new IllegalArgumentException("Invalid InjectionPoint: " + ip); - } } ProxyFactory.setBeanInstance(instance, beanInstance, bean); } else { @@ -105,56 +92,4 @@ public T newInstance(final BeanManagerImpl manager, final CreationalContext c } return instance; } - - private static class FieldInstanceProvider implements OnDemandBeanInstance.InstanceProvider { - private final WeldInjectionPoint ip; - private final T instance; - - public FieldInstanceProvider(final WeldInjectionPoint ip, final T instance) { - this.ip = ip; - this.instance = instance; - } - - public Object provideInstance() { - FieldInjectionPoint fip = (FieldInjectionPoint) ip; - return fip.delegate().get(instance); - } - } - - private static class ParameterInstanceProvider implements OnDemandBeanInstance.InstanceProvider { - private final WeldInjectionPoint ip; - private final BeanManagerImpl manager; - private final CreationalContext creationalContext; - - public ParameterInstanceProvider(final WeldInjectionPoint ip, final BeanManagerImpl manager, final CreationalContext creationalContext) { - this.ip = ip; - this.manager = manager; - this.creationalContext = creationalContext; - } - - public Object provideInstance() { - ParameterInjectionPoint pip = (ParameterInjectionPoint) ip; - // special value handling? - return pip.getValueToInject(manager, creationalContext); - } - } - - private static class MethodInstanceProvider implements OnDemandBeanInstance.InstanceProvider { - private final WeldInjectionPoint ip; - private final T instance; - - public MethodInstanceProvider(final WeldInjectionPoint ip, final T instance) { - this.ip = ip; - this.instance = instance; - } - - public Object provideInstance() { - MethodInjectionPoint mip = (MethodInjectionPoint) ip; - try { - return mip.delegate().invokeOnInstance(instance); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } }