You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ta...@apache.org on 2016/01/08 00:12:31 UTC

deltaspike git commit: DELTASPIKE-1061 custom annotation member values

Repository: deltaspike
Updated Branches:
  refs/heads/master 6ba0b458c -> 530dc72c8


DELTASPIKE-1061 custom annotation member values

Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/530dc72c
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/530dc72c
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/530dc72c

Branch: refs/heads/master
Commit: 530dc72c869af207dec8da1cbc7b793f8d01d85a
Parents: 6ba0b45
Author: Thomas Andraschko <ta...@apache.org>
Authored: Fri Jan 8 00:12:23 2016 +0100
Committer: Thomas Andraschko <ta...@apache.org>
Committed: Fri Jan 8 00:12:23 2016 +0100

----------------------------------------------------------------------
 .../proxy/impl/AsmProxyClassGenerator.java      | 54 ++++++++---
 .../impl/CopyAnnotationVisitorAdapter.java      | 96 ++++++++++++++++++++
 .../proxy/impl/AsmProxyClassGeneratorTest.java  | 65 +++++++++++++
 .../deltaspike/proxy/impl/TestAnnotation.java   | 34 +++++++
 .../apache/deltaspike/proxy/impl/TestClass.java | 28 ++++++
 .../proxy/impl/TestInvocationHandler.java       | 31 +++++++
 6 files changed, 295 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGenerator.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGenerator.java
index c795a0c..1ee1a63 100644
--- a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGenerator.java
+++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGenerator.java
@@ -32,6 +32,9 @@ import java.util.Arrays;
 import javax.enterprise.inject.Typed;
 
 import org.apache.deltaspike.proxy.spi.ProxyClassGenerator;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.Opcodes;
@@ -103,35 +106,60 @@ public class AsmProxyClassGenerator implements ProxyClassGenerator
         Type proxyType = Type.getObjectType(proxyName);
         Type delegateInvocationHandlerType = Type.getType(delegateInvocationHandlerClass);
 
-        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
         cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyType.getInternalName(), null,
                 superType.getInternalName(), interfaces);
 
-        // copy annotations
-        for (Annotation annotation : targetClass.getDeclaredAnnotations())
-        {
-            cw.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd();
-        }
-
         defineInvocationHandlerField(cw, delegateInvocationHandlerType);
         defineDefaultConstructor(cw, proxyType, superType);
         defineDelegateInvocationHandlerConstructor(cw, proxyType, superType, delegateInvocationHandlerType);
         defineDeltaSpikeProxyMethods(cw, proxyType, delegateInvocationHandlerType);
 
-        for (java.lang.reflect.Method method : delegateMethods)
+        if (delegateMethods != null)
         {
-            defineMethod(cw, method, DelegateManualInvocationHandler.class);
+            for (java.lang.reflect.Method method : delegateMethods)
+            {
+                defineMethod(cw, method, DelegateManualInvocationHandler.class);
+            }
         }
 
-        for (java.lang.reflect.Method method : interceptMethods)
+        if (interceptMethods != null)
         {
-            defineSuperAccessorMethod(cw, method, superType, superAccessorMethodSuffix);
-            defineMethod(cw, method, InterceptManualInvocationHandler.class);
+            for (java.lang.reflect.Method method : interceptMethods)
+            {
+                defineSuperAccessorMethod(cw, method, superType, superAccessorMethodSuffix);
+                defineMethod(cw, method, InterceptManualInvocationHandler.class);
+            }
+        }
+
+        // copy all annotations from the source class
+        try
+        {
+            // ClassVisitor to intercept all annotation visits on the class
+            ClassVisitor cv = new ClassVisitor(Opcodes.ASM5)
+            {
+                @Override
+                public AnnotationVisitor visitAnnotation(String desc, boolean visible)
+                {
+                    return new CopyAnnotationVisitorAdapter(
+                            super.visitAnnotation(desc, visible),
+                            cw.visitAnnotation(desc, visible));
+                }
+            };
+
+            // visit class to proxy with our visitor to copy all annotations from the source class to our ClassWriter
+            String sourceClassFilename = targetClass.getName().replace('.', '/') + ".class";
+            ClassReader cr = new ClassReader(targetClass.getClassLoader().getResourceAsStream(sourceClassFilename));
+            cr.accept(cv, 0);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
         }
 
         return cw.toByteArray();
     }
-
+    
     private static void defineInvocationHandlerField(ClassWriter cw, Type delegateInvocationHandlerType)
     {
         // generates

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/CopyAnnotationVisitorAdapter.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/CopyAnnotationVisitorAdapter.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/CopyAnnotationVisitorAdapter.java
new file mode 100644
index 0000000..17dbedf
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/CopyAnnotationVisitorAdapter.java
@@ -0,0 +1,96 @@
+/*
+ * 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.deltaspike.proxy.impl;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class CopyAnnotationVisitorAdapter extends AnnotationVisitor
+{
+    private final AnnotationVisitor from;
+    private final AnnotationVisitor to;
+
+    public CopyAnnotationVisitorAdapter(AnnotationVisitor from, AnnotationVisitor copyTo)
+    {
+        super(Opcodes.ASM5);
+
+        this.from = from;
+        this.to = copyTo;
+    }
+
+    @Override
+    public void visit(String name, Object value)
+    {
+        if (from != null)
+        {
+            from.visit(name, value);
+        }
+        to.visit(name, value);
+    }
+
+    @Override
+    public void visitEnum(String name, String desc, String value)
+    {
+        if (from != null)
+        {
+            from.visitEnum(name, desc, value);
+        }
+        to.visitEnum(name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String name, String desc)
+    {
+        if (from == null)
+        {
+            return new CopyAnnotationVisitorAdapter(
+                    null,
+                    to.visitAnnotation(name, desc));
+        }
+
+        return new CopyAnnotationVisitorAdapter(
+                from.visitAnnotation(name, desc),
+                to.visitAnnotation(name, desc));
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(String name)
+    {
+        if (from == null)
+        {
+            return new CopyAnnotationVisitorAdapter(
+                    null,
+                    to.visitArray(name));
+        }
+
+        return new CopyAnnotationVisitorAdapter(
+                from.visitArray(name),
+                to.visitArray(name));
+    }
+
+    @Override
+    public void visitEnd()
+    {
+        if (from != null)
+        {
+            from.visitEnd();
+        }
+        to.visitEnd();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGeneratorTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGeneratorTest.java b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGeneratorTest.java
new file mode 100644
index 0000000..01f72e2
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/AsmProxyClassGeneratorTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.deltaspike.proxy.impl;
+
+import javax.inject.Named;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class AsmProxyClassGeneratorTest
+{
+    private static Class<? extends TestClass> proxyClass;
+    
+    @BeforeClass
+    public static void init()
+    {
+        AsmProxyClassGenerator asmProxyClassGenerator = new AsmProxyClassGenerator();
+        proxyClass = asmProxyClassGenerator.generateProxyClass(TestClass.class.getClassLoader(),
+                TestClass.class,
+                TestInvocationHandler.class,
+                "$Test",
+                "$super",
+                null,
+                null,
+                null); 
+    }
+    
+    @Test
+    public void testCopyAnnotationValues()
+    {
+        Assert.assertEquals(
+                TestClass.class.getAnnotations().length,
+                proxyClass.getAnnotations().length);
+        
+        Assert.assertEquals(
+                TestClass.class.getAnnotation(Named.class).value(),
+                proxyClass.getAnnotation(Named.class).value());
+        
+        Assert.assertEquals(
+                TestClass.class.getAnnotation(TestAnnotation.class).value1(),
+                proxyClass.getAnnotation(TestAnnotation.class).value1());
+        Assert.assertEquals(
+                TestClass.class.getAnnotation(TestAnnotation.class).value2(),
+                proxyClass.getAnnotation(TestAnnotation.class).value2());
+        Assert.assertEquals(
+                TestClass.class.getAnnotation(TestAnnotation.class).value3(),
+                proxyClass.getAnnotation(TestAnnotation.class).value3());
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestAnnotation.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestAnnotation.java b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestAnnotation.java
new file mode 100644
index 0000000..0056ab9
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestAnnotation.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deltaspike.proxy.impl;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Documented
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface TestAnnotation
+{
+    int value1() default 13;
+    
+    Class value2() default TestAnnotation.class;
+    
+    String value3() default "tester";
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestClass.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestClass.java b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestClass.java
new file mode 100644
index 0000000..0df8b06
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestClass.java
@@ -0,0 +1,28 @@
+/*
+ * 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.deltaspike.proxy.impl;
+
+import javax.inject.Named;
+
+@Named("test")
+@TestAnnotation(value2 = TestClass.class, value1 = 15)
+public class TestClass
+{
+    
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/530dc72c/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestInvocationHandler.java b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestInvocationHandler.java
new file mode 100644
index 0000000..e466839
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/test/java/org/apache/deltaspike/proxy/impl/TestInvocationHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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.deltaspike.proxy.impl;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class TestInvocationHandler implements InvocationHandler
+{
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        return null;
+    }
+}