EMMA Coverage Report (generated Mon Nov 26 19:18:24 CET 2007)
[all classes][net.sourceforge.retroweaver.runtime.java.lang.annotation]

COVERAGE SUMMARY FOR SOURCE FILE [AIB.java]

nameclass, %method, %block, %line, %
AIB.java100% (11/11)62%  (67/108)85%  (944/1107)75%  (195/259)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AIB$AIBEmptyVisitor100% (1/1)14%  (5/35)18%  (8/44)14%  (5/35)
visit (int, int, String, String, String, String []): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitAnnotation (String, String): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitAnnotation (String, boolean): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitAnnotationDefault (): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitAttribute (Attribute): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitCode (): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitField (int, String, String, String, Object): FieldVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitFieldInsn (int, String, String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitFrame (int, int, Object [], int, Object []): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitIincInsn (int, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitInnerClass (String, String, String, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitInsn (int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitIntInsn (int, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitJumpInsn (int, Label): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitLabel (Label): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitLdcInsn (Object): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitLineNumber (int, Label): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitLocalVariable (String, String, String, Label, Label, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitLookupSwitchInsn (Label, int [], Label []): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitMaxs (int, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitMethod (int, String, String, String, String []): MethodVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitMethodInsn (int, String, String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitMultiANewArrayInsn (String, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitOuterClass (String, String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitParameterAnnotation (int, String, boolean): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitSource (String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitTableSwitchInsn (int, int, Label, Label []): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitTryCatchBlock (Label, Label, Label, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitTypeInsn (int, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitVarInsn (int, int): void 0%   (0/1)0%   (0/1)0%   (0/1)
AIB$AIBEmptyVisitor (): void 100% (1/1)100% (3/3)100% (1/1)
visit (String, Object): void 100% (1/1)100% (1/1)100% (1/1)
visitArray (String): AnnotationVisitor 100% (1/1)100% (2/2)100% (1/1)
visitEnd (): void 100% (1/1)100% (1/1)100% (1/1)
visitEnum (String, String, String): void 100% (1/1)100% (1/1)100% (1/1)
     
class AIB$DefaultAnnotation100% (1/1)80%  (4/5)80%  (35/44)90%  (9/10)
visitAnnotation (String, String): AnnotationVisitor 0%   (0/1)0%   (0/9)0%   (0/1)
AIB$DefaultAnnotation (AIB, String, String, Map): void 100% (1/1)100% (15/15)100% (5/5)
insertValue (String, Object): void 100% (1/1)100% (8/8)100% (2/2)
visitArray (String): AnnotationVisitor 100% (1/1)100% (11/11)100% (1/1)
visitEnd (): void 100% (1/1)100% (1/1)100% (1/1)
     
class AIB$AbstractAnnotationVisitor100% (1/1)100% (7/7)85%  (81/95)92%  (22/24)
getClass (String): Class 100% (1/1)36%  (8/22)33%  (1/3)
AIB$AbstractAnnotationVisitor (AIB, AIB$AbstractAnnotationVisitor, String): void 100% (1/1)100% (12/12)100% (4/4)
createAnnotation (String, Map): Annotation 100% (1/1)100% (14/14)100% (4/4)
getEnumValue (String, String): Object 100% (1/1)100% (12/12)100% (3/3)
visit (String, Object): void 100% (1/1)100% (19/19)100% (7/7)
visitAnnotation (String, String): AnnotationVisitor 100% (1/1)100% (8/8)100% (1/1)
visitEnum (String, String, String): void 100% (1/1)100% (8/8)100% (2/2)
     
class AIB100% (1/1)92%  (22/24)85%  (434/508)81%  (82.5/102)
visitOuterClass (String, String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitSource (String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
getDefaultValue (String): Object 100% (1/1)62%  (24/39)72%  (7.2/10)
getMethodDefaults (): Map 100% (1/1)71%  (20/28)84%  (4.2/5)
readClassStream (String, ClassVisitor): void 100% (1/1)77%  (85/110)66%  (13.2/20)
getAib (Class): AIB 100% (1/1)83%  (25/30)86%  (6/7)
<static initializer> 100% (1/1)86%  (49/57)80%  (8/10)
getMethodParameterAnnotations (String, Class [], Class): Annotation [][] 100% (1/1)86%  (44/51)80%  (8/10)
getMethodAnnotation (String, Class [], Class, Class): Annotation 100% (1/1)90%  (18/20)75%  (3/4)
getMethodAnnotations (String, Class [], Class): Annotation [] 100% (1/1)90%  (18/20)75%  (3/4)
AIB (Class): void 100% (1/1)100% (36/36)100% (9/9)
getClassAnnotation (Class): Annotation 100% (1/1)100% (7/7)100% (1/1)
getClassAnnotations (): Annotation [] 100% (1/1)100% (7/7)100% (1/1)
getDeclaredClassAnnotations (): Annotation [] 100% (1/1)100% (7/7)100% (1/1)
getFieldAnnotation (String, Class): Annotation 100% (1/1)100% (12/12)100% (2/2)
getFieldAnnotations (String): Annotation [] 100% (1/1)100% (12/12)100% (2/2)
getMethodIdentifier (String, Class [], Class): String 100% (1/1)100% (40/40)100% (6/6)
visit (int, int, String, String, String, String []): void 100% (1/1)100% (1/1)100% (1/1)
visitAnnotation (String, boolean): AnnotationVisitor 100% (1/1)100% (12/12)100% (2/2)
visitAttribute (Attribute): void 100% (1/1)100% (1/1)100% (1/1)
visitEnd (): void 100% (1/1)100% (1/1)100% (1/1)
visitField (int, String, String, String, Object): FieldVisitor 100% (1/1)100% (6/6)100% (1/1)
visitInnerClass (String, String, String, int): void 100% (1/1)100% (1/1)100% (1/1)
visitMethod (int, String, String, String, String []): MethodVisitor 100% (1/1)100% (8/8)100% (1/1)
     
class AIB$DefaultValueVisitor$1100% (1/1)50%  (2/4)89%  (31/35)60%  (3/5)
visitAnnotation (String, boolean): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitParameterAnnotation (int, String, boolean): AnnotationVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
AIB$DefaultValueVisitor$1 (AIB$DefaultValueVisitor, MethodVisitor, String, St... 100% (1/1)100% (13/13)100% (1/1)
visitAnnotationDefault (): AnnotationVisitor 100% (1/1)100% (18/18)100% (2/2)
     
class AIB$DefaultValueVisitor100% (1/1)73%  (8/11)89%  (33/37)77%  (10/13)
visitField (int, String, String, String, Object): FieldVisitor 0%   (0/1)0%   (0/2)0%   (0/1)
visitOuterClass (String, String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitSource (String, String): void 0%   (0/1)0%   (0/1)0%   (0/1)
AIB$DefaultValueVisitor (AIB): void 100% (1/1)100% (11/11)100% (2/2)
parseAttributes (String): Map 100% (1/1)100% (8/8)100% (2/2)
visit (int, int, String, String, String, String []): void 100% (1/1)100% (1/1)100% (1/1)
visitAnnotation (String, boolean): AnnotationVisitor 100% (1/1)100% (2/2)100% (1/1)
visitAttribute (Attribute): void 100% (1/1)100% (1/1)100% (1/1)
visitEnd (): void 100% (1/1)100% (1/1)100% (1/1)
visitInnerClass (String, String, String, int): void 100% (1/1)100% (1/1)100% (1/1)
visitMethod (int, String, String, String, String []): MethodVisitor 100% (1/1)100% (8/8)100% (1/1)
     
class AIB$NestedAnnotation100% (1/1)75%  (3/4)90%  (35/39)90%  (9/10)
visitArray (String): AnnotationVisitor 0%   (0/1)0%   (0/4)0%   (0/1)
AIB$NestedAnnotation (AIB, AIB$AbstractAnnotationVisitor, String): void 100% (1/1)100% (14/14)100% (4/4)
insertValue (String, Object): void 100% (1/1)100% (7/7)100% (2/2)
visitEnd (): void 100% (1/1)100% (14/14)100% (3/3)
     
class AIB$ArrayAnnotation100% (1/1)75%  (3/4)92%  (58/63)93%  (14/15)
visitArray (String): AnnotationVisitor 0%   (0/1)0%   (0/5)0%   (0/1)
AIB$ArrayAnnotation (AIB, AIB$AbstractAnnotationVisitor, String, String): void 100% (1/1)100% (17/17)100% (5/5)
insertValue (String, Object): void 100% (1/1)100% (6/6)100% (2/2)
visitEnd (): void 100% (1/1)100% (35/35)100% (7/7)
     
class AIB$1100% (1/1)75%  (3/4)92%  (35/38)79%  (5.5/7)
visitAttribute (Attribute): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitAnnotation (String, boolean): AnnotationVisitor 100% (1/1)85%  (11/13)75%  (1.5/2)
AIB$1 (AIB, String): void 100% (1/1)100% (14/14)100% (2/2)
visitEnd (): void 100% (1/1)100% (10/10)100% (2/2)
     
class AIB$TopLevelAnnotation100% (1/1)100% (5/5)94%  (99/105)91%  (20/22)
visitArray (String): AnnotationVisitor 100% (1/1)81%  (25/31)67%  (4/6)
AIB$TopLevelAnnotation (AIB, String, Map): void 100% (1/1)100% (26/26)100% (6/6)
getClassNameFromInternalName (String): String 100% (1/1)100% (18/18)100% (3/3)
insertValue (String, Object): void 100% (1/1)100% (11/11)100% (3/3)
visitEnd (): void 100% (1/1)100% (19/19)100% (4/4)
     
class AIB$2100% (1/1)100% (5/5)96%  (95/99)94%  (15/16)
visitAnnotation (String, boolean): AnnotationVisitor 100% (1/1)85%  (11/13)75%  (1.5/2)
visitParameterAnnotation (int, String, boolean): AnnotationVisitor 100% (1/1)94%  (31/33)92%  (5.5/6)
AIB$2 (AIB, MethodVisitor, String, String): void 100% (1/1)100% (23/23)100% (3/3)
visitAnnotationDefault (): AnnotationVisitor 100% (1/1)100% (2/2)100% (1/1)
visitEnd (): void 100% (1/1)100% (28/28)100% (4/4)

1 
2package net.sourceforge.retroweaver.runtime.java.lang.annotation;
3 
4import java.io.IOException;
5import java.io.InputStream;
6import java.lang.reflect.Array;
7import java.lang.reflect.Method;
8import java.util.ArrayList;
9import java.util.HashMap;
10import java.util.Hashtable;
11import java.util.LinkedList;
12import java.util.List;
13import java.util.Map;
14 
15import net.sourceforge.retroweaver.runtime.java.lang.Enum;
16 
17import org.objectweb.asm.AnnotationVisitor;
18import org.objectweb.asm.Attribute;
19import org.objectweb.asm.ClassReader;
20import org.objectweb.asm.ClassVisitor;
21import org.objectweb.asm.FieldVisitor;
22import org.objectweb.asm.Label;
23import org.objectweb.asm.MethodAdapter;
24import org.objectweb.asm.MethodVisitor;
25import org.objectweb.asm.Type;
26 
27/**
28 * The Annotation Information Block.
29 *
30 * This is the runtime data structure that holds all of the annotation data in
31 * a form that Retroweaver's runtime can use easily. At weave time, we create 
32 * a public static transient field named [ANNOTATIONS_FIELD] of this type. At
33 * runtime, we parse the class file, read the annotation data, and populate this
34 * data structure.
35 *
36 * ( Method parameter annotations appear in the same order as method parameters,
37 *  and each parameter gets its own list of Annotations )
38 *
39 * @author Toby Reyelts
40 *
41 */
42public class AIB implements ClassVisitor {
43 
44  private Class class_;
45  private Map<String,Annotation> classAnnotations;
46  private Map<String,Map<String,Annotation>> methodAnnotations;
47  private Map<String,ArrayList<Map<String,Annotation>>> methodParameterAnnotations;
48  private Map<String,Map<String,Annotation>> fieldAnnotations;
49  private Map<String,Annotation> inheritedClassAnnotations;
50  private Map<String,Object> cachedMethodDefaults;
51 
52  private AIB(Class c) {
53    classAnnotations = new HashMap<String,Annotation>();
54    methodAnnotations = new HashMap<String,Map<String,Annotation>>();
55    methodParameterAnnotations = new HashMap<String,ArrayList<Map<String,Annotation>>>();
56    fieldAnnotations = new HashMap<String,Map<String,Annotation>>();
57    inheritedClassAnnotations = new HashMap<String,Annotation>();
58 
59    this.class_ = c;
60 
61    readClassStream(c.getName(), this);
62  }
63 
64        private void readClassStream(final String name, final ClassVisitor cv) {
65                String resource = "/" + name.replace('.', '/') + ".class";
66                InputStream classStream = class_.getResourceAsStream(resource);
67                try {
68                        ClassReader r = new ClassReader(classStream);
69                        r.accept(cv, ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG
70                                        + ClassReader.SKIP_FRAMES);
71 
72                        Class parent = class_.getSuperclass();
73                        if (parent != null) {
74                                AIB parentAib = getAib(parent);
75                                for(Map.Entry<String, Annotation> entry: parentAib.inheritedClassAnnotations.entrySet()) {
76                                        inheritedClassAnnotations.put(entry.getKey(), entry.getValue());
77                                }
78                        }
79                        // add the local annotations
80                        for(Map.Entry<String, Annotation> entry: classAnnotations.entrySet()) {
81                                inheritedClassAnnotations.put(entry.getKey(), entry.getValue());
82                        }
83                } catch (IOException e) {
84                        // Shouldn't generally happen
85                        throw new AnnotationFormatError(
86                                        "[Retroweaver] Unable to read annotation data for: " + name, e);
87                } finally {
88                        try {
89                                if (classStream != null) {
90                                        classStream.close();
91                                }
92                        } catch (IOException e) { // NOPMD by xlv
93                        }
94                }
95        }
96 
97  private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[]{};
98 
99  private static final Annotation[][] EMPTY_ANNOTATION_ARRAY_ARRAY = new Annotation[][]{};
100 
101  public Annotation[] getClassAnnotations() {
102          return inheritedClassAnnotations.values().toArray( EMPTY_ANNOTATION_ARRAY );
103  }
104 
105  public Annotation[] getDeclaredClassAnnotations() {
106          return classAnnotations.values().toArray( EMPTY_ANNOTATION_ARRAY );
107  }
108 
109  public <T extends Annotation> T getClassAnnotation(final Class<T> annotationType) {
110          return (T) inheritedClassAnnotations.get(annotationType.getName());
111  }
112 
113  public Annotation[] getFieldAnnotations(final String fieldName) {
114          final Map<String,Annotation> annotations = fieldAnnotations.get( fieldName );
115      return annotations.values().toArray( EMPTY_ANNOTATION_ARRAY );
116  }
117 
118  public <T extends Annotation> T getFieldAnnotation(final String fieldName, final Class<T> annotationType) {
119          final Map<String,Annotation> annotations = fieldAnnotations.get( fieldName );
120          return (T) annotations.get(annotationType.getName());
121  }
122 
123  private String getMethodIdentifier(final String methodName, final Class[] parameterTypes, final Class returnType) {
124            final StringBuilder b = new StringBuilder(methodName);
125            b.append('(');
126            for (Class c: parameterTypes) {
127                    b.append(Type.getDescriptor(c));
128            }
129            b.append(')').append(Type.getDescriptor(returnType));
130            return b.toString();
131          
132  }
133  public Annotation[] getMethodAnnotations(final String methodName, final Class[] parameterTypes, final Class returnType) {
134          final Map<String,Annotation> annotations = methodAnnotations.get(getMethodIdentifier(methodName, parameterTypes, returnType));
135          if (annotations == null) {
136                  return EMPTY_ANNOTATION_ARRAY;
137          }
138      return annotations.values().toArray( EMPTY_ANNOTATION_ARRAY );          
139  }
140 
141  public <T extends Annotation> T getMethodAnnotation(final String methodName, final Class[] parameterTypes, final Class returnType, final Class<T> annotationType) {
142          final Map<String,Annotation> annotations = methodAnnotations.get(getMethodIdentifier(methodName, parameterTypes, returnType));
143          if (annotations == null) {
144                  return null;
145          }
146          return (T) annotations.get(annotationType.getName());
147  }
148 
149  private Map<String, Object> getMethodDefaults() {
150          assert(class_.isAnnotation());
151 
152          if (cachedMethodDefaults == null) {
153                DefaultValueVisitor v = new DefaultValueVisitor();
154                cachedMethodDefaults = v.parseAttributes(class_.getName());
155          }
156 
157          return cachedMethodDefaults;
158  }
159 
160  private static final Method cloneMethod;
161 
162  static {
163        try {
164                cloneMethod = Object.class.getDeclaredMethod("clone", new Class[0]);
165                cloneMethod.setAccessible(true);
166        } catch (NoSuchMethodException e) {
167                throw new RuntimeException(e.getMessage());
168        }
169  }
170 
171  public Object getDefaultValue(final String methodName) {
172    assert (class_.isAnnotation());
173 
174        Object o = getMethodDefaults().get(methodName);
175        if (o == null) {
176                return null;
177        } else if (o.getClass().isArray()) {
178                try {
179                        o = cloneMethod.invoke(o);
180                } catch (Exception e) {
181                        throw new RuntimeException(e.getMessage());
182                }
183        }
184        return o;
185  }
186 
187  public Annotation[][] getMethodParameterAnnotations(final String methodName, final Class[] parameterTypes, final Class returnType) {
188          ArrayList<Map<String, Annotation>> annotations = methodParameterAnnotations.get(getMethodIdentifier(methodName, parameterTypes, returnType));
189 
190          if (annotations == null) {
191                  return EMPTY_ANNOTATION_ARRAY_ARRAY; // NOPMD by xlv
192          }
193 
194          if (annotations.size() != parameterTypes.length) {
195                  throw new AnnotationFormatError("inconsistent parameter count");
196          }
197 
198          Annotation[][] a = new Annotation[parameterTypes.length][];
199 
200          for(int i = 0; i < parameterTypes.length; i++) {
201                  Map<String, Annotation> map = annotations.get(i);
202                  
203                  a[i] = map.values().toArray(EMPTY_ANNOTATION_ARRAY);
204          }
205          
206          return a;
207  }
208 
209        private static final Map<Class, AIB> classDescriptors = new Hashtable<Class, AIB>();
210 
211        /**
212         * Returns the AIB for the class.
213         */
214        public static AIB getAib(final Class c) {
215                synchronized (c) {
216                        AIB aib = classDescriptors.get(c);
217                        if (aib == null) {
218                                aib = new AIB(c);
219                                classDescriptors.put(c, aib);
220                        }
221                        return aib;
222                }
223        }
224 
225        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
226                if (!visible) { return EMPTY_VISITOR; }
227 
228                return new TopLevelAnnotation(desc, classAnnotations);
229        }
230 
231        public FieldVisitor visitField(final int access, final String fieldName,
232                        final String desc, final String signature, final Object value) {
233                return new FieldVisitor() {
234 
235                        Map<String,Annotation> annotations = new HashMap<String,Annotation>();
236                        
237                        public AnnotationVisitor visitAnnotation(String desc,
238                                        boolean visible) {
239                                if (!visible) { return EMPTY_VISITOR; }
240 
241                                return new TopLevelAnnotation(desc, annotations);
242                        }
243 
244                        public void visitAttribute(Attribute attr) {
245                                // EMPTY
246                        }
247 
248                        public void visitEnd() {
249                                fieldAnnotations.put(fieldName, annotations);
250                        }
251                };
252        }
253 
254        public MethodVisitor visitMethod(final int access, final String methodName,
255                        final String desc, final String signature, final String[] exceptions) {
256                return new MethodAdapter(EMPTY_VISITOR) {
257 
258                        Map<String,Annotation> ma = new HashMap<String,Annotation>();
259                        ArrayList<Map<String, Annotation>> pa = new ArrayList<Map<String, Annotation>>();
260 
261                        public AnnotationVisitor visitAnnotationDefault() {
262                                return EMPTY_VISITOR;
263                        }
264 
265                        public AnnotationVisitor visitAnnotation(String desc,
266                                        boolean visible) {
267                                if (!visible) { return EMPTY_VISITOR; }
268 
269                                return new TopLevelAnnotation(desc, ma);
270                        }
271 
272                        public AnnotationVisitor visitParameterAnnotation(int parameter,
273                                        String desc, boolean visible) {
274                                if (!visible) { return EMPTY_VISITOR; }
275 
276                                Map<String, Annotation> map;
277                                if (parameter < pa.size()) {
278                                        map = pa.get(parameter);
279                                } else {
280                                        map = new HashMap<String, Annotation>();
281                                        pa.add(parameter, map);
282                                }
283 
284                                return new TopLevelAnnotation(desc, map);
285                        }
286 
287                        public void visitEnd() {
288                                String name = methodName + desc;
289                                methodAnnotations.put(name, ma);
290                                methodParameterAnnotations.put(name, pa);
291                        }
292                };
293        }
294 
295        public void visit(int version, int access, String name, String signature,
296                        String superName, String[] interfaces) {
297                // EMPTY
298        }
299 
300        public void visitSource(String source, String debug) {
301                // EMPTY
302        }
303 
304        public void visitOuterClass(String owner, String name, String desc) {
305                // EMPTY
306        }
307 
308        public void visitAttribute(Attribute attr) {
309                // EMPTY
310        }
311 
312        public void visitInnerClass(String name, String outerName,
313                        String innerName, int access) {
314                // EMPTY
315        }
316 
317        public void visitEnd() {
318                // EMPTY
319        }
320 
321        class DefaultValueVisitor implements ClassVisitor {
322 
323                private final Map<String,Object> attributes = new HashMap<String,Object>();
324 
325                Map<String,Object> parseAttributes(String className) {
326                        readClassStream(className, this);
327 
328                        return attributes;
329                }
330 
331                public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
332                        return EMPTY_VISITOR;
333                }
334 
335                public FieldVisitor visitField(final int access, final String name,
336                                final String desc, final String signature, final Object value) {
337                        return EMPTY_VISITOR;
338                }
339 
340                public MethodVisitor visitMethod(final int access, final String methodName,
341                                final String desc, final String signature, final String[] exceptions) {
342                        return new MethodAdapter(EMPTY_VISITOR) {
343 
344                                public AnnotationVisitor visitAnnotationDefault() {
345                                        // remove leading ()
346                                        String type = desc.substring(2);
347 
348                                        return new DefaultAnnotation(methodName, type, attributes);
349                                }
350 
351                                public AnnotationVisitor visitAnnotation(String desc,
352                                                boolean visible) {
353                                        return EMPTY_VISITOR;
354                                }
355 
356                                public AnnotationVisitor visitParameterAnnotation(int parameter,
357                                                String desc, boolean visible) {
358                                        return EMPTY_VISITOR;
359                                }
360                        };
361                }
362 
363                public void visit(int version, int access, String name, String signature,
364                                String superName, String[] interfaces) {
365                        // EMPTY
366                }
367 
368                public void visitSource(String source, String debug) {
369                        // EMPTY
370                }
371 
372                public void visitOuterClass(String owner, String name, String desc) {
373                        // EMPTY
374                }
375 
376                public void visitAttribute(Attribute attr) {
377                        // EMPTY
378                }
379 
380                public void visitInnerClass(String name, String outerName,
381                                String innerName, int access) {
382                        // EMPTY
383                }
384 
385                public void visitEnd() {
386                        // EMPTY
387                }
388        }
389 
390        abstract class AbstractAnnotationVisitor implements AnnotationVisitor {
391 
392                protected final AbstractAnnotationVisitor parent;
393 
394                protected final String className;
395 
396                AbstractAnnotationVisitor(AbstractAnnotationVisitor parent, String className) {
397                        this.parent = parent;
398                        this.className = className;
399                }
400 
401                protected Class getClass(String name) {
402                        try {
403                                return Class.forName(name, true, class_.getClassLoader());
404                        } catch (ClassNotFoundException e) {
405                                throw new AnnotationFormatError(
406                                                "[Retroweaver] Unable to find class: " + name, e);
407                        }
408                }
409 
410                protected Annotation createAnnotation(String className, Map<String, Object>attributes) {
411                        String internalName = Type.getType(className).getClassName();
412                        Class<? extends Annotation> type = (Class<? extends Annotation>) getClass(internalName);
413                        Annotation a = AnnotationImpl.createAnnotation(type, attributes);
414 
415                        return a;
416                }
417 
418                private Object getEnumValue(final String desc, final String value) {
419                        String name = Type.getType(desc).getClassName();
420                        Class c = getClass(name);
421                        return Enum.valueOf(c, value);
422                }
423 
424                abstract void insertValue(String name, Object value);
425 
426                public void visit(String name, Object value) {
427                        Object v;
428                        if (value instanceof Type) {
429                                Type t = (Type) value;
430                                v = getClass(t.getClassName());
431                        } else {
432                                v = value;
433                        }
434 
435                        insertValue(name, v);
436                }
437 
438                public void visitEnum(String name, String desc, String value) {
439                        insertValue(name, getEnumValue(desc, value));
440                }
441 
442                public AnnotationVisitor visitAnnotation(String name, String desc) {
443                        return new NestedAnnotation(this, desc);
444                }
445 
446        }
447 
448        private class ArrayAnnotation extends AbstractAnnotationVisitor {
449 
450                ArrayAnnotation(AbstractAnnotationVisitor parent, String className, String type) {
451                        super(parent, className);
452                        this.type = type;
453                }
454 
455                private final String type;
456 
457                private final List<Object> values = new LinkedList<Object>();
458 
459                void insertValue(String name, Object value) {
460                        values.add(value);
461                }
462 
463                public AnnotationVisitor visitArray(String name) {
464                        throw new UnsupportedOperationException("Nested arrays are not allowed");
465                }
466 
467                public void visitEnd() {
468                        Class c = getClass(type.replace('/', '.'));
469                        c = c.getComponentType();
470 
471                        Object a = Array.newInstance(c, values.size());
472                        if (!values.isEmpty()) {
473                                a = values.toArray((Object[]) a);
474                        }
475 
476                        parent.insertValue(className, a);
477                }
478        }
479 
480        private class NestedAnnotation extends AbstractAnnotationVisitor {                
481 
482                NestedAnnotation(AbstractAnnotationVisitor parent, String className) {
483                        super(parent, className);
484                }
485 
486                private final Map<String, Object> attributes = new HashMap<String, Object>();
487 
488                void insertValue(String name, Object value) {
489                        attributes.put(name, value);
490                }
491 
492                public AnnotationVisitor visitArray(String name) {
493                        throw new UnsupportedOperationException();
494                }
495 
496                public void visitEnd() {
497                        Annotation annotation = createAnnotation(className, attributes);
498 
499                        parent.insertValue(className, annotation);
500                }
501 
502        }
503 
504        private class DefaultAnnotation extends AbstractAnnotationVisitor {
505                
506                DefaultAnnotation(String className, String type, Map<String, Object> attributes) {
507                        super(null, className);
508                        this.type = type;
509                        this.attributes = attributes;
510                }
511 
512                private final String type;
513 
514                private final Map<String, Object> attributes;
515                
516                void insertValue(String name, Object value) {
517                        attributes.put(className, value);
518                }
519 
520                public AnnotationVisitor visitArray(String name) {
521                        return new ArrayAnnotation(this, className, type);
522                }
523 
524                public AnnotationVisitor visitAnnotation(String name, String desc) {
525                        return new NestedAnnotation(this, className);
526                }
527 
528                public void visitEnd() {
529                }
530 
531        }
532 
533        private class TopLevelAnnotation extends AbstractAnnotationVisitor {
534 
535                TopLevelAnnotation(String className, Map<String,Annotation> annotations) {
536                        super(null, className);
537 
538                        this.annotations = annotations;
539 
540                        // first get default values
541                        // then visitor methods are used to fill the custom settings
542                        String type = Type.getType(className).getClassName();
543                        attributes = new HashMap<String, Object>(getAib(getClass(type)).getMethodDefaults());
544                }
545 
546                private final Map<String,Annotation> annotations;
547 
548                private final Map<String, Object> attributes;
549 
550                private String getClassNameFromInternalName(final String name) {
551                        if (name.charAt(0) != 'L') {
552                                return name;
553                        }
554 
555                        return name.replace('/', '.').substring(1, name.length()-1);
556                }
557 
558                void insertValue(String name, Object value) {
559                        String key = getClassNameFromInternalName(name);
560                        attributes.put(key, value);
561                }
562 
563                public AnnotationVisitor visitArray(String name) {
564                        try {
565                                String type = Type.getType(className).getClassName();
566                                Method m = Class.forName(type).getMethod(name, new Class[0]);
567                                type = m.getReturnType().getName();
568                                return new ArrayAnnotation(this, name, type);
569                        } catch (Exception e) {
570                                throw new AnnotationFormatError(e);
571                        }
572                }
573 
574                public void visitEnd() {
575                        Annotation annotation = createAnnotation(className, attributes);
576 
577                        String key = getClassNameFromInternalName(className);
578                        annotations.put(key, annotation);
579                }
580 
581        }
582        
583        public static final AIBEmptyVisitor EMPTY_VISITOR = new AIBEmptyVisitor();
584 
585        public static final class AIBEmptyVisitor implements ClassVisitor, FieldVisitor,
586                        MethodVisitor, AnnotationVisitor {
587 
588                public void visit(final int version, final int access,
589                                final String name, final String signature,
590                                final String superName, final String[] interfaces) {
591                }
592 
593                public void visitSource(final String source, final String debug) {
594                }
595 
596                public void visitOuterClass(final String owner, final String name,
597                                final String desc) {
598                }
599 
600                public AnnotationVisitor visitAnnotation(final String desc,
601                                final boolean visible) {
602                        return this;
603                }
604 
605                public void visitAttribute(final Attribute attr) {
606                }
607 
608                public void visitInnerClass(final String name, final String outerName,
609                                final String innerName, final int access) {
610                }
611 
612                public FieldVisitor visitField(final int access, final String name,
613                                final String desc, final String signature, final Object value) {
614                        return this;
615                }
616 
617                public MethodVisitor visitMethod(final int access, final String name,
618                                final String desc, final String signature,
619                                final String[] exceptions) {
620                        return this;
621                }
622 
623                public void visitEnd() {
624                }
625 
626                public AnnotationVisitor visitAnnotationDefault() {
627                        return this;
628                }
629 
630                public AnnotationVisitor visitParameterAnnotation(final int parameter,
631                                final String desc, final boolean visible) {
632                        return this;
633                }
634 
635                public void visitCode() {
636                }
637 
638                public void visitFrame(final int type, final int nLocal,
639                                final Object[] local, final int nStack, final Object[] stack) {
640                }
641 
642                public void visitInsn(final int opcode) {
643                }
644 
645                public void visitIntInsn(final int opcode, final int operand) {
646                }
647 
648                public void visitVarInsn(final int opcode, final int var) {
649                }
650 
651                public void visitTypeInsn(final int opcode, final String desc) {
652                }
653 
654                public void visitFieldInsn(final int opcode, final String owner,
655                                final String name, final String desc) {
656                }
657 
658                public void visitMethodInsn(final int opcode, final String owner,
659                                final String name, final String desc) {
660                }
661 
662                public void visitJumpInsn(final int opcode, final Label label) {
663                }
664 
665                public void visitLabel(final Label label) {
666                }
667 
668                public void visitLdcInsn(final Object cst) {
669                }
670 
671                public void visitIincInsn(final int var, final int increment) {
672                }
673 
674                public void visitTableSwitchInsn(final int min, final int max,
675                                final Label dflt, final Label labels[]) {
676                }
677 
678                public void visitLookupSwitchInsn(final Label dflt, final int keys[],
679                                final Label labels[]) {
680                }
681 
682                public void visitMultiANewArrayInsn(final String desc, final int dims) {
683                }
684 
685                public void visitTryCatchBlock(final Label start, final Label end,
686                                final Label handler, final String type) {
687                }
688 
689                public void visitLocalVariable(final String name, final String desc,
690                                final String signature, final Label start, final Label end,
691                                final int index) {
692                }
693 
694                public void visitLineNumber(final int line, final Label start) {
695                }
696 
697                public void visitMaxs(final int maxStack, final int maxLocals) {
698                }
699 
700                public void visit(final String name, final Object value) {
701                }
702 
703                public void visitEnum(final String name, final String desc,
704                                final String value) {
705                }
706 
707                public AnnotationVisitor visitAnnotation(final String name,
708                                final String desc) {
709                        return this;
710                }
711 
712                public AnnotationVisitor visitArray(final String name) {
713                        return this;
714                }
715        }
716 
717}
718 

[all classes][net.sourceforge.retroweaver.runtime.java.lang.annotation]
EMMA 2.0.7906 (unsupported private build) (C) Vladimir Roubtsov