diff --git a/impl/src/main/java/org/jboss/weld/bean/AbstractClassBean.java b/impl/src/main/java/org/jboss/weld/bean/AbstractClassBean.java index b24903ac2ac..7907181fa01 100644 --- a/impl/src/main/java/org/jboss/weld/bean/AbstractClassBean.java +++ b/impl/src/main/java/org/jboss/weld/bean/AbstractClassBean.java @@ -52,10 +52,11 @@ import org.jboss.interceptor.model.InterceptionModelBuilder; import org.jboss.interceptor.model.InterceptorMetadata; import org.jboss.interceptor.util.InterceptionUtils; -import org.jboss.interceptor.util.proxy.TargetInstanceProxy; import org.jboss.weld.bean.interceptor.InterceptionMetadataService; import org.jboss.weld.bean.interceptor.WeldClassReference; import org.jboss.weld.bean.proxy.DecorationHelper; +import org.jboss.weld.bean.proxy.ProxyFactory; +import org.jboss.weld.bean.proxy.TargetBeanInstance; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.context.SerializableContextualImpl; import org.jboss.weld.ejb.EJBApiAbstraction; @@ -71,8 +72,6 @@ import org.jboss.weld.metadata.cache.MetaAnnotationStore; import org.jboss.weld.serialization.spi.helpers.SerializableContextual; import org.jboss.weld.util.Beans; -import org.jboss.weld.util.Proxies; -import org.jboss.weld.util.Proxies.TypeInfo; import org.jboss.weld.util.reflection.SecureReflections; import org.slf4j.cal10n.LocLogger; @@ -184,10 +183,6 @@ public void initialize(BeanDeployerEnvironment environment) public void initializeAfterBeanDiscovery() { initDecorators(); - if (hasDecorators()) - { - initProxyClassForDecoratedBean(); - } super.initializeAfterBeanDiscovery(); } @@ -201,15 +196,12 @@ public boolean hasDecorators() return this.decorators != null && this.decorators.size() > 0; } - protected void initProxyClassForDecoratedBean() - { - this.proxyClassForDecorators = Proxies.createProxyClass(TypeInfo.of(getTypes()).add(TargetInstanceProxy.class)); - } - protected T applyDecorators(T instance, CreationalContext creationalContext, InjectionPoint originalInjectionPoint) { T proxy = null; - DecorationHelper decorationHelper = new DecorationHelper(instance, proxyClassForDecorators, beanManager, decorators); + TargetBeanInstance beanInstance = new TargetBeanInstance(this, instance); + ProxyFactory proxyFactory = new ProxyFactory(beanInstance); + DecorationHelper decorationHelper = new DecorationHelper(beanInstance, proxyFactory.getProxyClass(), beanManager, decorators); DecorationHelper.getHelperStack().push(decorationHelper); proxy = decorationHelper.getNextDelegate(originalInjectionPoint, creationalContext); 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 131600126c2..1e23384fe07 100644 --- a/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java +++ b/impl/src/main/java/org/jboss/weld/bean/DecoratorImpl.java @@ -29,7 +29,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -39,6 +38,9 @@ import javax.inject.Inject; import org.jboss.weld.bean.proxy.AbstractDecoratorMethodHandler; +import org.jboss.weld.bean.proxy.DecoratorProxyFactory; +import org.jboss.weld.bean.proxy.ProxyFactory; +import org.jboss.weld.bean.proxy.TargetBeanInstance; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.exceptions.DefinitionException; import org.jboss.weld.injection.MethodInjectionPoint; @@ -53,7 +55,6 @@ import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.resources.ClassTransformer; import org.jboss.weld.util.Decorators; -import org.jboss.weld.util.Proxies; import org.jboss.weld.util.reflection.Reflections; public class DecoratorImpl extends ManagedBean implements WeldDecorator @@ -141,6 +142,15 @@ protected void initDecoratedTypes() protected void initDelegateInjectionPoint() { this.delegateInjectionPoint = getDelegateInjectionPoints().iterator().next(); + if (getWeldAnnotated().isAbstract()) + { + Class clazz = new DecoratorProxyFactory(getWeldAnnotated().getJavaClass(), delegateInjectionPoint).getProxyClass(); + proxyClassForAbstractDecorators = beanManager.getServices().get(ClassTransformer.class).loadClass(clazz); + constructorForAbstractDecorator = WeldConstructorImpl.of( + proxyClassForAbstractDecorators.getDeclaredWeldConstructor(getConstructor().getSignature()), + proxyClassForAbstractDecorators, + beanManager.getServices().get(ClassTransformer.class)); + } } @Override @@ -249,31 +259,6 @@ public Set getDecoratedTypes() return delegateInjectionPoint; } - @Override - protected void initType() - { - super.initType(); - if (getWeldAnnotated().isAbstract()) - { - Proxies.TypeInfo typeInfo = Proxies.TypeInfo.of(Collections.singleton(getWeldAnnotated().getJavaClass())); - Class clazz = Proxies.createProxyClass(null, typeInfo); - proxyClassForAbstractDecorators = beanManager.getServices().get(ClassTransformer.class).loadClass(clazz); - } - } - - @Override - protected void initConstructor() - { - super.initConstructor(); - if (getWeldAnnotated().isAbstract()) - { - constructorForAbstractDecorator = WeldConstructorImpl.of( - proxyClassForAbstractDecorators.getDeclaredWeldConstructor(getConstructor().getSignature()), - proxyClassForAbstractDecorators, - beanManager.getServices().get(ClassTransformer.class)); - } - } - @Override public void initDecorators() { @@ -291,7 +276,6 @@ protected T createInstance(CreationalContext ctx) { ProxyClassConstructorInjectionPointWrapper constructorInjectionPointWrapper = new ProxyClassConstructorInjectionPointWrapper(this, constructorForAbstractDecorator, getConstructor()); T instance = constructorInjectionPointWrapper.newInstance(beanManager, ctx); - Proxies.attachMethodHandler(instance, new AbstractDecoratorMethodHandler(annotatedDelegateItem, getDelegateInjectionPoint(), constructorInjectionPointWrapper.getInjectedDelegate())); return instance; } } diff --git a/impl/src/main/java/org/jboss/weld/bean/ManagedBean.java b/impl/src/main/java/org/jboss/weld/bean/ManagedBean.java index 90437f41322..75725321d00 100644 --- a/impl/src/main/java/org/jboss/weld/bean/ManagedBean.java +++ b/impl/src/main/java/org/jboss/weld/bean/ManagedBean.java @@ -52,6 +52,8 @@ import org.jboss.weld.bean.interceptor.ClassInterceptionHandlerFactory; import org.jboss.weld.bean.interceptor.InterceptionMetadataService; import org.jboss.weld.bean.interceptor.WeldClassReference; +import org.jboss.weld.bean.proxy.ProxyFactory; +import org.jboss.weld.bean.proxy.TargetBeanInstance; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.exceptions.DefinitionException; import org.jboss.weld.exceptions.DeploymentException; @@ -67,7 +69,6 @@ import org.jboss.weld.serialization.spi.helpers.SerializableContextual; import org.jboss.weld.util.AnnotatedTypes; import org.jboss.weld.util.Beans; -import org.jboss.weld.util.CleanableMethodHandler; import org.jboss.weld.util.reflection.Reflections; import org.slf4j.cal10n.LocLogger; import org.slf4j.ext.XLogger; @@ -581,8 +582,10 @@ protected T applyInterceptors(T instance, final CreationalContext creationalC if (interceptionRegistries.size() > 0) { InterceptorProxyCreatorImpl interceptorProxyCreator = new InterceptorProxyCreatorImpl(interceptionRegistries, interceptionHandlerFactories); - MethodHandler methodHandler = new CleanableMethodHandler(interceptorProxyCreator.createMethodHandler(instance, getType(), getBeanManager().getServices().get(InterceptionMetadataService.class).getInterceptorMetadataRegistry().getInterceptorClassMetadata(WeldClassReference.of(getWeldAnnotated()), true))); - instance = interceptorProxyCreator.createProxyInstance(InterceptionUtils.createProxyClassWithHandler(getType(), methodHandler), methodHandler); + MethodHandler methodHandler = interceptorProxyCreator.createMethodHandler(instance, getType(), getBeanManager().getServices().get(InterceptionMetadataService.class).getInterceptorMetadataRegistry().getInterceptorClassMetadata(WeldClassReference.of(getWeldAnnotated()), true)); + TargetBeanInstance targetInstance = new TargetBeanInstance(this, instance); + targetInstance.setInterceptorsHandler(methodHandler); + instance = new ProxyFactory(targetInstance).create(targetInstance); } } diff --git a/impl/src/main/java/org/jboss/weld/bean/SessionBean.java b/impl/src/main/java/org/jboss/weld/bean/SessionBean.java index f640e283e68..2cf39df4b41 100644 --- a/impl/src/main/java/org/jboss/weld/bean/SessionBean.java +++ b/impl/src/main/java/org/jboss/weld/bean/SessionBean.java @@ -30,7 +30,6 @@ import static org.jboss.weld.logging.messages.BeanMessage.SCOPE_NOT_ALLOWED_ON_STATELESS_SESSION_BEAN; import static org.jboss.weld.logging.messages.BeanMessage.SPECIALIZING_ENTERPRISE_BEAN_MUST_EXTEND_AN_ENTERPRISE_BEAN; -import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -55,7 +54,10 @@ import org.jboss.weld.bean.interceptor.InterceptorBindingsAdapter; import org.jboss.weld.bean.proxy.EnterpriseBeanInstance; import org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler; +import org.jboss.weld.bean.proxy.EnterpriseProxyFactory; +import org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance; import org.jboss.weld.bean.proxy.Marker; +import org.jboss.weld.bean.proxy.ProxyFactory; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.ejb.InternalEjbDescriptor; import org.jboss.weld.ejb.api.SessionObjectReference; @@ -74,8 +76,6 @@ import org.jboss.weld.serialization.spi.helpers.SerializableContextual; import org.jboss.weld.util.AnnotatedTypes; import org.jboss.weld.util.Beans; -import org.jboss.weld.util.Proxies; -import org.jboss.weld.util.Proxies.TypeInfo; import org.jboss.weld.util.reflection.HierarchyDiscovery; import org.jboss.weld.util.reflection.SecureReflections; @@ -245,7 +245,7 @@ protected void initTypes() protected void initProxyClass() { - this.proxyClass = Proxies.createProxyClass(TypeInfo.of(getTypes()).add(EnterpriseBeanInstance.class).add(Serializable.class)); + this.proxyClass = new EnterpriseProxyFactory(getWeldAnnotated().getJavaClass()).getProxyClass(); } /** @@ -322,7 +322,7 @@ public T create(final CreationalContext creationalContext) { T instance = SecureReflections.newInstance(proxyClass); creationalContext.push(instance); - Proxies.attachMethodHandler(instance, new EnterpriseBeanProxyMethodHandler(SessionBean.this, creationalContext)); + ProxyFactory.setBeanInstance(instance, new EnterpriseTargetBeanInstance(getWeldAnnotated().getJavaClass(), new EnterpriseBeanProxyMethodHandler(SessionBean.this, creationalContext))); if (hasDecorators()) { instance = applyDecorators(instance, creationalContext, null); diff --git a/impl/src/main/java/org/jboss/weld/bean/builtin/ee/AbstractEEBean.java b/impl/src/main/java/org/jboss/weld/bean/builtin/ee/AbstractEEBean.java index dcd48853e41..7f14f8d8ccf 100644 --- a/impl/src/main/java/org/jboss/weld/bean/builtin/ee/AbstractEEBean.java +++ b/impl/src/main/java/org/jboss/weld/bean/builtin/ee/AbstractEEBean.java @@ -16,10 +16,6 @@ */ package org.jboss.weld.bean.builtin.ee; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED; - -import java.io.Serializable; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Set; @@ -29,16 +25,15 @@ import org.jboss.weld.bean.builtin.AbstractBuiltInBean; import org.jboss.weld.bean.builtin.CallableMethodHandler; -import org.jboss.weld.exceptions.DefinitionException; +import org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance; +import org.jboss.weld.bean.proxy.ProxyFactory; import org.jboss.weld.manager.BeanManagerImpl; -import org.jboss.weld.util.Proxies; -import org.jboss.weld.util.Proxies.TypeInfo; public abstract class AbstractEEBean extends AbstractBuiltInBean { - - private final T proxy; - private final Class type; + + private final T proxy; + private final Class type; private final Set types; protected AbstractEEBean(Class type, Callable callable, BeanManagerImpl beanManager) @@ -48,36 +43,25 @@ protected AbstractEEBean(Class type, Callable callable, BeanManagerImpl be this.types = new HashSet(); this.types.add(Object.class); this.types.add(type); - try - { - this.proxy = Proxies.createProxy(new CallableMethodHandler(callable), TypeInfo.of(getTypes()).add(Serializable.class)); - } - catch (InstantiationException e) - { - throw new DefinitionException(PROXY_INSTANTIATION_FAILED, e, this); - } - catch (IllegalAccessException e) - { - throw new DefinitionException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, this); - } + this.proxy = new ProxyFactory(type).create(new EnterpriseTargetBeanInstance(type, new CallableMethodHandler(callable))); } public T create(CreationalContext creationalContext) { return proxy; } - - public void destroy(T instance, CreationalContext creationalContext) + + public void destroy(T instance, CreationalContext creationalContext) { // no-op } - + @Override public Class getType() { return type; } - + public Set getTypes() { return types; diff --git a/impl/src/main/java/org/jboss/weld/bean/builtin/ee/EEResourceProducerField.java b/impl/src/main/java/org/jboss/weld/bean/builtin/ee/EEResourceProducerField.java index 438fa84e277..7f262740675 100644 --- a/impl/src/main/java/org/jboss/weld/bean/builtin/ee/EEResourceProducerField.java +++ b/impl/src/main/java/org/jboss/weld/bean/builtin/ee/EEResourceProducerField.java @@ -18,8 +18,6 @@ import static org.jboss.weld.logging.messages.BeanMessage.BEAN_NOT_EE_RESOURCE_PRODUCER; import static org.jboss.weld.logging.messages.BeanMessage.INVALID_RESOURCE_PRODUCER_FIELD; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED; import java.io.Serializable; @@ -30,34 +28,32 @@ import org.jboss.weld.bean.AbstractClassBean; import org.jboss.weld.bean.ProducerField; import org.jboss.weld.bean.builtin.CallableMethodHandler; +import org.jboss.weld.bean.proxy.BeanInstance; +import org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance; +import org.jboss.weld.bean.proxy.ProxyFactory; import org.jboss.weld.bootstrap.BeanDeployerEnvironment; import org.jboss.weld.ejb.EJBApiAbstraction; import org.jboss.weld.exceptions.ForbiddenStateException; -import org.jboss.weld.exceptions.WeldException; import org.jboss.weld.introspector.WeldField; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.persistence.PersistenceApiAbstraction; import org.jboss.weld.serialization.spi.ContextualStore; -import org.jboss.weld.util.Proxies; -import org.jboss.weld.util.Proxies.TypeInfo; import org.jboss.weld.util.reflection.Reflections; import org.jboss.weld.ws.WSApiAbstraction; /** * @author pmuir - * */ public class EEResourceProducerField extends ProducerField { - - + private static class EEResourceCallable extends AbstractEECallable { - - private static final long serialVersionUID = 6287931036073200963L; - - private final String beanId; - private transient T instance; + + private static final long serialVersionUID = 6287931036073200963L; + + private final String beanId; + private transient T instance; private final CreationalContext creationalContext; public EEResourceCallable(BeanManagerImpl beanManager, ProducerField producerField, CreationalContext creationalContext) @@ -71,12 +67,12 @@ public T call() throws Exception { if (instance == null) { - Contextual contextual = Container.instance().services().get(ContextualStore.class)., T>getContextual(beanId); + Contextual contextual = Container.instance().services().get(ContextualStore.class)., T> getContextual(beanId); if (contextual instanceof EEResourceProducerField) { @SuppressWarnings("unchecked") EEResourceProducerField bean = (EEResourceProducerField) contextual; - + this.instance = bean.createUnderlying(creationalContext); } else @@ -86,15 +82,15 @@ public T call() throws Exception } return instance; } - + @Override public String toString() { return beanId; } - + } - + /** * Creates an EE resource producer field * @@ -112,7 +108,7 @@ protected EEResourceProducerField(WeldField field, AbstractClassBe { super(field, declaringBean, manager); } - + @Override public void initialize(BeanDeployerEnvironment environment) { @@ -122,7 +118,7 @@ public void initialize(BeanDeployerEnvironment environment) checkEEResource(); } } - + protected void checkEEResource() { EJBApiAbstraction ejbApiAbstraction = beanManager.getServices().get(EJBApiAbstraction.class); @@ -133,31 +129,21 @@ protected void checkEEResource() throw new ForbiddenStateException(INVALID_RESOURCE_PRODUCER_FIELD, getWeldAnnotated()); } } - + @Override public T create(CreationalContext creationalContext) { - try - { - if (Reflections.isFinal(getWeldAnnotated().getJavaClass()) || Serializable.class.isAssignableFrom(getWeldAnnotated().getJavaClass())) - { - return createUnderlying(creationalContext); - } - else - { - return Proxies.createProxy(new CallableMethodHandler(new EEResourceCallable(getBeanManager(), this, creationalContext)), TypeInfo.of(getTypes()).add(Serializable.class)); - } - } - catch (InstantiationException e) + if (Reflections.isFinal(getWeldAnnotated().getJavaClass()) || Serializable.class.isAssignableFrom(getWeldAnnotated().getJavaClass())) { - throw new WeldException(PROXY_INSTANTIATION_FAILED, e, this); + return createUnderlying(creationalContext); } - catch (IllegalAccessException e) + else { - throw new WeldException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, this); + BeanInstance proxyBeanInstance = new EnterpriseTargetBeanInstance(getTypes(), new CallableMethodHandler(new EEResourceCallable(getBeanManager(), this, creationalContext))); + return new ProxyFactory(proxyBeanInstance).create(proxyBeanInstance); } } - + /** * Access to the underlying producer field */ @@ -165,12 +151,11 @@ private T createUnderlying(CreationalContext creationalContext) { return super.create(creationalContext); } - + @Override public boolean isPassivationCapableBean() { return true; } - } diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/AbstractBeanInstance.java b/impl/src/main/java/org/jboss/weld/bean/proxy/AbstractBeanInstance.java new file mode 100644 index 00000000000..9ce32da43a2 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/AbstractBeanInstance.java @@ -0,0 +1,72 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import static org.jboss.weld.logging.Category.BEAN; +import static org.jboss.weld.logging.LoggerFactory.loggerFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Set; + +import javax.enterprise.inject.spi.Bean; + +import org.jboss.weld.util.Proxies.TypeInfo; +import org.jboss.weld.util.reflection.SecureReflections; +import org.slf4j.cal10n.LocLogger; + +/** + * @author David Allen + */ +public abstract class AbstractBeanInstance implements BeanInstance +{ + // The log provider + protected static final LocLogger log = loggerFactory().getLogger(BEAN); + + public Object invoke(Method method, Object... arguments) throws Throwable + { + Object result = null; + try + { + SecureReflections.ensureAccessible(method); + result = method.invoke(getInstance(), arguments); + } + catch (InvocationTargetException e) + { + throw e.getCause(); + } + return result; + } + + protected Class computeInstanceType(Bean bean) + { + return computeInstanceType(bean.getTypes()); + } + + protected Class computeInstanceType(Set types) + { + TypeInfo typeInfo = TypeInfo.of(types); + Class superClass = typeInfo.getSuperClass(); + if (superClass.equals(Object.class)) + { + superClass = typeInfo.getSuperInterface(); + } + return superClass; + } +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/BeanInstance.java b/impl/src/main/java/org/jboss/weld/bean/proxy/BeanInstance.java new file mode 100644 index 00000000000..9be0d3227b2 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/BeanInstance.java @@ -0,0 +1,43 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import java.lang.reflect.Method; + +/** + * Each proxy maintains a single bean instance on which methods + * are invoked. Different types of bean instances can also + * be used to provide varying methods of obtaining the actual + * instance from the container. + * + * @author David Allen + * + */ +public interface BeanInstance +{ + /** + * Returns the current instance for a proxy. + * + * @return the current bean instance + */ + public Object getInstance(); + + public Class getInstanceType(); + + public Object invoke(Method method, Object... arguments) throws Throwable; +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/ClientProxyProvider.java b/impl/src/main/java/org/jboss/weld/bean/proxy/ClientProxyProvider.java index 9c15b032d6d..ee0d90fbe7e 100644 --- a/impl/src/main/java/org/jboss/weld/bean/proxy/ClientProxyProvider.java +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/ClientProxyProvider.java @@ -17,22 +17,14 @@ package org.jboss.weld.bean.proxy; import static org.jboss.weld.logging.messages.BeanMessage.BEAN_ID_CREATION_FAILED; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED; -import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED; -import java.io.Serializable; import java.util.concurrent.ConcurrentMap; import javax.enterprise.inject.spi.Bean; -import org.jboss.interceptor.proxy.LifecycleMixin; import org.jboss.weld.Container; -import org.jboss.weld.bean.AbstractClassBean; import org.jboss.weld.exceptions.DefinitionException; -import org.jboss.weld.exceptions.WeldException; import org.jboss.weld.serialization.spi.ContextualStore; -import org.jboss.weld.util.Proxies; -import org.jboss.weld.util.Proxies.TypeInfo; import com.google.common.base.Function; import com.google.common.collect.MapMaker; @@ -91,27 +83,29 @@ public ClientProxyProvider() */ private static T createClientProxy(Bean bean, String id) throws RuntimeException { - try - { - TypeInfo typeInfo; - if ((bean instanceof AbstractClassBean) && ((AbstractClassBean)bean).hasInterceptors()) - { - typeInfo = TypeInfo.of(bean.getTypes()).add(Serializable.class).add(LifecycleMixin.class); - } - else - { - typeInfo = TypeInfo.of(bean.getTypes()).add(Serializable.class); - } - return Proxies.createProxy(new ClientProxyMethodHandler(bean, id), typeInfo); - } - catch (InstantiationException e) - { - throw new WeldException(PROXY_INSTANTIATION_FAILED, e, bean); - } - catch (IllegalAccessException e) - { - throw new WeldException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, bean); - } + ContextBeanInstance beanInstance = new ContextBeanInstance(bean, id); + return new ProxyFactory(beanInstance).create(beanInstance); +// try +// { +// TypeInfo typeInfo; +// if ((bean instanceof AbstractClassBean) && ((AbstractClassBean)bean).hasInterceptors()) +// { +// typeInfo = TypeInfo.of(bean.getTypes()).add(Serializable.class).add(LifecycleMixin.class); +// } +// else +// { +// typeInfo = TypeInfo.of(bean.getTypes()).add(Serializable.class); +// } +// return Proxies.createProxy(new ClientProxyMethodHandler(bean, id), typeInfo); +// } +// catch (InstantiationException e) +// { +// throw new WeldException(PROXY_INSTANTIATION_FAILED, e, bean); +// } +// catch (IllegalAccessException e) +// { +// throw new WeldException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, bean); +// } } /** @@ -123,6 +117,7 @@ private static T createClientProxy(Bean bean, String id) throws RuntimeEx * @param bean The bean to get a proxy to * @return the client proxy for the bean */ + @SuppressWarnings("unchecked") public T getClientProxy(final Bean bean) { return (T) pool.get(bean); diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/ContextBeanInstance.java b/impl/src/main/java/org/jboss/weld/bean/proxy/ContextBeanInstance.java new file mode 100644 index 00000000000..c0ff89546c2 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/ContextBeanInstance.java @@ -0,0 +1,111 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import java.io.Serializable; + +import javax.enterprise.context.spi.Context; +import javax.enterprise.inject.spi.Bean; + +import org.jboss.weld.Container; +import org.jboss.weld.context.CreationalContextImpl; +import org.jboss.weld.context.WeldCreationalContext; +import org.jboss.weld.injection.CurrentInjectionPoint; +import org.jboss.weld.injection.SimpleInjectionPoint; +import org.jboss.weld.serialization.spi.ContextualStore; + +/** + * An instance locator that uses a context to lookup the instance if + * it exists; otherwise, a new instance will be created from the + * bean. + * + * @author David Allen + * + */ +public class ContextBeanInstance extends AbstractBeanInstance implements Serializable +{ + + private static final long serialVersionUID = -8144230657830556503L; + // The bean + private transient Bean bean; + // The bean index in the manager + private final String id; + // The actual type of the resulting bean instance + private final Class instanceType; + + private static final ThreadLocal> currentCreationalContext = new ThreadLocal>(); + + /** + * Creates a new locator for instances of the given bean. + * + * @param bean The contextual bean + * @param id The unique identifier of this bean + */ + public ContextBeanInstance(Bean bean, String id) + { + this.bean = bean; + this.id = id; + this.instanceType = computeInstanceType(bean); + log.trace("Created context instance locator for bean " + bean + " identified as " + id); + } + + public T getInstance() + { + if (bean == null) + { + bean = Container.instance().services().get(ContextualStore.class)., T>getContextual(id); + } + Context context = Container.instance().deploymentManager().getContext(bean.getScope()); + WeldCreationalContext creationalContext; + WeldCreationalContext previousCreationalContext = currentCreationalContext.get(); + if (currentCreationalContext.get() == null) + { + creationalContext = new CreationalContextImpl(bean); + } + else + { + creationalContext = currentCreationalContext.get().getCreationalContext(bean); + } + currentCreationalContext.set(creationalContext); + try + { + // Ensure that there is no injection point associated + Container.instance().services().get(CurrentInjectionPoint.class).push(SimpleInjectionPoint.EMPTY_INJECTION_POINT); + return context.get(bean, creationalContext); + } + finally + { + Container.instance().services().get(CurrentInjectionPoint.class).pop(); + if (previousCreationalContext == null) + { + currentCreationalContext.remove(); + } + else + { + currentCreationalContext.set(previousCreationalContext); + } + } + } + + @SuppressWarnings("unchecked") + public Class getInstanceType() + { + return (Class) instanceType; + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/DecorationHelper.java b/impl/src/main/java/org/jboss/weld/bean/proxy/DecorationHelper.java index d0a9710eac8..68679656bc1 100644 --- a/impl/src/main/java/org/jboss/weld/bean/proxy/DecorationHelper.java +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/DecorationHelper.java @@ -47,7 +47,9 @@ public class DecorationHelper } }; - private Class proxyClassForDecorator; + private final Class proxyClassForDecorator; + + private final TargetBeanInstance targetBeanInstance; private T originalInstance; @@ -59,9 +61,11 @@ public class DecorationHelper List> decorators; - public DecorationHelper(T originalInstance, Class proxyClassForDecorator, BeanManagerImpl beanManager, List> decorators) + @SuppressWarnings("unchecked") + public DecorationHelper(TargetBeanInstance originalInstance, Class proxyClassForDecorator, BeanManagerImpl beanManager, List> decorators) { - this.originalInstance = originalInstance; + this.originalInstance = (T) originalInstance.getInstance(); + this.targetBeanInstance = originalInstance; this.beanManager = beanManager; this.decorators = new LinkedList>(decorators); this.proxyClassForDecorator = proxyClassForDecorator; @@ -92,7 +96,9 @@ public T getNextDelegate(InjectionPoint injectionPoint, CreationalContext cre try { T proxy = SecureReflections.newInstance(proxyClassForDecorator); - Proxies.attachMethodHandler(proxy, createMethodHandler(injectionPoint, creationalContext, (Decorator) decorators.get(counter++))); + TargetBeanInstance newTargetBeanInstance = new TargetBeanInstance(targetBeanInstance); + newTargetBeanInstance.setInterceptorsHandler(createMethodHandler(injectionPoint, creationalContext, (Decorator) decorators.get(counter++))); + ProxyFactory.setBeanInstance(proxy, newTargetBeanInstance); previousDelegate = proxy; return proxy; } diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/DecoratorProxyFactory.java b/impl/src/main/java/org/jboss/weld/bean/proxy/DecoratorProxyFactory.java new file mode 100644 index 00000000000..cb055fec899 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/DecoratorProxyFactory.java @@ -0,0 +1,237 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.NotFoundException; + +import javax.decorator.Delegate; + +import org.jboss.weld.exceptions.WeldException; +import org.jboss.weld.injection.FieldInjectionPoint; +import org.jboss.weld.injection.ParameterInjectionPoint; +import org.jboss.weld.injection.WeldInjectionPoint; + +/** + * This special proxy factory is mostly used for abstract decorators. When + * a delegate field is injected, the abstract methods directly invoke the + * corresponding method on the delegate. All other cases forward the calls + * to the {@link BeanInstance} for further processing. + * + * @author David Allen + */ +public class DecoratorProxyFactory extends ProxyFactory +{ + private static final String PROXY_SUFFIX = "DecoratorProxy"; + private final WeldInjectionPoint delegateInjectionPoint; + private final CtClass delegateClass; + private final Field delegateField; + + public DecoratorProxyFactory(Class proxyType, WeldInjectionPoint delegateInjectionPoint) + { + super(proxyType); + this.delegateInjectionPoint = delegateInjectionPoint; + try + { + delegateClass = classPool.get(((Class) delegateInjectionPoint.getBaseType()).getName()); + } + catch (NotFoundException e) + { + throw new WeldException(e); + } + if (delegateInjectionPoint instanceof FieldInjectionPoint) + { + delegateField = ((FieldInjectionPoint) delegateInjectionPoint).getJavaMember(); + } + else + { + delegateField = null; + } + } + + @Override + protected void addConstructors(CtClass proxyClassType) + { + try + { + CtClass baseType = classPool.get(beanType.getName()); + for (CtConstructor constructor : baseType.getConstructors()) + { + int delegateInjectionPosition = getDelegateInjectionPosition(constructor); + if (delegateInjectionPosition >= 0) + { + proxyClassType.addConstructor(CtNewConstructor.make(constructor.getParameterTypes(), constructor.getExceptionTypes(), createDelegateInitializerCode(null, delegateInjectionPosition), proxyClassType)); + } + else + { + proxyClassType.addConstructor(CtNewConstructor.copy(constructor, proxyClassType, null)); + } + } + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + @Override + protected void addMethodsFromClass(CtClass proxyClassType) + { + String initializerMethod = null; + int delegateParameterPosition = -1; + if (delegateInjectionPoint instanceof ParameterInjectionPoint) + { + ParameterInjectionPoint parameterIP = (ParameterInjectionPoint) delegateInjectionPoint; + if (parameterIP.getMember() instanceof Method) + { + initializerMethod = ((Method) parameterIP.getMember()).getName(); + delegateParameterPosition = parameterIP.getPosition(); + } + } + try + { + for (CtMethod method : proxyClassType.getMethods()) + { + if (!method.getDeclaringClass().getName().equals("java.lang.Object") || method.getName().equals("toString")) + { + log.trace("Adding method " + method.getLongName()); + String methodBody = null; + if ((delegateParameterPosition >= 0) && (initializerMethod.equals(method.getName()))) + { + methodBody = createDelegateInitializerCode(initializerMethod, delegateParameterPosition); + } + else if (Modifier.isAbstract(method.getModifiers())) + { + methodBody = createAbstractMethodCode(method); + } + + if (methodBody != null) + { + proxyClassType.addMethod(CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(), method.getExceptionTypes(), methodBody, proxyClassType)); + } + } + } + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + @Override + protected String getProxyNameSuffix() + { + return PROXY_SUFFIX; + } + + private String createAbstractMethodCode(CtMethod method) throws NotFoundException + { + CtMethod delegateMethod = null; + StringBuilder bodyString = new StringBuilder(); + bodyString.append("{ "); + try + { + delegateMethod = delegateClass.getMethod(method.getName(), method.getSignature()); + if (method.getReturnType() != null) + { + bodyString.append("return ($r)"); + } + } + catch (NotFoundException e) + { + throw new WeldException(e); + } + + if ((delegateField != null) && (!Modifier.isPrivate(delegateField.getModifiers()))) + { + // Call the corresponding method directly on the delegate + bodyString.append(delegateField.getName()); + bodyString.append('.'); + bodyString.append(method.getName()); + bodyString.append("($$); }"); + log.trace("Delegating call directly to delegate for method " + method.getLongName()); + } + else + { + // Use the associated bean instance to invoke the method + bodyString.append("beanInstance.invoke("); + if (Modifier.isPublic(delegateMethod.getModifiers())) + { + bodyString.append("beanInstance.getInstanceType().getMethod(\""); + log.trace("Using getMethod in proxy for method " + method.getLongName()); + } + else + { + bodyString.append(method.getDeclaringClass().getName()); + bodyString.append(".class.getDeclaredMethod(\""); + log.trace("Using getDeclaredMethod in proxy for method " + method.getLongName()); + } + bodyString.append(method.getName()); + bodyString.append("\", "); + bodyString.append(getSignatureClasses(method)); + bodyString.append("), $args); }"); + } + + return bodyString.toString(); + } + + private String createDelegateInitializerCode(String initializerName, int delegateParameterPosition) + { + StringBuilder buffer = new StringBuilder(); + buffer.append("{ super"); + if (initializerName != null) + { + buffer.append('.'); + buffer.append(initializerName); + } + buffer.append("($$);\n"); + buffer.append("beanInstance = new "); + buffer.append(TargetBeanInstance.class.getName()); + buffer.append("($"); + buffer.append(delegateParameterPosition + 1); + buffer.append("); }"); + return buffer.toString(); + } + + private int getDelegateInjectionPosition(CtConstructor constructor) + { + int position = -1; + Object[][] parameterAnnotations = constructor.getAvailableParameterAnnotations(); + for (int i = 0; i < parameterAnnotations.length; i++) + { + for (int j = 0; j < parameterAnnotations[i].length; j++) + { + if (parameterAnnotations[i][j] instanceof Delegate) + { + position = i; + break; + } + } + } + return position; + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseProxyFactory.java b/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseProxyFactory.java new file mode 100644 index 00000000000..2f141168a35 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseProxyFactory.java @@ -0,0 +1,72 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtNewConstructor; + +import org.jboss.weld.exceptions.WeldException; + +/** + * This factory produces proxies specific for enterprise beans, in particular + * session beans. It adds the interface {@link EnterpriseBeanInstance} to + * each proxy class. + * + * @author David Allen + */ +public class EnterpriseProxyFactory extends ProxyFactory +{ + private static final String PROXY_SUFFIX = "EnterpriseProxy"; + + /** + * Produces a factory for a specific bean implementation. + * + * @param proxiedBeanType the actual enterprise bean + */ + public EnterpriseProxyFactory(Class proxiedBeanType) + { + super(proxiedBeanType); + addInterface(EnterpriseBeanInstance.class); + } + + // Not sure this is a useful approach, but non-default constructors are problematic (DRA) + @Override + protected void addConstructors(CtClass proxyClassType) + { + try + { + CtClass baseType = classPool.get(beanType.getName()); + for (CtConstructor constructor : baseType.getConstructors()) + { + proxyClassType.addConstructor(CtNewConstructor.copy(constructor, proxyClassType, null)); + } + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + @Override + protected String getProxyNameSuffix() + { + return PROXY_SUFFIX; + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseTargetBeanInstance.java b/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseTargetBeanInstance.java new file mode 100644 index 00000000000..02f67cee9e8 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/EnterpriseTargetBeanInstance.java @@ -0,0 +1,65 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Set; + +import javassist.util.proxy.MethodHandler; + +/** + * @author David Allen + */ +public class EnterpriseTargetBeanInstance extends AbstractBeanInstance implements Serializable +{ + private static final long serialVersionUID = 2825052095047112162L; + + private final Class beanType; + private final MethodHandler methodHandler; + + public EnterpriseTargetBeanInstance(Class baseType, MethodHandler methodHandler) + { + this.beanType = baseType; + this.methodHandler = methodHandler; + } + + public EnterpriseTargetBeanInstance(Set types, MethodHandler methodHandler) + { + this.beanType = computeInstanceType(types); + this.methodHandler = methodHandler; + } + + public Object getInstance() + { + return null; + } + + public Class getInstanceType() + { + return beanType; + } + + public Object invoke(Method method, Object... arguments) throws Throwable + { + // Pass the invocation directly to the method handler + return methodHandler.invoke(null, method, method, arguments); + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/Proxy.java b/impl/src/main/java/org/jboss/weld/bean/proxy/Proxy.java new file mode 100644 index 00000000000..ea4adad6e23 --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/Proxy.java @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +/** + * General interface for all proxies adding functionality that can change + * the behavior of the proxy during runtime. + * + * @author David Allen + * + */ +public interface Proxy +{ + /** + * Gets the proxied bean instance. + * + * @return the bean instance being proxied + */ + public BeanInstance proxy_getInstance(); + + /** + * Sets the proxied instance. + * + * @param beanInstance a bean instance to proxy + */ + public void proxy_setInstance(BeanInstance beanInstance); +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java b/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java new file mode 100644 index 00000000000..95a2ddc504c --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java @@ -0,0 +1,439 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import static org.jboss.weld.logging.Category.BEAN; +import static org.jboss.weld.logging.LoggerFactory.loggerFactory; +import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED; +import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED; + +import java.io.Serializable; +import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Arrays; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.NotFoundException; + +import org.jboss.interceptor.proxy.LifecycleMixin; +import org.jboss.interceptor.util.proxy.TargetInstanceProxy; +import org.jboss.weld.bean.proxy.util.ClassloaderClassPath; +import org.jboss.weld.exceptions.DefinitionException; +import org.jboss.weld.exceptions.WeldException; +import org.slf4j.cal10n.LocLogger; + +/** + * Main factory to produce proxy classes and instances for Weld beans. This + * implementation creates proxies which forward non-static method invocations to + * a {@link BeanInstance}. All proxies implement the {@link Proxy} interface. + * + * @author David Allen + */ +public class ProxyFactory +{ + // The log provider + protected static final LocLogger log = loggerFactory().getLogger(BEAN); + // Default proxy class name suffix + private static final String PROXY_SUFFIX = "Proxy"; + + protected final Class beanType; + protected final ArrayList> additionalInterfaces = new ArrayList>(); + protected ClassLoader classLoader; + protected ProtectionDomain protectionDomain; + protected ClassPool classPool; + + /** + * Creates a new proxy factory from any type of BeanInstance. This bean + * instance is only used for initialization information and is not associated + * with this factory once created. + * + * @param instance a bean instance that will be used with the proxy + */ + public ProxyFactory(BeanInstance beanInstance) + { + this.beanType = beanInstance.getInstanceType(); + init(); + } + + /** + * Creates a new proxy factory with only the type of proxy specified. + * + * @param proxiedBeanType the super-class for this proxy class + */ + public ProxyFactory(Class proxiedBeanType) + { + this.beanType = proxiedBeanType; + init(); + } + + /** + * Initializes the proxy factory. + */ + private void init() + { + classLoader = beanType.getClassLoader(); + protectionDomain = beanType.getProtectionDomain(); + if (beanType.getName().startsWith("java.")) + { + classLoader = this.getClass().getClassLoader(); + protectionDomain = this.getClass().getProtectionDomain(); + } + classPool = new ClassPool(); + classPool.appendClassPath(new ClassloaderClassPath(classLoader)); + addDefaultAdditionalInterfaces(); + } + + /** + * Adds an additional interface that the proxy should implement. The default + * implementation will be to forward invocations to the bean instance. + * + * @param newInterface an interface + */ + public void addInterface(Class newInterface) + { + if (!newInterface.isInterface()) + { + throw new IllegalArgumentException(newInterface + " is not an interface"); + } + additionalInterfaces.add(newInterface); + } + + /** + * Method to create a new proxy that wraps the bean instance. + * + * @return a new proxy object + */ + public T create(BeanInstance beanInstance) + { + T proxy = null; + Class proxyClass = getProxyClass(); + try + { + proxy = proxyClass.newInstance(); + } + catch (InstantiationException e) + { + throw new DefinitionException(PROXY_INSTANTIATION_FAILED, e, this); + } + catch (IllegalAccessException e) + { + throw new DefinitionException(PROXY_INSTANTIATION_BEAN_ACCESS_FAILED, e, this); + } + ((Proxy) proxy).proxy_setInstance(beanInstance); + return proxy; + } + + /** + * Produces or returns the existing proxy class. + * + * @return always the class of the proxy + */ + @SuppressWarnings("unchecked") + public Class getProxyClass() + { + String proxyClassName = beanType.getName() + "_$$_Weld" + getProxyNameSuffix(); + if (proxyClassName.startsWith("java.")) + { + proxyClassName = proxyClassName.replaceFirst("java", "org.jboss.weld"); + } + Class proxyClass = null; + log.trace("Retrieving/generating proxy class " + proxyClassName); + try + { + // First check to see if we already have this proxy class + proxyClass = (Class) classLoader.loadClass(proxyClassName); + } + catch (ClassNotFoundException e) + { + // Create the proxy class for this instance + try + { + proxyClass = createProxyClass(proxyClassName); + } + catch (Exception e1) + { + throw new WeldException(e1); + } + } + return proxyClass; + } + + /** + * Convenience method to set the underlying bean instance for a proxy. + * + * @param proxy the proxy instance + * @param beanInstance the instance of the bean + */ + public static void setBeanInstance(T proxy, BeanInstance beanInstance) + { + if (proxy instanceof Proxy) + { + Proxy proxyView = (Proxy) proxy; + proxyView.proxy_setInstance(beanInstance); + } + } + + /** + * Returns a suffix to append to the name of the proxy class. The name + * already consists of _$$_Weld, to which the suffix is added. + * This allows the creation of different types of proxies for the same class. + * + * @return a name suffix + */ + protected String getProxyNameSuffix() + { + return PROXY_SUFFIX; + } + + private void addDefaultAdditionalInterfaces() + { + additionalInterfaces.add(Serializable.class); + } + + @SuppressWarnings("unchecked") + private Class createProxyClass(String proxyClassName) throws Exception + { + CtClass instanceType = classPool.get(beanType.getName()); + CtClass proxyClassType = null; + if (instanceType.isInterface()) + { + proxyClassType = classPool.makeClass(proxyClassName); + proxyClassType.addInterface(instanceType); + } + else + { + proxyClassType = classPool.makeClass(proxyClassName, instanceType); + } + + // Add interfaces which require method generation + for (Class clazz : additionalInterfaces) + { + proxyClassType.addInterface(classPool.get(clazz.getName())); + } + addFields(proxyClassType); + addConstructors(proxyClassType); + addMethods(proxyClassType); + + // Additional interfaces whose methods require special handling + proxyClassType.addInterface(classPool.get(Proxy.class.getName())); + proxyClassType.addInterface(classPool.get(LifecycleMixin.class.getName())); + proxyClassType.addInterface(classPool.get(TargetInstanceProxy.class.getName())); + + Class proxyClass = proxyClassType.toClass(classLoader, protectionDomain); + proxyClassType.detach(); + log.trace("Created Proxy class of type " + proxyClass + " supporting interfaces " + Arrays.toString(proxyClass.getInterfaces())); + return proxyClass; + } + + /** + * Adds a public default constructor to the proxy class for ease of + * instantiating it. + * + * @param proxyClassType the Javassist class for the proxy + */ + protected void addConstructors(CtClass proxyClassType) + { + try + { + proxyClassType.addConstructor(CtNewConstructor.defaultConstructor(proxyClassType)); + } + catch (CannotCompileException e) + { + throw new WeldException(e); + } + } + + private void addFields(CtClass proxyClassType) + { + // The field for the instance locator + try + { + proxyClassType.addField(new CtField(classPool.get("org.jboss.weld.bean.proxy.BeanInstance"), "beanInstance", proxyClassType)); + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + private void addMethods(CtClass proxyClassType) + { + // Add all class methods for interception + addMethodsFromClass(proxyClassType); + + // Add special proxy methods + addSpecialMethods(proxyClassType); + } + + protected void addMethodsFromClass(CtClass proxyClassType) + { + try + { + for (CtMethod method : proxyClassType.getMethods()) + { + if (!Modifier.isStatic(method.getModifiers()) && !method.getDeclaringClass().getName().equals("java.lang.Object") || method.getName().equals("toString")) + { + log.trace("Adding method " + method.getLongName()); + proxyClassType.addMethod(CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(), method.getExceptionTypes(), createInterceptorBody(method), proxyClassType)); + } + } + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + /** + * Creates the given method on the proxy class where the implementation + * forwards the call directly to the bean instance. + * + * @param method any Javassist method + * @return a string containing the method body code to be compiled + * @throws NotFoundException if any of the parameter types are not found + */ + protected String createInterceptorBody(CtMethod method) throws NotFoundException + { + StringBuilder bodyString = new StringBuilder(); + bodyString.append("{ "); + try + { + if (method.getReturnType() != null) + { + bodyString.append("return ($r)"); + } + } + catch (NotFoundException e) + { + // Assume this is a void method + } + + bodyString.append("beanInstance.invoke("); + if (Modifier.isPublic(method.getModifiers())) + { + bodyString.append("beanInstance.getInstanceType().getMethod(\""); + log.trace("Using getMethod in proxy for method " + method.getLongName()); + } + else + { + bodyString.append(method.getDeclaringClass().getName()); + bodyString.append(".class.getDeclaredMethod(\""); + log.trace("Using getDeclaredMethod in proxy for method " + method.getLongName()); + } + bodyString.append(method.getName()); + bodyString.append("\", "); + bodyString.append(getSignatureClasses(method)); + bodyString.append("), $args); }"); + + return bodyString.toString(); + } + + /** + * Produces the code for the list of argument types for the given method. + * + * @param method the method for which to produce the parameter list + * @return a string of comma-delimited class objects + * @throws NotFoundException if any of the parameter types are not found by + * Javassist + */ + protected String getSignatureClasses(CtMethod method) throws NotFoundException + { + if (method.getParameterTypes().length > 0) + { + StringBuilder signatureBuffer = new StringBuilder(); + signatureBuffer.append("new Class[]{"); + boolean firstClass = true; + for (CtClass clazz : method.getParameterTypes()) + { + if (firstClass) + { + firstClass = false; + } + else + { + signatureBuffer.append(", "); + } + signatureBuffer.append(clazz.getName()); + signatureBuffer.append(".class"); + } + signatureBuffer.append('}'); + return signatureBuffer.toString(); + } + else + { + return "null"; + } + } + + private void addSpecialMethods(CtClass proxyClassType) + { + try + { + // Add public getter/setter pair for the instance locator + proxyClassType.addMethod(CtNewMethod.make("public org.jboss.weld.bean.proxy.BeanInstance proxy_getInstance() { return beanInstance; }", proxyClassType)); + proxyClassType.addMethod(CtNewMethod.make("public void proxy_setInstance(org.jboss.weld.bean.proxy.BeanInstance beanInstance) { this.beanInstance = beanInstance; }", proxyClassType)); + + // Add special methods for interceptors + CtClass lifecycleMixinClass = classPool.get(LifecycleMixin.class.getName()); + for (CtMethod method : lifecycleMixinClass.getDeclaredMethods()) + { + log.trace("Adding method " + method.getLongName()); + proxyClassType.addMethod(CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(), method.getExceptionTypes(), createLifecycleBody(method), proxyClassType)); + } + CtClass targetInstanceProxyClass = classPool.get(TargetInstanceProxy.class.getName()); + CtMethod getInstanceMethod = targetInstanceProxyClass.getDeclaredMethod("getTargetInstance"); + CtMethod getInstanceClassMethod = targetInstanceProxyClass.getDeclaredMethod("getTargetClass"); + proxyClassType.addMethod(CtNewMethod.make(getInstanceMethod.getReturnType(), getInstanceMethod.getName(), getInstanceMethod.getParameterTypes(), getInstanceMethod.getExceptionTypes(), "{ return beanInstance.getInstance(); }", proxyClassType)); + proxyClassType.addMethod(CtNewMethod.make(getInstanceClassMethod.getReturnType(), getInstanceClassMethod.getName(), getInstanceClassMethod.getParameterTypes(), getInstanceClassMethod.getExceptionTypes(), "{ return beanInstance.getInstanceType(); }", proxyClassType)); + } + catch (Exception e) + { + throw new WeldException(e); + } + } + + /** + * Creates the method body code for lifecycle methods which forward the calls + * directly to the bean instance. + * + * @param method a lifecycle method + * @return code for the body of the method to be compiled + * @throws NotFoundException if any of the parameter types are not found + */ + private String createLifecycleBody(CtMethod method) throws NotFoundException + { + StringBuilder bodyString = new StringBuilder(); + bodyString.append("{ beanInstance.invoke("); + bodyString.append(LifecycleMixin.class.getName()); + bodyString.append(".class.getDeclaredMethod(\""); + bodyString.append(method.getName()); + bodyString.append("\", "); + bodyString.append(getSignatureClasses(method)); + bodyString.append("), $args); }"); + + return bodyString.toString(); + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/TargetBeanInstance.java b/impl/src/main/java/org/jboss/weld/bean/proxy/TargetBeanInstance.java new file mode 100644 index 00000000000..31d624149da --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/TargetBeanInstance.java @@ -0,0 +1,105 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy; + +import java.io.Serializable; +import java.lang.reflect.Method; + +import javassist.util.proxy.MethodHandler; + +import javax.enterprise.inject.spi.Bean; + +/** + * A simple {@link BeanInstance} which always maintains a specific bean instance + * that is being proxied. + * + * @author David Allen + */ +public class TargetBeanInstance extends AbstractBeanInstance implements Serializable +{ + private static final long serialVersionUID = 1099995238604086450L; + private final Object instance; + private final Class instanceType; + private MethodHandler interceptorsHandler; + + public TargetBeanInstance(Bean bean, Object instance) + { + this.instance = instance; + this.instanceType = computeInstanceType(bean); + } + + public TargetBeanInstance(Object instance) + { + this.instance = instance; + this.instanceType = (Class) instance.getClass(); + } + + /** + * Copy constructor + * + * @param otherBeanInstance other bean instance to copy + */ + public TargetBeanInstance(TargetBeanInstance otherBeanInstance) + { + this.instance = otherBeanInstance.instance; + this.instanceType = otherBeanInstance.instanceType; + this.interceptorsHandler = otherBeanInstance.interceptorsHandler; + } + + public Object getInstance() + { + return instance; + } + + public Class getInstanceType() + { + return instanceType; + } + + /** + * @return the interceptorsHandler + */ + public MethodHandler getInterceptorsHandler() + { + return interceptorsHandler; + } + + /** + * @param interceptorsHandler the interceptorsHandler to set + */ + public void setInterceptorsHandler(MethodHandler interceptorsHandler) + { + this.interceptorsHandler = interceptorsHandler; + } + + @Override + public Object invoke(Method method, Object... arguments) throws Throwable + { + if (interceptorsHandler != null) + { + log.trace("Invoking interceptor chain for method " + method.toGenericString() + " on " + getInstance()); + return interceptorsHandler.invoke(getInstance(), method, method, arguments); + } + else + { + log.trace("Invoking method " + method.toGenericString() + " directly on " + getInstance()); + return super.invoke(method, arguments); + } + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/util/ClassloaderClassPath.java b/impl/src/main/java/org/jboss/weld/bean/proxy/util/ClassloaderClassPath.java new file mode 100644 index 00000000000..a18428fd46e --- /dev/null +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/util/ClassloaderClassPath.java @@ -0,0 +1,59 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2008, Red Hat, Inc. and/or its affiliates, 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.proxy.util; + +import java.io.InputStream; +import java.net.URL; + +import javassist.ClassPath; +import javassist.NotFoundException; + +/** + * A special classpath type used with the high-level Javassist API to lookup + * class bytecode through a specific classloader. This avoids the problem + * of finding classes in Javassist when it is used in JEE containers. + * + * @author David Allen + * + */ +public class ClassloaderClassPath implements ClassPath +{ + private final ClassLoader classLoader; + + public ClassloaderClassPath(ClassLoader classLoader) + { + this.classLoader = classLoader; + } + + public void close() + { + } + + public URL find(String classname) + { + String resourceName = classname.replace('.', '/') + ".class"; + return classLoader.getResource(resourceName); + } + + public InputStream openClassfile(String classname) throws NotFoundException + { + String resourceName = classname.replace('.', '/') + ".class"; + return classLoader.getResourceAsStream(resourceName); + } + +} diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/WeldBootstrap.java b/impl/src/main/java/org/jboss/weld/bootstrap/WeldBootstrap.java index 7cfb3d8ed9f..19f8cc471dc 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/WeldBootstrap.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/WeldBootstrap.java @@ -91,7 +91,6 @@ import org.jboss.weld.servlet.ServletApiAbstraction; import org.jboss.weld.servlet.api.ServletServices; import org.jboss.weld.transaction.spi.TransactionServices; -import org.jboss.weld.util.JavassistCleaner; import org.jboss.weld.util.Names; import org.jboss.weld.util.collections.Arrays2; import org.jboss.weld.util.serviceProvider.DefaultServiceLoaderFactory; @@ -321,7 +320,6 @@ private ServiceRegistry getImplementationServices(ResourceLoader resourceLoader) services.add(MetaAnnotationStore.class, new MetaAnnotationStore(services.get(ClassTransformer.class))); services.add(ContextualStore.class, new ContextualStoreImpl()); services.add(ServiceLoaderFactory.class, new DefaultServiceLoaderFactory()); - services.add(JavassistCleaner.class, new JavassistCleaner()); services.add(InterceptionMetadataService.class, new InterceptionMetadataService()); services.add(CurrentInjectionPoint.class, new CurrentInjectionPoint()); return services; 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 728eaa577f5..d34852007a6 100644 --- a/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java +++ b/impl/src/main/java/org/jboss/weld/injection/ProxyClassConstructorInjectionPointWrapper.java @@ -39,8 +39,6 @@ public class ProxyClassConstructorInjectionPointWrapper extends ConstructorIn { private ConstructorInjectionPoint originalConstructorInjectionPoint; - private Object injectedDelegate; - public ProxyClassConstructorInjectionPointWrapper(Bean declaringBean, WeldConstructor weldConstructor, ConstructorInjectionPoint originalConstructorInjectionPoint) { super(declaringBean, weldConstructor); @@ -52,31 +50,4 @@ public List> getWeldParameters() { return originalConstructorInjectionPoint.getWeldParameters(); } - - @Override - protected Object[] getParameterValues(List> parameters, Object specialVal, Class specialParam, BeanManagerImpl manager, CreationalContext creationalContext) - { - Object[] parameterValues = super.getParameterValues(parameters, specialVal, specialParam, manager, creationalContext); - if (parameters.size() > 0) - { - for (ParameterInjectionPoint parameterInjectionPoint: parameters) - { - if (parameterInjectionPoint.isDelegate()) - { - this.injectedDelegate = parameterValues[parameterInjectionPoint.getPosition()]; - } - } - } - return parameterValues; - } - - /** - * The delegate injected during the constructed process, if any - * - * @return - */ - public Object getInjectedDelegate() - { - return injectedDelegate; - } } diff --git a/impl/src/main/java/org/jboss/weld/util/CleanableMethodHandler.java b/impl/src/main/java/org/jboss/weld/util/CleanableMethodHandler.java deleted file mode 100644 index 133de6967bf..00000000000 --- a/impl/src/main/java/org/jboss/weld/util/CleanableMethodHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.util; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.lang.reflect.Method; - -import javassist.util.proxy.MethodHandler; - -import org.jboss.weld.Container; - -public class CleanableMethodHandler implements MethodHandler, Serializable -{ - - private static final long serialVersionUID = 2140367342468307705L; - - private MethodHandler delegate; - - public CleanableMethodHandler(MethodHandler delegate) - { - this.delegate = delegate; - Container.instance().services().get(JavassistCleaner.class).add(this); - } - - public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable - { - return delegate.invoke(self, thisMethod, proceed, args); - } - - public void clean() - { - this.delegate = null; - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - Container.instance().services().get(JavassistCleaner.class).add(this); - } - -} diff --git a/impl/src/main/java/org/jboss/weld/util/JavassistCleaner.java b/impl/src/main/java/org/jboss/weld/util/JavassistCleaner.java deleted file mode 100644 index 8d6312b5779..00000000000 --- a/impl/src/main/java/org/jboss/weld/util/JavassistCleaner.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.util; - -import java.util.ArrayList; -import java.util.Collection; - -import org.jboss.weld.bootstrap.api.Service; - -public class JavassistCleaner implements Service -{ - - private final Collection cleanableMethodHandlers; - - public JavassistCleaner() - { - this.cleanableMethodHandlers = new ArrayList(); - } - - public void add(CleanableMethodHandler cleanableMethodHandler) - { - cleanableMethodHandlers.add(cleanableMethodHandler); - } - - public void cleanup() - { - for (CleanableMethodHandler cleanableMethodHandler : cleanableMethodHandlers) - { - cleanableMethodHandler.clean(); - } - cleanableMethodHandlers.clear(); - } - -} \ No newline at end of file diff --git a/impl/src/main/java/org/jboss/weld/util/Proxies.java b/impl/src/main/java/org/jboss/weld/util/Proxies.java index b1f4fe9d8ee..596f1ddb141 100644 --- a/impl/src/main/java/org/jboss/weld/util/Proxies.java +++ b/impl/src/main/java/org/jboss/weld/util/Proxies.java @@ -102,6 +102,25 @@ public Class getSuperClass() return superclass; } + public Class getSuperInterface() + { + if (interfaces.isEmpty()) + { + return null; + } + Iterator> it = interfaces.iterator(); + Class superclass = it.next(); + while (it.hasNext()) + { + Class clazz = it.next(); + if (superclass.isAssignableFrom(clazz)) + { + superclass = clazz; + } + } + return superclass; + } + private Class[] getInterfaces() { return interfaces.toArray(EMPTY_CLASSES); @@ -166,78 +185,6 @@ public static TypeInfo create() } - /** - * Create a proxy with a handler, registering the proxy for cleanup - * - * @param - * @param methodHandler - * @param typeInfo - * @return - * @throws IllegalAccessException - * @throws InstantiationException - */ - public static T createProxy(MethodHandler methodHandler, TypeInfo typeInfo) throws IllegalAccessException, InstantiationException - { - if (InstantiatorFactory.useInstantiators()) - { - Class proxyClass = Proxies. createProxyClass(methodHandler, typeInfo); - T instance = SecureReflections.newUnsafeInstance(proxyClass); - setMethodHandler(proxyClass, instance, methodHandler); - return instance; - } - else - { - return SecureReflections.newInstance(Proxies. createProxyClass(methodHandler, typeInfo)); - } - } - - private static void setMethodHandler(Class clazz, T instance, MethodHandler methodHandler) - { - try - { - Method setter = SecureReflections.getDeclaredMethod(clazz, "setHandler", MethodHandler.class); - SecureReflections.invoke(instance, setter, methodHandler); - } - catch (Exception e) - { - throw new WeldException(METHODHANDLER_SET_FAILED, e, clazz); - } - } - - /** - * Create a proxy class - * - * You will need to manually register the proxy instances for cleanup - * - * @param - * @param typeInfo - * @return - */ - public static Class createProxyClass(TypeInfo typeInfo) - { - return createProxyClass(null, typeInfo); - } - - /** - * Create a proxy class - * - * You will need to manually register the proxy instances for cleanup - * - * @param - * @param methodHandler - * @param typeInfo - * @return - */ - public static Class createProxyClass(MethodHandler methodHandler, TypeInfo typeInfo) - { - ProxyFactory proxyFactory = typeInfo.createProxyFactory(); - attachMethodHandler(proxyFactory, methodHandler); - - @SuppressWarnings("unchecked") - Class clazz = proxyFactory.createClass(); - return clazz; - } - /** * Indicates if a class is proxyable * @@ -341,31 +288,4 @@ else if (Reflections.isArrayType(clazz)) return null; } } - - public static ProxyFactory attachMethodHandler(ProxyFactory proxyFactory, MethodHandler methodHandler) - { - if (methodHandler != null) - { - proxyFactory.setHandler(new CleanableMethodHandler(methodHandler)); - } - return proxyFactory; - } - - public static T attachMethodHandler(T instance, MethodHandler methodHandler) - { - if (instance instanceof ProxyObject) - { - if (methodHandler != null) - { - ((ProxyObject) instance).setHandler(new CleanableMethodHandler(methodHandler)); - } - return instance; - } - else - { - throw new ForbiddenArgumentException(INSTANCE_NOT_A_PROXY, instance); - } - - } - } diff --git a/porting-package/src/main/java/org/jboss/weld/tck/BeansImpl.java b/porting-package/src/main/java/org/jboss/weld/tck/BeansImpl.java index 75a2a4c9432..b4148d430e7 100644 --- a/porting-package/src/main/java/org/jboss/weld/tck/BeansImpl.java +++ b/porting-package/src/main/java/org/jboss/weld/tck/BeansImpl.java @@ -31,7 +31,7 @@ public class BeansImpl implements Beans public boolean isProxy(Object instance) { - return instance.getClass().getName().indexOf("_$$_javassist_") > 0; + return instance.getClass().getName().indexOf("_$$_Weld") > 0; } } diff --git a/tests/src/main/java/org/jboss/weld/test/Utils.java b/tests/src/main/java/org/jboss/weld/test/Utils.java index 18032508d6a..5f7c43d2796 100644 --- a/tests/src/main/java/org/jboss/weld/test/Utils.java +++ b/tests/src/main/java/org/jboss/weld/test/Utils.java @@ -35,6 +35,7 @@ import javax.enterprise.inject.spi.Bean; import javax.enterprise.util.TypeLiteral; +import org.jboss.weld.bean.proxy.Proxy; import org.jboss.weld.exceptions.UnsatisfiedResolutionException; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.mock.el.EL; @@ -169,4 +170,8 @@ public static T evaluateValueExpression(BeanManagerImpl beanManager, String return (T) EL.EXPRESSION_FACTORY.createValueExpression(elContext, expression, expectedType).getValue(elContext); } + public static boolean isProxy(Object proxy) + { + return proxy instanceof Proxy; + } } diff --git a/tests/src/test/java/org/jboss/weld/tests/proxy/enterprise/EnterpriseBeanProxyTest.java b/tests/src/test/java/org/jboss/weld/tests/proxy/enterprise/EnterpriseBeanProxyTest.java index 171b95b7311..57fedd48b1d 100644 --- a/tests/src/test/java/org/jboss/weld/tests/proxy/enterprise/EnterpriseBeanProxyTest.java +++ b/tests/src/test/java/org/jboss/weld/tests/proxy/enterprise/EnterpriseBeanProxyTest.java @@ -22,6 +22,7 @@ import org.jboss.testharness.impl.packaging.Packaging; import org.jboss.testharness.impl.packaging.PackagingType; import org.jboss.weld.test.AbstractWeldTest; +import org.jboss.weld.test.Utils; import org.testng.annotations.Test; @Artifact @@ -36,7 +37,7 @@ public class EnterpriseBeanProxyTest extends AbstractWeldTest public void testNoInterfaceView() throws Exception { Object mouse = getReference(MouseLocal.class); - assert mouse instanceof ProxyObject; + assert Utils.isProxy(mouse); assert mouse instanceof MouseLocal; }