1 19 package edu.umd.cs.findbugs.visitclass; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.DataInputStream ; 23 import java.io.IOException ; 24 import java.util.HashMap ; 25 import java.util.Map ; 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 40 private static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; 41 44 private static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; 45 48 private static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; 49 52 private static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; 53 static final boolean DEBUG = false; 54 55 61 public void visitAnnotation(String annotationClass, 62 Map <String , Object > map, boolean runtimeVisible) { 63 if (DEBUG) { 64 System.out.println("Annotation: " + annotationClass); 65 for (Map.Entry <String , Object > e : map.entrySet()) { 66 System.out.println(" " + e.getKey()); 67 System.out.println(" -> " + e.getValue()); 68 } 69 } 70 } 71 72 79 public void visitParameterAnnotation(int p, String annotationClass, 80 Map <String , Object > map, boolean runtimeVisible) { 81 } 88 89 public void visitSyntheticParameterAnnotation(int p, boolean runtimeVisible) { 90 } 91 92 @Override 93 public void visit(Unknown obj) { 94 try { 95 96 String name = obj.getName(); 97 if (DEBUG) 98 System.out.println("In " + getDottedClassName() + " found " 99 + name); 100 byte[] b = obj.getBytes(); 101 DataInputStream bytes = new DataInputStream ( 102 new ByteArrayInputStream (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 annotationName = getAnnotationName(bytes); 113 int numPairs = bytes.readUnsignedShort(); 114 Map <String , Object > 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 annotationName = getAnnotationName(bytes); 146 int numPairs = bytes.readUnsignedShort(); 147 Map <String , Object > 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 e) { 169 } 171 } 172 173 private Map <String , Object > readAnnotationValues(DataInputStream bytes, 174 int numPairs) throws IOException { 175 Map <String , Object > values = new HashMap <String , Object >(); 176 for (int j = 0; j < numPairs; j++) { 177 int memberNameIndex = bytes.readUnsignedShort(); 178 String memberName = ((ConstantUtf8) getConstantPool().getConstant( 179 memberNameIndex)).getBytes(); 180 if (DEBUG) 181 System.out.println("memberName: " + memberName); 182 Object 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 getAnnotationName(DataInputStream bytes) throws IOException { 191 int annotationNameIndex = bytes.readUnsignedShort(); 192 String 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 readAnnotationValue(DataInputStream bytes) 202 throws IOException { 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 [] result = new Object [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 )(byte) ((ConstantInteger) c).getBytes(); 233 case 'C': 234 return (Character )(char) ((ConstantInteger) c).getBytes(); 235 case 'D': 236 return new Double (((ConstantDouble) c).getBytes()); 237 case 'F': 238 return new Float (((ConstantFloat) c).getBytes()); 239 case 'I': 240 return (Integer )((ConstantInteger) c).getBytes(); 241 case 'J': 242 return (Long )((ConstantLong) c).getBytes(); 243 case 'S': 244 return ( Character )(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 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 ("Impossible"); 258 } 259 case '@': 260 throw new IllegalArgumentException ("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 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 result = cName +"." + c2.getBytes(); 271 return result; 273 } 274 default: 275 if (DEBUG) System.out.println("Unexpected tag of " + tag); 276 throw new IllegalArgumentException ("Unexpected tag of " + tag); 277 } 278 } catch (RuntimeException 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 |