KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > annotation > instrumentation > asm > AsmAnnotationHelper


1 /**************************************************************************************
2  * Copyright (c) Jonas Bon?r, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.annotation.instrumentation.asm;
9
10 import org.objectweb.asm.ClassVisitor;
11 import org.objectweb.asm.Attribute;
12 import org.objectweb.asm.CodeVisitor;
13 import org.objectweb.asm.Label;
14 import org.objectweb.asm.Type;
15 import org.objectweb.asm.attrs.RuntimeInvisibleAnnotations;
16 import org.objectweb.asm.attrs.Annotation;
17 import org.objectweb.asm.attrs.RuntimeVisibleAnnotations;
18 import org.objectweb.asm.attrs.AnnotationDefaultAttribute;
19 import org.objectweb.asm.attrs.Attributes;
20 import org.codehaus.aspectwerkz.annotation.AnnotationInfo;
21 import org.codehaus.aspectwerkz.annotation.AnnotationDefault;
22 import org.codehaus.aspectwerkz.annotation.Java5AnnotationInvocationHandler;
23
24 import java.util.List JavaDoc;
25 import java.util.Iterator JavaDoc;
26
27 /**
28  * Helper visitor to extract Annotations.
29  * The visitors are not writing any bytecode and using a Null ClassVisitor / Code Visitor as a target instead.
30  *
31  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur</a>
32  */

33 public class AsmAnnotationHelper {
34
35     private final static String JavaDoc INIT_METHOD_NAME = "<init>";
36
37     /**
38      * Generic extractor
39      */

40     private static class AnnotationExtractor extends NullClassAdapter {
41
42         /**
43          * The list where encountered annotation will be put
44          */

45         protected List JavaDoc m_annotations;
46
47         /**
48          * This classloader will be used to instantiate the proxy instance for Custom Annotation support (1.3/1.4).
49          * See CustomAttribute that wraps in a RuntimeInvisibleAnnotation the user custom annotations.
50          * <br/>Note: no weak reference is used since the visitor is created for a one shot usage.
51          */

52         protected ClassLoader JavaDoc m_loader;
53
54         /**
55          * Generic extractor
56          *
57          * @param annotations list where to put annotations
58          * @param loader classLoader used to instantiate proxy of custom annotations
59          */

60         private AnnotationExtractor(List JavaDoc annotations, final ClassLoader JavaDoc loader) {
61             m_annotations = annotations;
62             m_loader = loader;
63         }
64     }
65
66     /**
67      * Extracts class level annotations
68      */

69     public static class ClassAnnotationExtractor extends AnnotationExtractor {
70
71         public ClassAnnotationExtractor(List JavaDoc annotations, final ClassLoader JavaDoc loader) {
72             super(annotations, loader);
73         }
74
75         public void visitAttribute(final Attribute attribute) {
76             m_annotations = extractAnnotations(m_annotations, attribute, m_loader);
77             super.visitAttribute(attribute);
78         }
79     }
80
81     /**
82      * Generic extractor for member (ctor, method, field) annotations extraction
83      */

84     private static class MemberAnnotationExtractor extends AnnotationExtractor {
85
86         /**
87          * Member name (method name, "<init>", field name
88          */

89         protected String JavaDoc m_name;
90
91         /**
92          * Member descriptor (as in visitMethod/visitField ASM methods)
93          */

94         protected String JavaDoc m_desc;
95
96         /**
97          * Method annotation extractor
98          *
99          * @param annotations
100          * @param name of the member for which we want the annotations
101          * @param desc of the member for which we want the annotations
102          * @param loader
103          */

104         private MemberAnnotationExtractor(List JavaDoc annotations, String JavaDoc name, String JavaDoc desc, final ClassLoader JavaDoc loader) {
105             super(annotations, loader);
106             m_name = name;
107             m_desc = desc;
108         }
109     }
110
111     /**
112      * Method annotations extractor
113      */

114     public static class MethodAnnotationExtractor extends MemberAnnotationExtractor {
115
116         public MethodAnnotationExtractor(List JavaDoc annotations, String JavaDoc name, String JavaDoc desc, final ClassLoader JavaDoc loader) {
117             super(annotations, name, desc, loader);
118         }
119
120         public CodeVisitor visitMethod(final int access,
121                                        final String JavaDoc name,
122                                        final String JavaDoc desc,
123                                        final String JavaDoc[] exceptions,
124                                        final Attribute attrs) {
125             if (name.equals(m_name) && desc.equals(m_desc)) {
126                 m_annotations = extractAnnotations(m_annotations, attrs, m_loader);
127             }
128             return super.visitMethod(access, name, desc, exceptions, attrs);
129         }
130     }
131
132     /**
133      * Constructor annotations extractor
134      */

135     public static class ConstructorAnnotationExtractor extends MethodAnnotationExtractor {
136
137         public ConstructorAnnotationExtractor(List JavaDoc annotations, String JavaDoc desc, final ClassLoader JavaDoc loader) {
138             super(annotations, INIT_METHOD_NAME, desc, loader);
139         }
140     }
141
142     /**
143      * Field annotations extractor
144      */

145     public static class FieldAnnotationExtractor extends MemberAnnotationExtractor {
146
147         public FieldAnnotationExtractor(List JavaDoc annotations, String JavaDoc name, final ClassLoader JavaDoc loader) {
148             super(annotations, name, null, loader);
149         }
150
151         public void visitField(final int access,
152                                final String JavaDoc name,
153                                final String JavaDoc desc,
154                                final Object JavaDoc value,
155                                final Attribute attrs) {
156             // no match on desc
157
if (name.equals(m_name)) {
158                 m_annotations = extractAnnotations(m_annotations, attrs, m_loader);
159             }
160             super.visitField(access, name, desc, value, attrs);
161         }
162     }
163
164     /**
165      * A NullClassAdapter that does nothing.
166      * Can be used to speed up ASM and avoid unecessary bytecode writing thru a regular ClassWriter when this is not
167      * needed (read only purpose).
168      */

169     public static class NullClassAdapter implements ClassVisitor {
170
171         public final static ClassVisitor NULL_CLASS_ADAPTER = new NullClassAdapter();
172
173         public void visit(int i, int i1, String JavaDoc s, String JavaDoc s1, String JavaDoc[] strings, String JavaDoc s2) {
174         }
175
176         public void visitInnerClass(String JavaDoc s, String JavaDoc s1, String JavaDoc s2, int i) {
177         }
178
179         public void visitField(int i, String JavaDoc s, String JavaDoc s1, Object JavaDoc o, Attribute attribute) {
180         }
181
182         public CodeVisitor visitMethod(int i, String JavaDoc s, String JavaDoc s1, String JavaDoc[] strings, Attribute attribute) {
183             return NullCodeAdapter.NULL_CODE_ADAPTER;
184         }
185
186         public void visitAttribute(Attribute attribute) {
187         }
188
189         public void visitEnd() {
190         }
191     }
192
193     /**
194      * A NullCodeAdapter that does nothing.
195      * Can be used to speed up ASM and avoid unecessary bytecode writing thru a regular CodeWriter when this is not
196      * needed (read only purpose)
197      */

198     public static class NullCodeAdapter implements CodeVisitor {
199
200         public final static CodeVisitor NULL_CODE_ADAPTER = new NullCodeAdapter();
201
202         public void visitInsn(int opcode) {
203         }
204
205         public void visitIntInsn(int opcode, int operand) {
206         }
207
208         public void visitVarInsn(int opcode, int var) {
209         }
210
211         public void visitTypeInsn(int opcode, String JavaDoc desc) {
212         }
213
214         public void visitFieldInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
215         }
216
217         public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
218         }
219
220         public void visitJumpInsn(int opcode, Label label) {
221         }
222
223         public void visitLabel(Label label) {
224         }
225
226         public void visitLdcInsn(Object JavaDoc cst) {
227         }
228
229         public void visitIincInsn(int var, int increment) {
230         }
231
232         public void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]) {
233         }
234
235         public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) {
236         }
237
238         public void visitMultiANewArrayInsn(String JavaDoc desc, int dims) {
239         }
240
241         public void visitTryCatchBlock(Label start, Label end, Label handler, String JavaDoc type) {
242         }
243
244         public void visitMaxs(int maxStack, int maxLocals) {
245         }
246
247         public void visitLocalVariable(String JavaDoc name, String JavaDoc desc, Label start, Label end, int index) {
248         }
249
250         public void visitLineNumber(int line, Label start) {
251         }
252
253         public void visitAttribute(Attribute attr) {
254         }
255     }
256
257     /**
258      * Helper method to extract Runtime(In)VisibleAnnotations and unwrap custom annotation proxies
259      *
260      * @param annotations
261      * @param attribute
262      * @param loader
263      * @return annotations list populated
264      */

265     public static List JavaDoc extractAnnotations(List JavaDoc annotations, final Attribute attribute, final ClassLoader JavaDoc loader) {
266         for (Attribute current = attribute; current != null; current = current.next) {
267             if (current instanceof RuntimeInvisibleAnnotations) {
268                 for (Iterator JavaDoc it = ((RuntimeInvisibleAnnotations) current).annotations.iterator(); it.hasNext();) {
269                     Annotation annotation = (Annotation) it.next();
270                     if (CustomAttribute.TYPE.equals(annotation.type)) {
271                         annotations.add(CustomAttributeHelper.extractCustomAnnotation(annotation));
272                     } else {
273                         AnnotationInfo annotationInfo = getAnnotationInfo(annotation, loader);
274                         annotations.add(annotationInfo);
275                     }
276                 }
277             } else if (current instanceof RuntimeVisibleAnnotations) {
278                 for (Iterator JavaDoc it = ((RuntimeVisibleAnnotations) current).annotations.iterator(); it.hasNext();) {
279                     Annotation annotation = (Annotation) it.next();
280                     AnnotationInfo annotationInfo = getAnnotationInfo(annotation, loader);
281                     annotations.add(annotationInfo);
282                 }
283             } else if (current instanceof AnnotationDefaultAttribute) {
284                 AnnotationDefaultAttribute defaultAttribute = (AnnotationDefaultAttribute) current;
285                 AnnotationInfo annotationInfo = new AnnotationInfo(
286                         AnnotationDefault.NAME,
287                         new AnnotationDefault.AnnotationDefaultImpl(defaultAttribute.defaultValue)
288                 );
289                 annotations.add(annotationInfo);
290             }
291         }
292         return annotations;
293     }
294
295     /**
296      * Creates and returns a new annotation info build up from the Java5 annotation.
297      *
298      * @param annotation the ASM annotation abstraction
299      * @param loader the class loader that has loaded the proxy class to use
300      * @return the annotation info
301      */

302     public static AnnotationInfo getAnnotationInfo(final Annotation annotation, final ClassLoader JavaDoc loader) {
303         String JavaDoc annotationName = Type.getType(annotation.type).getClassName();
304         return new AnnotationInfo(annotationName,
305                                   Java5AnnotationInvocationHandler.getAnnotationProxy(annotation, loader)
306         );
307     }
308 }
309
Popular Tags