KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > visitclass > AnnotationVisitor


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003-2005 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package edu.umd.cs.findbugs.visitclass;
20
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.DataInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import org.apache.bcel.classfile.Constant;
28 import org.apache.bcel.classfile.ConstantDouble;
29 import org.apache.bcel.classfile.ConstantFloat;
30 import org.apache.bcel.classfile.ConstantInteger;
31 import org.apache.bcel.classfile.ConstantLong;
32 import org.apache.bcel.classfile.ConstantUtf8;
33 import org.apache.bcel.classfile.Unknown;
34
35 public class AnnotationVisitor extends PreorderVisitor {
36
37     /**
38      *
39      */

40     private static final String JavaDoc RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
41     /**
42      *
43      */

44     private static final String JavaDoc RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
45     /**
46      *
47      */

48     private static final String JavaDoc RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
49     /**
50      *
51      */

52     private static final String JavaDoc RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
53     static final boolean DEBUG = false;
54
55     /**
56      * Visit annotation on a class, field or method
57      * @param annotationClass class of annotation
58      * @param map map from names to values
59      * @param runtimeVisible true if annotation is runtime visible
60      */

61     public void visitAnnotation(String JavaDoc annotationClass,
62             Map JavaDoc<String JavaDoc, Object JavaDoc> map, boolean runtimeVisible) {
63         if (DEBUG) {
64         System.out.println("Annotation: " + annotationClass);
65         for (Map.Entry JavaDoc<String JavaDoc, Object JavaDoc> e : map.entrySet()) {
66             System.out.println(" " + e.getKey());
67             System.out.println(" -> " + e.getValue());
68         }
69         }
70     }
71
72     /**
73      * Visit annotation on a method parameter
74      * @param p parameter number, starting at zero (this parameter is not counted)
75      * @param annotationClass class of annotation
76      * @param map map from names to values
77      * @param runtimeVisible true if annotation is runtime visible
78      */

79     public void visitParameterAnnotation(int p, String JavaDoc annotationClass,
80             Map JavaDoc<String JavaDoc, Object JavaDoc> map, boolean runtimeVisible) {
81 // System.out
82
// .println("Parameter " + p + " Annotation: " + annotationClass);
83
// for (Map.Entry<String, Object> e : map.entrySet()) {
84
// System.out.println(" " + e.getKey());
85
// System.out.println(" -> " + e.getValue());
86
// }
87
}
88
89     public void visitSyntheticParameterAnnotation(int p, boolean runtimeVisible) {
90     }
91     
92     @Override JavaDoc
93          public void visit(Unknown obj) {
94         try {
95             
96                 String JavaDoc name = obj.getName();
97                 if (DEBUG)
98                     System.out.println("In " + getDottedClassName() + " found "
99                             + name);
100                 byte[] b = obj.getBytes();
101                 DataInputStream JavaDoc bytes = new DataInputStream JavaDoc(
102                         new ByteArrayInputStream JavaDoc(b));
103                 boolean runtimeVisible = name.equals(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
104                 if (name.equals(RUNTIME_VISIBLE_ANNOTATIONS)
105                         || name.equals(RUNTIME_INVISIBLE_ANNOTATIONS)) {
106
107                     int numAnnotations = bytes.readUnsignedShort();
108                     if (DEBUG)
109                         System.out.println("# of annotations: "
110                                 + numAnnotations);
111                     for (int i = 0; i < numAnnotations; i++) {
112                         String JavaDoc annotationName = getAnnotationName(bytes);
113                         int numPairs = bytes.readUnsignedShort();
114                         Map JavaDoc<String JavaDoc, Object JavaDoc> values = readAnnotationValues(
115                                 bytes, numPairs);
116                         visitAnnotation(annotationName, values, name
117                                 .equals(RUNTIME_VISIBLE_ANNOTATIONS));
118                     }
119
120                 } else if (runtimeVisible
121                         || name.equals(RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS)) {
122                     int numParameters = bytes.readUnsignedByte();
123                     if (DEBUG) System.out.println("Number of parameters: " + numParameters);
124                     int numParametersToMethod = getNumberMethodArguments();
125                     if (DEBUG) System.out.println("Number of parameters to method: " + numParametersToMethod);
126                     int offset = 0;
127                     if (numParametersToMethod > numParameters) {
128                         offset = 1;
129                         visitSyntheticParameterAnnotation(
130                                 0,
131                                 runtimeVisible);
132                         for(int p = numParameters+1; p < numParametersToMethod; p++) {
133                             visitSyntheticParameterAnnotation(
134                                     p,
135                                     runtimeVisible);
136                         }
137                     }
138                     for (int p = 0; p < numParameters; p++) {
139                         int numAnnotations = bytes.readUnsignedShort();
140                         if (DEBUG)
141                             System.out.println("# of annotations on parameter " + (offset+p)
142                                     + ": "
143                                     + numAnnotations);
144                         for (int i = 0; i < numAnnotations; i++) {
145                             String JavaDoc annotationName = getAnnotationName(bytes);
146                             int numPairs = bytes.readUnsignedShort();
147                             Map JavaDoc<String JavaDoc, Object JavaDoc> values = readAnnotationValues(
148                                     bytes, numPairs);
149                             
150                             visitParameterAnnotation(
151                                     p+offset,
152                                     annotationName,
153                                     values,
154                                     runtimeVisible);
155                         }
156                     }
157
158                 }
159
160                 if (DEBUG) {
161                     for (byte aB : b)
162                         System.out.print(Integer.toString((aB & 0xff), 16)
163                                 + " ");
164                     System.out.println();
165                 }
166             
167
168         } catch (Exception JavaDoc e) {
169             // ignore
170
}
171     }
172
173     private Map JavaDoc<String JavaDoc, Object JavaDoc> readAnnotationValues(DataInputStream JavaDoc bytes,
174             int numPairs) throws IOException JavaDoc {
175         Map JavaDoc<String JavaDoc, Object JavaDoc> values = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>();
176         for (int j = 0; j < numPairs; j++) {
177             int memberNameIndex = bytes.readUnsignedShort();
178             String JavaDoc memberName = ((ConstantUtf8) getConstantPool().getConstant(
179                     memberNameIndex)).getBytes();
180             if (DEBUG)
181                 System.out.println("memberName: " + memberName);
182             Object JavaDoc value = readAnnotationValue(bytes);
183             if (DEBUG)
184                 System.out.println(memberName + ":" + value);
185             values.put(memberName, value);
186         }
187         return values;
188     }
189
190     private String JavaDoc getAnnotationName(DataInputStream JavaDoc bytes) throws IOException JavaDoc {
191         int annotationNameIndex = bytes.readUnsignedShort();
192         String JavaDoc annotationName = ((ConstantUtf8) getConstantPool().getConstant(
193                 annotationNameIndex)).getBytes().replace('/','.');
194         annotationName = annotationName.substring(1,
195                 annotationName.length() - 1);
196         if (DEBUG)
197             System.out.println("Annotation name: " + annotationName);
198         return annotationName;
199     }
200
201     private Object JavaDoc readAnnotationValue(DataInputStream JavaDoc bytes)
202             throws IOException JavaDoc {
203         try {
204         char tag = (char) bytes.readUnsignedByte();
205         if (DEBUG)
206             System.out.println("tag: " + tag);
207         switch (tag) {
208         case '[':
209         {
210             int sz = bytes.readUnsignedShort();
211             if (DEBUG)
212                 System.out.println("Array of " + sz + " entries");
213             Object JavaDoc[] result = new Object JavaDoc[sz];
214             for (int i = 0; i < sz; i++)
215                 result[i] = readAnnotationValue(bytes);
216             return result;
217         }
218         case 'B':
219         case 'C':
220         case 'D':
221         case 'F':
222         case 'I':
223         case 'J':
224         case 'S':
225         case 'Z':
226         case 's':
227         case 'c':
228             int cp_index = bytes.readUnsignedShort();
229             Constant c = getConstantPool().getConstant(cp_index);
230             switch (tag) {
231             case 'B':
232                 return (Byte JavaDoc)(byte) ((ConstantInteger) c).getBytes();
233             case 'C':
234                 return (Character JavaDoc)(char) ((ConstantInteger) c).getBytes();
235             case 'D':
236                 return new Double JavaDoc(((ConstantDouble) c).getBytes());
237             case 'F':
238                 return new Float JavaDoc(((ConstantFloat) c).getBytes());
239             case 'I':
240                 return (Integer JavaDoc)((ConstantInteger) c).getBytes();
241             case 'J':
242                 return (Long JavaDoc)((ConstantLong) c).getBytes();
243             case 'S':
244                 return ( Character JavaDoc)(char) ((ConstantInteger) c).getBytes();
245             case 'Z':
246                 return Boolean.valueOf(((ConstantInteger) c).getBytes() != 0);
247             case 's':
248                 return ((ConstantUtf8) c).getBytes();
249             case 'c':
250                 String JavaDoc cName = ((ConstantUtf8)c).getBytes().replace('/','.');
251                 if (cName.startsWith("L") && cName.endsWith(";"))
252                     cName = cName.substring(1,cName.length()-1);
253                 if (DEBUG) System.out.println("cName: " + cName);
254                 return cName;
255             default:
256                 if (DEBUG) System.out.println("Impossible");
257                 throw new IllegalStateException JavaDoc("Impossible");
258             }
259         case '@':
260             throw new IllegalArgumentException JavaDoc("Not ready to handle annotations as elements of annotations");
261         case 'e':
262             {
263             int cp1= bytes.readUnsignedShort();
264             ConstantUtf8 c1 = (ConstantUtf8) getConstantPool().getConstant(cp1);
265             String JavaDoc cName = c1.getBytes().replace('/','.');
266             if (cName.startsWith("L") && cName.endsWith(";"))
267                 cName = cName.substring(1,cName.length()-1);
268             int cp2= bytes.readUnsignedShort();
269             ConstantUtf8 c2 = (ConstantUtf8) getConstantPool().getConstant(cp2);
270             String JavaDoc result = cName +"." + c2.getBytes();
271             // System.out.println(result);
272
return result;
273             }
274         default:
275             if (DEBUG) System.out.println("Unexpected tag of " + tag);
276             throw new IllegalArgumentException JavaDoc("Unexpected tag of " + tag);
277         }
278         } catch (RuntimeException JavaDoc e) {
279             if (DEBUG) {
280             System.out.println("Problem processing annotation " + e.getMessage());
281             e.printStackTrace();
282             }
283             throw e;
284         }
285     }
286 }
287
Popular Tags