Author: mstruk
Date: 2011-04-24 17:29:13 -0400 (Sun, 24 Apr 2011)
New Revision: 6342
Added:
sandbox/cdi_support/cdi/trunk/api/src/main/java/org/gatein/cdi/api/proxyproducer/
sandbox/cdi_support/cdi/trunk/api/src/main/java/org/gatein/cdi/api/proxyproducer/ProxyProducer.java
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/InjectionPointImpl.java
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerBean.java
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerExtension.java
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerInvocationHandler.java
Log:
Added missing code
Added:
sandbox/cdi_support/cdi/trunk/api/src/main/java/org/gatein/cdi/api/proxyproducer/ProxyProducer.java
===================================================================
---
sandbox/cdi_support/cdi/trunk/api/src/main/java/org/gatein/cdi/api/proxyproducer/ProxyProducer.java
(rev 0)
+++
sandbox/cdi_support/cdi/trunk/api/src/main/java/org/gatein/cdi/api/proxyproducer/ProxyProducer.java 2011-04-24
21:29:13 UTC (rev 6342)
@@ -0,0 +1,13 @@
+package org.gatein.cdi.api.proxyproducer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.METHOD)
+public @interface ProxyProducer
+{
+
+}
Added:
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/InjectionPointImpl.java
===================================================================
---
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/InjectionPointImpl.java
(rev 0)
+++
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/InjectionPointImpl.java 2011-04-24
21:29:13 UTC (rev 6342)
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.gatein.cdi.impl.proxyproducer;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.AnnotationLiteral;
+
+/**
+ * A simple implementation of InjectionPoint
+ *
+ * @author stuart
+ *
+ */
+public class InjectionPointImpl implements InjectionPoint
+{
+
+ public InjectionPointImpl(AnnotatedField<?> field, Set<Annotation>
qualifiers, Bean<?> bean, boolean trans, boolean delegate)
+ {
+ this.annotated = field;
+ this.member = field.getJavaMember();
+ this.qualifiers = new HashSet<Annotation>(qualifiers);
+ this.type = field.getJavaMember().getGenericType();
+ this.trans = trans;
+ this.delegate = delegate;
+ this.bean = bean;
+ }
+
+ public InjectionPointImpl(AnnotatedField<?> field, BeanManager beanManager,
Bean<?> bean, boolean trans, boolean delegate)
+ {
+ this.annotated = field;
+ this.member = field.getJavaMember();
+ this.qualifiers = new HashSet<Annotation>();
+ this.type = field.getJavaMember().getGenericType();
+ this.trans = trans;
+ this.delegate = delegate;
+ this.bean = bean;
+ for (Annotation a : field.getAnnotations())
+ {
+ if (beanManager.isQualifier(a.annotationType()))
+ {
+ qualifiers.add(a);
+ }
+ }
+ }
+
+ public InjectionPointImpl(AnnotatedParameter<?> param, Set<Annotation>
qualifiers, Bean<?> bean, boolean trans, boolean delegate)
+ {
+ this.annotated = param;
+ this.member = param.getDeclaringCallable().getJavaMember();
+ this.qualifiers = new HashSet<Annotation>(qualifiers);
+ this.trans = trans;
+ this.delegate = delegate;
+ this.bean = bean;
+ this.type = param.getBaseType();
+ }
+
+ public InjectionPointImpl(AnnotatedParameter<?> param, BeanManager beanManager,
Bean<?> bean, boolean trans, boolean delegate)
+ {
+ this.annotated = param;
+ this.member = param.getDeclaringCallable().getJavaMember();
+ this.qualifiers = new HashSet<Annotation>();
+ this.trans = trans;
+ this.delegate = delegate;
+ this.bean = bean;
+ this.type = param.getBaseType();
+ for (Annotation a : annotated.getAnnotations())
+ {
+ if (beanManager.isQualifier(a.annotationType()))
+ {
+ qualifiers.add(a);
+ }
+ }
+ qualifiers.add(new AnnotationLiteral<Default>() {});
+ }
+
+ private final Annotated annotated;
+
+ private final Member member;
+
+ private final Bean<?> bean;
+
+ private final Set<Annotation> qualifiers;
+
+ private final Type type;
+
+ private final boolean trans;
+
+ private final boolean delegate;
+
+ public Annotated getAnnotated()
+ {
+ return annotated;
+ }
+
+ public Bean<?> getBean()
+ {
+ return bean;
+ }
+
+ public Member getMember()
+ {
+ return member;
+ }
+
+ public Set<Annotation> getQualifiers()
+ {
+ return qualifiers;
+ }
+
+ public Type getType()
+ {
+ return type;
+ }
+
+ public boolean isDelegate()
+ {
+ return delegate;
+ }
+
+ public boolean isTransient()
+ {
+ return trans;
+ }
+
+}
Added:
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerBean.java
===================================================================
---
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerBean.java
(rev 0)
+++
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerBean.java 2011-04-24
21:29:13 UTC (rev 6342)
@@ -0,0 +1,234 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.gatein.cdi.impl.proxyproducer;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javassist.util.proxy.MethodFilter;
+import javassist.util.proxy.ProxyFactory;
+import javassist.util.proxy.ProxyObject;
+import org.jboss.interceptor.util.proxy.TargetInstanceProxy;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Named;
+
+/**
+ * Bean implementation that produces a JDK proxy
+ *
+ * when a method is invoked on the proxy it calls the managed producer method
+ * and invokes the method on the returned object
+ *
+ * @author stuart
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ *
+ * @param <M>
+ */
+public class ProxyProducerBean<M> implements Bean<M>
+{
+
+ final private Class<?> beanClass;
+
+ final private String name;
+
+ final private Set<Annotation> qualifiers;
+
+ final private Set<Type> types;
+
+ final private Class<M> proxyClass;
+
+ final private BeanManager manager;
+
+ final private AnnotatedMethod<?> method;
+
+ private final static Annotation[] defaultQualifiers = { new
AnnotationLiteral<Default>()
+ {
+ } };
+
+ public ProxyProducerBean(AnnotatedMethod<?> method, BeanManager manager)
+ {
+ this.method = method;
+ beanClass = method.getDeclaringType().getJavaClass();
+ // get the name
+ if (method.isAnnotationPresent(Named.class))
+ {
+ name = method.getAnnotation(Named.class).value();
+ }
+ else
+ {
+ name = null;
+ }
+ // get the qualifiers
+ qualifiers = new HashSet<Annotation>();
+ for (Annotation a : method.getAnnotations())
+ {
+ if (manager.isQualifier(a.annotationType()))
+ {
+ qualifiers.add(a);
+ }
+ }
+ if (qualifiers.isEmpty())
+ {
+ qualifiers.add(new AnnotationLiteral<Default>()
+ {
+ });
+ }
+ // get the bean types
+ types = new HashSet<Type>();
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+ types.add(method.getBaseType());
+ types.add(Object.class);
+ /*
+ for (Type t : method.getTypeClosure())
+ {
+ if (t instanceof Class<?>)
+ {
+ Class<?> c = (Class<?>) t;
+ types.add(c);
+ classes.add(c);
+ }
+ else if (t instanceof ParameterizedType)
+ {
+ ParameterizedType p = (ParameterizedType) t;
+ Class<?> c = (Class<?>) p.getRawType();
+ types.add(t);
+ }
+ break;
+ }
+ */
+ this.manager = manager;
+
+ // build the properties
+ /*
+ Class<?>[] iarray = new Class[classes.size()];
+ int count = 0;
+ for (Class<?> c : classes)
+ {
+ iarray[count++] = c;
+ }
+ */
+ ProxyFactory f = new ProxyFactory();
+ Class<?> retType = method.getJavaMember().getReturnType();
+ if (retType.isInterface())
+ {
+ f.setSuperclass(Object.class);
+ Class<?>[] ifaces = { retType, TargetInstanceProxy.class };
+ f.setInterfaces(ifaces);
+ }
+ else
+ {
+ f.setSuperclass(retType);
+ Class<?>[] ifaces = { TargetInstanceProxy.class };
+ f.setInterfaces(ifaces);
+ }
+
+ f.setFilter(new MethodFilter()
+ {
+ public boolean isHandled(Method m)
+ {
+ // ignore finalize()
+ return !m.getName().equals("finalize");
+ }
+ });
+ proxyClass = f.createClass();
+
+ }
+
+ public Class<?> getBeanClass()
+ {
+ return beanClass;
+ }
+
+ public Set<InjectionPoint> getInjectionPoints()
+ {
+ return Collections.emptySet();
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public Set<Annotation> getQualifiers()
+ {
+ return qualifiers;
+ }
+
+ /**
+ * the proxies that are injected all have Dependant scope
+ */
+ public Class<? extends Annotation> getScope()
+ {
+ return Dependent.class;
+ }
+
+ public Set<Class<? extends Annotation>> getStereotypes()
+ {
+ return Collections.emptySet();
+ }
+
+ public Set<Type> getTypes()
+ {
+ return types;
+ }
+
+ public boolean isAlternative()
+ {
+ return false;
+ }
+
+ public boolean isNullable()
+ {
+ return false;
+ }
+
+ public M create(CreationalContext<M> creationalContext)
+ {
+ Set<Bean<?>> beans = manager.getBeans(InjectionPoint.class,
defaultQualifiers);
+ Bean<?> injectionPointBean = (Bean<?>) beans.iterator().next();
+ InjectionPoint injectionPoint = (InjectionPoint)
manager.getReference(injectionPointBean, InjectionPoint.class, creationalContext);
+ ProxyProducerInvocationHandler hdl = new ProxyProducerInvocationHandler(manager,
this.method, this, injectionPoint);
+ try
+ {
+ M obj = proxyClass.newInstance();
+ ((ProxyObject) obj).setHandler(hdl);
+ creationalContext.push(obj);
+ return obj;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void destroy(M instance, CreationalContext<M> creationalContext)
+ {
+ creationalContext.release();
+ }
+}
Added:
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerExtension.java
===================================================================
---
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerExtension.java
(rev 0)
+++
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerExtension.java 2011-04-24
21:29:13 UTC (rev 6342)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.gatein.cdi.impl.proxyproducer;
+
+import org.gatein.cdi.api.proxyproducer.ProxyProducer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+
+/**
+ * An extension that allows the use of @ManagedProducer methods
+ *
+ * these methods work in a similar manner to @Unwrap methods in seam 2
+ *
+ * @author stuart
+ *
+ */
+public class ProxyProducerExtension implements Extension
+{
+
+ final private Set<ProxyProducerBean<?>> beans = new
HashSet<ProxyProducerBean<?>>();
+
+ public void processAnnotatedType(@Observes ProcessAnnotatedType<?> type,
BeanManager manager)
+ {
+ for (AnnotatedMethod<?> m : type.getAnnotatedType().getMethods())
+ {
+ if (m.isAnnotationPresent(ProxyProducer.class))
+ {
+ // we have a managed producer
+ // lets make a note of it and register it later
+ beans.add(new ProxyProducerBean(m, manager));
+ }
+ }
+ }
+
+ public void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBean)
+ {
+ for (ProxyProducerBean<?> b : beans)
+ {
+ afterBean.addBean(b);
+ }
+ }
+
+}
Added:
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerInvocationHandler.java
===================================================================
---
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerInvocationHandler.java
(rev 0)
+++
sandbox/cdi_support/cdi/trunk/impl/src/main/java/org/gatein/cdi/impl/proxyproducer/ProxyProducerInvocationHandler.java 2011-04-24
21:29:13 UTC (rev 6342)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.gatein.cdi.impl.proxyproducer;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javassist.util.proxy.MethodHandler;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.AmbiguousResolutionException;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.jboss.interceptor.util.proxy.TargetInstanceProxy;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class ProxyProducerInvocationHandler implements MethodHandler
+{
+
+ final private BeanManager manager;
+ final private AnnotatedMethod<?> annotatedMethod;
+ final private Method method;
+ final private Bean<?> bean;
+ final private InjectionPoint[] injectionPoints;
+ final private Bean<?> mainClassBean;
+ final private InjectionPoint injectionPoint;
+
+
+ public ProxyProducerInvocationHandler(BeanManager manager, AnnotatedMethod<?>
method, Bean<?> bean, InjectionPoint injectionPoint)
+ {
+ this.manager = manager;
+ this.method = method.getJavaMember();
+ this.annotatedMethod = method;
+ this.bean = bean;
+ injectionPoints = new InjectionPoint[this.method.getParameterTypes().length];
+ for (int i = 0; i < injectionPoints.length; ++i)
+ {
+ injectionPoints[i] = new InjectionPointImpl(method.getParameters().get(i),
manager, bean, false, false);
+ }
+ Type mainType = method.getDeclaringType().getBaseType();
+ HashSet<Annotation> mainClassQualifiers = new HashSet<Annotation>();
+ for (Annotation a : method.getDeclaringType().getAnnotations())
+ {
+ if (manager.isQualifier(a.annotationType()))
+ {
+ mainClassQualifiers.add(a);
+ }
+ }
+ Set<Bean<?>> beans = manager.getBeans(mainType,
mainClassQualifiers.toArray(new Annotation[0]));
+ if (beans.isEmpty())
+ {
+ throw new UnsatisfiedResolutionException("Could not find declaring bean for
managed producer method " + method.getDeclaringType().getJavaClass() + "."
+ this.method.getName());
+ }
+ else if (beans.size() > 1)
+ {
+ throw new AmbiguousResolutionException("Could not find declaring bean for
managed producer method " + method.getDeclaringType().getJavaClass() + "."
+ this.method.getName());
+ }
+ mainClassBean = beans.iterator().next();
+ this.injectionPoint = injectionPoint;
+ }
+
+ public Object invoke(Object proxy, Method thisMethod, Method m, Object[] args) throws
Throwable
+ {
+ CreationalContext<?> ctx = manager.createCreationalContext(bean);
+ try
+ {
+ Object[] params = new Object[method.getParameterTypes().length];
+ for (int i = 0; i < this.method.getParameterTypes().length; ++i)
+ {
+ if
(InjectionPoint.class.isAssignableFrom(this.method.getParameterTypes()[i]))
+ {
+ params[i] = injectionPoint;
+ }
+ else
+ {
+ params[i] = manager.getInjectableReference(injectionPoints[i], ctx);
+ }
+ }
+ Object base = manager.getReference(mainClassBean,
annotatedMethod.getDeclaringType().getJavaClass(), ctx);
+
+ Object result = method.invoke(base, params);
+
+ Class declaringClass = thisMethod.getDeclaringClass();
+ if (declaringClass == TargetInstanceProxy.class)
+ {
+ if ("getTargetInstance".equals(thisMethod.getName()))
+ return result;
+ else if ("getTargetClass".equals(thisMethod.getName()))
+ {
+ return method.getReturnType();
+ }
+ }
+
+ if (result == null)
+ {
+ if (declaringClass == Object.class &&
"toString".equals(thisMethod.getName()))
+ {
+ return proxy.getClass() + "@ -- No delegate --";
+ }
+ else
+ {
+ throw new IllegalStateException("Proxy has no delegate (" +
method + " returned null)");
+ }
+ }
+ Object ret = thisMethod.invoke(result, args);
+ return ret;
+ }
+ finally
+ {
+ ctx.release();
+ }
+ }
+
+}