You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2014/12/23 12:17:34 UTC
svn commit: r1647547 - in /openwebbeans/trunk/webbeans-impl/src:
main/java/org/apache/webbeans/inject/ main/java/org/apache/webbeans/portable/
main/java/org/apache/webbeans/proxy/
test/java/org/apache/webbeans/test/decorators/constructor/ test/java/org...
Author: rmannibucau
Date: Tue Dec 23 11:17:34 2014
New Revision: 1647547
URL: http://svn.apache.org/r1647547
Log:
allowing cnstructor injection in decorators
Added:
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/DecoratorConstructorInjectionTest.java
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/AbstractDecoratorInjectionTarget.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/SubclassProxyFactoryTest.java
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java Tue Dec 23 11:17:34 2014
@@ -53,7 +53,7 @@ import org.apache.webbeans.util.WebBeans
public abstract class AbstractInjectable<T>
{
- private Producer<?> owner;
+ protected Producer<?> owner;
protected final CreationalContextImpl<?> creationalContext;
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/AbstractDecoratorInjectionTarget.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/AbstractDecoratorInjectionTarget.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/AbstractDecoratorInjectionTarget.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/AbstractDecoratorInjectionTarget.java Tue Dec 23 11:17:34 2014
@@ -19,6 +19,8 @@
package org.apache.webbeans.portable;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -26,8 +28,11 @@ import javax.enterprise.inject.spi.Annot
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.context.creational.CreationalContextImpl;
+import org.apache.webbeans.inject.InjectableConstructor;
public class AbstractDecoratorInjectionTarget<T> extends InjectionTargetImpl<T>
{
@@ -50,11 +55,76 @@ public class AbstractDecoratorInjectionT
classLoader = Thread.currentThread().getContextClassLoader();
}
- proxySubClass = webBeansContext.getSubclassProxyFactory().createImplementedSubclass(classLoader, classToProxy);
+ proxySubClass = webBeansContext.getSubclassProxyFactory().createImplementedSubclass(classLoader, annotatedType);
- //X TODO what about @Inject constructors?
- Constructor<T> ct = webBeansContext.getWebBeansUtil().getNoArgConstructor(proxySubClass);
- return new AnnotatedConstructorImpl<T>(webBeansContext, ct, annotatedType);
+ Constructor<T> ct = (Constructor<T>) webBeansContext.getSecurityService().doPrivilegedGetDeclaredConstructors(proxySubClass)[0];
+ Constructor<T> parentCtor;
+ try
+ {
+ parentCtor = classToProxy.getConstructor(ct.getParameterTypes());
+ }
+ catch (final NoSuchMethodException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ return new SubClassAnnotatedConstructorImpl<T>(webBeansContext, parentCtor, ct, annotatedType);
+ }
+
+ @Override
+ protected SubClassAnnotatedConstructorImpl<T> getConstructor()
+ {
+ if (constructor == null)
+ {
+ constructor = createConstructor();
+ }
+ return (SubClassAnnotatedConstructorImpl<T>) constructor;
+ }
+
+ @Override
+ protected T newInstance(CreationalContextImpl<T> creationalContext)
+ {
+ return new AbstractDecoratorInjectableConstructor<T>(
+ getConstructor().parentConstructor, getConstructor().getJavaMember(), this, creationalContext).doInjection();
}
+ public static class SubClassAnnotatedConstructorImpl<T> extends AnnotatedConstructorImpl<T>
+ {
+ private final Constructor<T> parentConstructor;
+
+ public SubClassAnnotatedConstructorImpl(final WebBeansContext webBeansContext,
+ final Constructor<T> parentConstructor,
+ final Constructor<T> javaMember,
+ final AnnotatedType<T> declaringType)
+ {
+ super(webBeansContext, javaMember, declaringType);
+ this.parentConstructor = parentConstructor;
+ }
+ }
+
+ public static class AbstractDecoratorInjectableConstructor<T> extends InjectableConstructor<T>
+ {
+ private final Constructor<T> parent;
+
+ public AbstractDecoratorInjectableConstructor(final Constructor<T> parentConstructor,
+ final Constructor<T> cons, final InjectionTarget<T> owner,
+ final CreationalContextImpl<T> creationalContext)
+ {
+ super(cons, owner, creationalContext);
+ this.parent = parentConstructor;
+ }
+
+ @Override
+ protected List<InjectionPoint> getInjectionPoints(Member member)
+ {
+ List<InjectionPoint> injectionPoints = new ArrayList<InjectionPoint>();
+ for (InjectionPoint injectionPoint : owner.getInjectionPoints())
+ {
+ if (injectionPoint.getMember().equals(parent)) // we don't compare to the runtime subclass constructor
+ {
+ injectionPoints.add(injectionPoint);
+ }
+ }
+ return injectionPoints;
+ }
+ }
}
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java Tue Dec 23 11:17:34 2014
@@ -18,6 +18,7 @@
*/
package org.apache.webbeans.proxy;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -105,7 +106,7 @@ public abstract class AbstractProxyFacto
* @param classFileName
* @throws ProxyGenerationException
*/
- protected abstract void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName)
+ protected abstract void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> injectConstructor)
throws ProxyGenerationException;
/**
@@ -174,6 +175,12 @@ public abstract class AbstractProxyFacto
return fixedClassName;
}
+ protected <T> Class<T> createProxyClass(ClassLoader classLoader, String proxyClassName, Class<T> classToProxy,
+ Method[] interceptedMethods, Method[] nonInterceptedMethods)
+ throws ProxyGenerationException
+ {
+ return createProxyClass(classLoader, proxyClassName, classToProxy, interceptedMethods, nonInterceptedMethods, null);
+ }
/**
* @param classLoader to use for creating the class in
@@ -184,21 +191,21 @@ public abstract class AbstractProxyFacto
* @return the proxy class
*/
protected <T> Class<T> createProxyClass(ClassLoader classLoader, String proxyClassName, Class<T> classToProxy,
- Method[] interceptedMethods, Method[] nonInterceptedMethods)
+ Method[] interceptedMethods, Method[] nonInterceptedMethods,
+ Constructor<T> constructor)
throws ProxyGenerationException
{
String proxyClassFileName = proxyClassName.replace('.', '/');
- final byte[] proxyBytes = generateProxy(classLoader, classToProxy, proxyClassName, proxyClassFileName, interceptedMethods, nonInterceptedMethods);
-
- Class<T> clazz = defineAndLoadClass(classLoader, proxyClassName, proxyBytes);
-
+ final byte[] proxyBytes = generateProxy(
+ classLoader, classToProxy, proxyClassName, proxyClassFileName,
+ interceptedMethods, nonInterceptedMethods, constructor);
- return clazz;
+ return defineAndLoadClass(classLoader, proxyClassName, proxyBytes);
}
private byte[] generateProxy(ClassLoader classLoader, Class<?> classToProxy, String proxyClassName, String proxyClassFileName,
- Method[] interceptedMethods, Method[] nonInterceptedMethods)
+ Method[] interceptedMethods, Method[] nonInterceptedMethods, Constructor<?> constructor)
throws ProxyGenerationException
{
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
@@ -225,7 +232,7 @@ public abstract class AbstractProxyFacto
cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
FIELD_BEAN_PASSIVATION_ID, Type.getDescriptor(String.class), null, null).visitEnd();
- createConstructor(cw, proxyClassFileName, classToProxy, classFileName);
+ createConstructor(cw, proxyClassFileName, classToProxy, classFileName, constructor);
if (nonInterceptedMethods != null)
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java Tue Dec 23 11:17:34 2014
@@ -259,7 +259,7 @@ public class InterceptorDecoratorProxyFa
* @throws ProxyGenerationException
*/
@Override
- protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName)
+ protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> ignored)
throws ProxyGenerationException
{
Constructor superDefaultCt;
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java Tue Dec 23 11:17:34 2014
@@ -304,7 +304,8 @@ public class NormalScopeProxyFactory ext
@Override
- protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName) throws ProxyGenerationException
+ protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> ignored)
+ throws ProxyGenerationException
{
try
{
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java Tue Dec 23 11:17:34 2014
@@ -31,6 +31,10 @@ import org.apache.xbean.asm5.MethodVisit
import org.apache.xbean.asm5.Opcodes;
import org.apache.xbean.asm5.Type;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.inject.Inject;
+
/**
* This factory creates subclasses for abstract classes.
* This is being used for Abstract Decorators.
@@ -50,8 +54,9 @@ public class SubclassProxyFactory extend
}
- public <T> Class<T> createImplementedSubclass(ClassLoader classLoader, Class<T> classToProxy)
+ public <T> Class<T> createImplementedSubclass(ClassLoader classLoader, AnnotatedType<T> annotatedType)
{
+ Class<T> classToProxy = annotatedType.getJavaClass();
if (!Modifier.isAbstract(classToProxy.getModifiers()))
{
throw new WebBeansConfigurationException("Only abstract classes should get subclassed, not " + classToProxy);
@@ -64,7 +69,7 @@ public class SubclassProxyFactory extend
return proxyClass;
}
- proxyClass = createSubClass(classLoader, classToProxy);
+ proxyClass = createSubClass(classLoader, annotatedType);
return proxyClass;
}
@@ -91,13 +96,14 @@ public class SubclassProxyFactory extend
/**
* @param classLoader to use for creating the class in
- * @param classToProxy the class for which a subclass will get generated
+ * @param annotatedType the annotatedType for which a subclass will get generated
* @param <T>
* @return the proxy class
*/
- public synchronized <T> Class<T> createSubClass(ClassLoader classLoader, Class<T> classToProxy)
+ public synchronized <T> Class<T> createSubClass(ClassLoader classLoader, AnnotatedType<T> annotatedType)
throws ProxyGenerationException
{
+ Class<T> classToProxy = annotatedType.getJavaClass();
Class<T> clazz = tryToLoadClass(classLoader, classToProxy);
if (clazz != null)
{
@@ -109,19 +115,31 @@ public class SubclassProxyFactory extend
List<Method> methods = ClassUtil.getNonPrivateMethods(classToProxy, true);
Method[] businessMethods = methods.toArray(new Method[methods.size()]);
- clazz = createProxyClass(classLoader, proxyClassName, classToProxy, businessMethods, new Method[0]);
+ Constructor<T> cons = null;
+ for (AnnotatedConstructor<T> c : annotatedType.getConstructors())
+ {
+ if (c.isAnnotationPresent(Inject.class))
+ {
+ cons = c.getJavaMember();
+ break;
+ }
+ }
+
+ clazz = createProxyClass(classLoader, proxyClassName, classToProxy, businessMethods, new Method[0], cons);
return clazz;
}
@Override
- protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName) throws ProxyGenerationException
+ protected void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> constructor)
+ throws ProxyGenerationException
{
try
{
Constructor superDefaultCt;
String parentClassFileName;
+ String[] exceptions = null;
if (classToProxy.isInterface())
{
parentClassFileName = Type.getInternalName(Object.class);
@@ -130,13 +148,34 @@ public class SubclassProxyFactory extend
else
{
parentClassFileName = classFileName;
- superDefaultCt = classToProxy.getConstructor(null);
+ if (constructor == null)
+ {
+ superDefaultCt = classToProxy.getConstructor(null);
+ }
+ else
+ {
+ superDefaultCt = constructor;
+
+ Class<?>[] exceptionTypes = constructor.getExceptionTypes();
+ exceptions = exceptionTypes.length == 0 ? null : new String[exceptionTypes.length];
+ for (int i = 0; i < exceptionTypes.length; i++)
+ {
+ exceptions[i] = Type.getDescriptor(exceptionTypes[i]);
+ }
+ }
}
final String descriptor = Type.getConstructorDescriptor(superDefaultCt);
- final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
+ final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, exceptions);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
+ if (constructor != null)
+ {
+ for (int i = 1; i <= constructor.getParameterTypes().length; i++)
+ {
+ mv.visitVarInsn(Opcodes.ALOAD, i);
+ }
+ }
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, parentClassFileName, "<init>", descriptor, false);
mv.visitInsn(Opcodes.RETURN);
Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/DecoratorConstructorInjectionTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/DecoratorConstructorInjectionTest.java?rev=1647547&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/DecoratorConstructorInjectionTest.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/decorators/constructor/DecoratorConstructorInjectionTest.java Tue Dec 23 11:17:34 2014
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.webbeans.test.decorators.constructor;
+
+import junit.framework.Assert;
+import org.apache.webbeans.test.AbstractUnitTest;
+import org.junit.Test;
+
+import javax.annotation.Priority;
+import javax.decorator.Decorator;
+import javax.decorator.Delegate;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+
+public class DecoratorConstructorInjectionTest extends AbstractUnitTest
+{
+ @Test
+ public void run()
+ {
+ startContainer(Foo.class, Dec.class, FooImpl.class, ABeanJustToEnsureInjectionsWork.class);
+ Assert.assertTrue(getInstance(Foo.class).dec());
+ }
+
+ public static interface Foo
+ {
+ boolean dec();
+ boolean normal();
+ }
+
+ public static class FooImpl implements Foo
+ {
+ public boolean dec()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean normal()
+ {
+ return true;
+ }
+ }
+
+ @Decorator
+ @Priority(1)
+ public static abstract class Dec implements Foo
+ {
+ private final Foo del;
+ private final Integer number;
+ private final ABeanJustToEnsureInjectionsWork injection;
+
+ @Inject
+ public Dec(@Delegate @Any Foo delegate, ABeanJustToEnsureInjectionsWork injection, Integer integer) throws IllegalArgumentException
+ {
+ this.del = delegate;
+ this.number = integer;
+ this.injection = injection;
+ }
+
+ @Override
+ public boolean dec()
+ {
+ return del != null && !Foo.class.cast(del).dec() && Foo.class.cast(del).normal()
+ && number == 1 && injection != null;
+ }
+ }
+
+ public static class ABeanJustToEnsureInjectionsWork
+ {
+ @Produces
+ public Integer aWrapper = 1;
+ }
+}
Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/SubclassProxyFactoryTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/SubclassProxyFactoryTest.java?rev=1647547&r1=1647546&r2=1647547&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/SubclassProxyFactoryTest.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/SubclassProxyFactoryTest.java Tue Dec 23 11:17:34 2014
@@ -35,7 +35,8 @@ public class SubclassProxyFactoryTest ex
startContainer();
Class<? extends MyAbstractTestDecorator> subClass
- = getWebBeansContext().getSubclassProxyFactory().createSubClass(this.getClass().getClassLoader(), MyAbstractTestDecorator.class);
+ = getWebBeansContext().getSubclassProxyFactory().createSubClass(
+ this.getClass().getClassLoader(), getBeanManager().createAnnotatedType(MyAbstractTestDecorator.class));
Assert.assertNotNull(subClass);
MyAbstractTestDecorator instance = subClass.newInstance();