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 <[email protected]> Authored: Fri Jan 8 00:12:23 2016 +0100 Committer: Thomas Andraschko <[email protected]> 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; + } +}
