KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > backport175 > bytecode > AnnotationDefaults


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

8 package com.tc.backport175.bytecode;
9
10 import com.tc.backport175.ReaderException;
11 import com.tc.backport175.bytecode.AnnotationElement.Annotation;
12
13 import com.tc.asm.AnnotationVisitor;
14 import com.tc.asm.ClassAdapter;
15 import com.tc.asm.ClassReader;
16 import com.tc.asm.ClassVisitor;
17 import com.tc.asm.ClassWriter;
18 import com.tc.asm.MethodAdapter;
19 import com.tc.asm.MethodVisitor;
20
21 import java.util.Map JavaDoc;
22 import java.util.WeakHashMap JavaDoc;
23
24 /**
25  * Container for default value of the annotations
26  * <p/>
27  * As per spec, default values are "unnamed" annotation on the element method of the annotation interface.
28  *
29  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
30  */

31 class AnnotationDefaults {
32
33     /**
34      * Cache of default values, key is annotationClassKey, value is Annotation whose elements are named according
35      * to the element name which have a default value. Element without default value are thus not present in the Annotation.
36      */

37     private static Map JavaDoc s_annotationDefaults = new WeakHashMap JavaDoc();
38
39     /**
40      * Retrieve (create if not in cache) the annotation defaults
41      *
42      * @param annotationClassName
43      * @param loader
44      * @return
45      */

46     public static AnnotationElement.Annotation getDefaults(final String JavaDoc annotationClassName, final ClassLoader JavaDoc loader) {
47         AnnotationReader.ClassKey key = new AnnotationReader.ClassKey(annotationClassName, loader);
48         AnnotationElement.Annotation defaults = (AnnotationElement.Annotation) s_annotationDefaults.get(key);
49         if (defaults == null) {
50             final AnnotationElement.Annotation newDefaults = new AnnotationElement.Annotation(annotationClassName);
51             final byte[] bytes;
52             try {
53                 bytes = AnnotationReader.getBytecodeFor(annotationClassName, loader);
54             } catch (Exception JavaDoc e) {
55                 throw new ReaderException("could not retrieve the bytecode from the bytecode provider for class [" + annotationClassName+ "]", e);
56             }
57             ClassReader cr = new ClassReader(bytes);
58             ClassWriter cw = new ClassWriter(false, true);
59             cr.accept(new AnnotationDefaultsClassVisitor(cw, newDefaults, loader), true);
60             defaults = newDefaults;
61             s_annotationDefaults.put(key, newDefaults);
62         }
63         return defaults;
64     }
65
66     private static final class AnnotationDefaultsClassVisitor extends ClassAdapter {
67
68       private final AnnotationElement.Annotation defaults;
69       private final ClassLoader JavaDoc loader;
70
71       private AnnotationDefaultsClassVisitor(ClassVisitor cv, AnnotationElement.Annotation defaults, ClassLoader JavaDoc loader) {
72         super(cv);
73         this.defaults = defaults;
74         this.loader = loader;
75       }
76
77       public MethodVisitor visitMethod(int access, final String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
78           return new AnnotationDefaultsMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), name, defaults, loader);
79       }
80     }
81
82     private static final class AnnotationDefaultsMethodVisitor extends MethodAdapter {
83       private final String JavaDoc name;
84       private final Annotation defaults;
85       private final ClassLoader JavaDoc loader;
86       
87       private AnnotationDefaultsMethodVisitor(MethodVisitor mv, String JavaDoc name, Annotation defaults, ClassLoader JavaDoc loader) {
88         super(mv);
89         this.name = name;
90         this.defaults = defaults;
91         this.loader = loader;
92       }
93       
94       public AnnotationVisitor visitAnnotationDefault() {
95         return new DefaultAnnotationBuilderVisitor(defaults, name, loader);
96       }
97     }
98
99     /**
100      * Read the default value of annotation element
101      * Behave like a regular annotation visitor except that the name is force to the element name (else null in bytecode)
102      *
103      * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
104      */

105     static class DefaultAnnotationBuilderVisitor extends AnnotationReader.AnnotationBuilderVisitor {
106
107         private String JavaDoc m_methodName;
108
109         public DefaultAnnotationBuilderVisitor(final AnnotationElement.NestedAnnotationElement annotation, String JavaDoc methodName, ClassLoader JavaDoc loader) {
110             super(annotation, loader, null);
111             m_methodName = methodName;
112         }
113
114         public void visit(String JavaDoc name, Object JavaDoc value) {
115             super.visit(m_methodName, value);
116         }
117
118         public void visitEnum(String JavaDoc name, String JavaDoc desc, String JavaDoc value) {
119             super.visitEnum(m_methodName, desc, value);
120         }
121
122         public AnnotationVisitor visitAnnotation(String JavaDoc name, String JavaDoc desc) {
123             return super.visitAnnotation(m_methodName, desc);
124         }
125
126         public AnnotationVisitor visitArray(String JavaDoc name) {
127             return super.visitArray(m_methodName);
128         }
129
130     }
131
132     public static void refresh(AnnotationReader.ClassKey key) {
133         AnnotationElement.Annotation defaults = (AnnotationElement.Annotation) s_annotationDefaults.get(key);
134         if (defaults != null) {
135             s_annotationDefaults.remove(key);
136         }
137     }
138 }
139
Popular Tags