001 package AST; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.*; 006 import beaver.*; 007 import java.util.ArrayList; 008 import java.util.zip.*; 009 import java.io.*; 010 import java.io.FileNotFoundException; 011 import java.util.Collection; 012 /** 013 * @ast class 014 * 015 */ 016 public class Attributes extends java.lang.Object { 017 018 protected BytecodeParser p; 019 020 021 protected boolean isSynthetic; 022 023 024 025 protected Attributes(BytecodeParser parser) { 026 p = parser; 027 isSynthetic = false; 028 } 029 030 031 032 protected void processAttribute(String attribute_name, int attribute_length) { 033 if(attribute_name.equals("Synthetic")) { 034 isSynthetic = true; 035 } else { 036 this.p.skip(attribute_length); 037 } 038 } 039 040 041 042 protected void attributes() { 043 int attributes_count = p.u2(); 044 if(BytecodeParser.VERBOSE) 045 p.println(" " + attributes_count + " attributes:"); 046 for (int j = 0; j < attributes_count; j++) { 047 int attribute_name_index = p.u2(); 048 int attribute_length = p.u4(); 049 String attribute_name = p.getCONSTANT_Utf8_Info(attribute_name_index).string(); 050 if(BytecodeParser.VERBOSE) 051 p.println(" Attribute: " + attribute_name + ", length: " 052 + attribute_length); 053 processAttribute(attribute_name, attribute_length); 054 } 055 } 056 057 058 059 public boolean isSynthetic() { 060 return isSynthetic; 061 } 062 063 064 065 // 4.8.15.1 066 protected ElementValue readElementValue() { 067 char c = (char)p.u1(); 068 switch (c) { 069 case 'e': 070 int type_name_index = this.p.u2(); 071 String type_name = this.p.getCONSTANT_Utf8_Info(type_name_index).string(); 072 // remove inital L and trailing ; 073 Access typeAccess = this.p.fromClassName(type_name.substring(1, type_name.length() - 1)); 074 int const_name_index = this.p.u2(); 075 String const_name = this.p.getCONSTANT_Utf8_Info(const_name_index).string(); 076 return new ElementConstantValue(typeAccess.qualifiesAccess(new VarAccess(const_name))); 077 case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': case 's': 078 int const_value_index = p.u2(); 079 Expr e = this.p.getCONSTANT_Info(const_value_index).expr(); 080 return new ElementConstantValue(e); 081 case 'c': 082 int class_info_index = p.u2(); 083 String descriptor = this.p.getCONSTANT_Utf8_Info(class_info_index).string(); 084 e = new TypeDescriptor(p, descriptor).type(); 085 return new ElementConstantValue(e); 086 case '@': 087 return new ElementAnnotationValue(readAnnotation()); 088 case '[': 089 int index = p.u2(); 090 List list = new List(); 091 for(int i = 0; i < index; i++) 092 list.add(readElementValue()); 093 return new ElementArrayValue(list); 094 default: 095 throw new Error("AnnotationDefault tag " + c + " not supported"); 096 } 097 } 098 099 100 101 // 4.8.15 102 protected Annotation readAnnotation() { 103 Access typeAccess = new FieldDescriptor(p, "").type(); 104 int num_element_value_pairs = p.u2(); 105 List list = new List(); 106 for(int i = 0; i < num_element_value_pairs; i++) { 107 int element_name_index = p.u2(); 108 String element_name = p.getCONSTANT_Utf8_Info(element_name_index).string(); 109 ElementValue element_value = readElementValue(); 110 list.add(new ElementValuePair(element_name, element_value)); 111 } 112 return new Annotation("Annotation", typeAccess, list); 113 } 114 115 116 117 public static class FieldAttributes extends Attributes { 118 protected CONSTANT_Info constantValue; 119 public java.util.ArrayList annotations; 120 public Signatures.FieldSignature fieldSignature; 121 public FieldAttributes(BytecodeParser p) { 122 super(p); 123 attributes(); 124 } 125 126 protected void processAttribute(String attribute_name, int attribute_length) { 127 if(attribute_name.equals("ConstantValue") && attribute_length == 2) { 128 int constantvalue_index = p.u2(); 129 constantValue = p.getCONSTANT_Info(constantvalue_index); 130 } 131 else if(attribute_name.equals("RuntimeVisibleAnnotations")) { 132 int num_annotations = p.u2(); 133 if(annotations == null) 134 annotations = new java.util.ArrayList(); 135 for(int j = 0; j < num_annotations; j++) 136 annotations.add(readAnnotation()); 137 } 138 else if(attribute_name.equals("RuntimeInvisibleAnnotations")) { 139 int num_annotations = p.u2(); 140 if(annotations == null) 141 annotations = new java.util.ArrayList(); 142 for(int j = 0; j < num_annotations; j++) 143 annotations.add(readAnnotation()); 144 } 145 else if(attribute_name.equals("Signature")) { 146 int signature_index = p.u2(); 147 String s = p.getCONSTANT_Utf8_Info(signature_index).string(); 148 fieldSignature = new Signatures.FieldSignature(s); 149 } 150 else { 151 super.processAttribute(attribute_name, attribute_length); 152 } 153 } 154 155 public CONSTANT_Info constantValue() { 156 return constantValue; 157 } 158 } 159 160 161 162 public static class MethodAttributes extends Attributes { 163 protected List exceptionList; 164 protected ElementValue elementValue; 165 public Signatures.MethodSignature methodSignature; 166 public java.util.ArrayList annotations; 167 public java.util.ArrayList[] parameterAnnotations; 168 169 public MethodAttributes(BytecodeParser p) { 170 super(p); 171 attributes(); 172 } 173 174 protected void processAttribute(String attribute_name, int attribute_length) { 175 if(attribute_name.equals("Exceptions")) { 176 parseExceptions(); 177 } 178 else if(attribute_name.equals("AnnotationDefault")) { 179 annotationDefault(); 180 } 181 else if(attribute_name.equals("Signature")) { 182 int signature_index = p.u2(); 183 String s = p.getCONSTANT_Utf8_Info(signature_index).string(); 184 methodSignature = new Signatures.MethodSignature(s); 185 } 186 else if(attribute_name.equals("RuntimeVisibleAnnotations")) { 187 int num_annotations = p.u2(); 188 if(annotations == null) 189 annotations = new java.util.ArrayList(); 190 for(int j = 0; j < num_annotations; j++) 191 annotations.add(readAnnotation()); 192 } 193 else if(attribute_name.equals("RuntimeInvisibleAnnotations")) { 194 int num_annotations = p.u2(); 195 if(annotations == null) 196 annotations = new java.util.ArrayList(); 197 for(int j = 0; j < num_annotations; j++) 198 annotations.add(readAnnotation()); 199 } 200 else if(attribute_name.equals("RuntimeVisibleParameterAnnotations")) { 201 int num_parameters = p.u1(); 202 if(parameterAnnotations == null) 203 parameterAnnotations = new java.util.ArrayList[num_parameters]; 204 for(int i = 0; i < num_parameters; i++) { 205 if(parameterAnnotations[i] == null) 206 parameterAnnotations[i] = new java.util.ArrayList(); 207 int num_annotations = p.u2(); 208 for(int j = 0; j < num_annotations; j++) 209 parameterAnnotations[i].add(readAnnotation()); 210 } 211 } 212 else if(attribute_name.equals("RuntimeInvisibleParameterAnnotations")) { 213 int num_parameters = p.u1(); 214 if(parameterAnnotations == null) 215 parameterAnnotations = new java.util.ArrayList[num_parameters]; 216 for(int i = 0; i < num_parameters; i++) { 217 if(parameterAnnotations[i] == null) 218 parameterAnnotations[i] = new java.util.ArrayList(); 219 int num_annotations = p.u2(); 220 for(int j = 0; j < num_annotations; j++) 221 parameterAnnotations[i].add(readAnnotation()); 222 } 223 } 224 /* 225 else if(attribute_name.equals("RuntimeVisibleExtendedAnnotations")) { 226 int num_annotations = p.u2(); 227 java.util.ArrayList extendedAnnotations = new java.util.ArrayList(); 228 for(int j = 0; j < num_annotations; j++) { 229 extendedAnnotations.add(readAnnotation()); 230 } 231 int kind = p.u1(); 232 if(kind == 0x06) 233 System.out.println("Found receiver annotation"); 234 if(kind >= 0x00 && kind <= 0x05) // typecast, instaceof, new 235 p.u2(); // skip 2 236 else if(kind == 0x08 || kind == 0x09) { // local variable 237 int table_length = p.u2(); 238 for(int i = 0; i < table_length; i++) 239 p.skip(6); 240 } 241 else if(kind >= 0x10 && kind <= 0x13) // bound 242 p.skip(2); 243 else if(kind >= 0x14 && kind <= 0x15) // extends, implements 244 p.skip(1); 245 else if(kind >= 0x16 && kind <= 0x17) // throws 246 p.skip(1); 247 248 249 this.p.skip(attribute_length); 250 } 251 */ 252 else { 253 super.processAttribute(attribute_name, attribute_length); 254 } 255 } 256 257 private void parseExceptions() { 258 int number_of_exceptions = p.u2(); 259 exceptionList = new List(); 260 if(BytecodeParser.VERBOSE) 261 p.println(" " + number_of_exceptions + " exceptions:"); 262 for (int i = 0; i < number_of_exceptions; i++) { 263 CONSTANT_Class_Info exception = p.getCONSTANT_Class_Info(p.u2()); 264 if(BytecodeParser.VERBOSE) 265 p.println(" exception " + exception.name()); 266 exceptionList.add(exception.access()); 267 } 268 } 269 270 public List exceptionList() { 271 return exceptionList != null ? exceptionList : new List(); 272 } 273 274 public ElementValue elementValue() { 275 return elementValue; 276 } 277 278 // 4.8.19 279 private void annotationDefault() { 280 elementValue = readElementValue(); 281 } 282 283 } 284 285 286 287 public static class TypeAttributes extends Attributes { 288 TypeDecl typeDecl; 289 TypeDecl outerTypeDecl; 290 Program classPath; 291 292 private boolean isInnerClass; 293 294 public TypeAttributes(BytecodeParser p, TypeDecl typeDecl, TypeDecl outerTypeDecl, Program classPath) { 295 super(p); 296 this.typeDecl = typeDecl; 297 this.outerTypeDecl = outerTypeDecl; 298 this.classPath = classPath; 299 attributes(); 300 } 301 302 public boolean isInnerClass() { 303 return isInnerClass; 304 } 305 306 protected void processAttribute(String attribute_name, int attribute_length) { 307 if(attribute_name.equals("InnerClasses")) { 308 innerClasses(); 309 } 310 else if(attribute_name.equals("Signature")) { 311 int signature_index = p.u2(); 312 String s = p.getCONSTANT_Utf8_Info(signature_index).string(); 313 Signatures.ClassSignature classSignature = new Signatures.ClassSignature(s); 314 typeDecl = typeDecl.makeGeneric(classSignature); 315 } 316 else if(attribute_name.equals("RuntimeVisibleAnnotations")) { 317 int num_annotations = p.u2(); 318 //System.out.println("RuntimeVisibleAnnotations: " + num_annotations); 319 for(int j = 0; j < num_annotations; j++) { 320 Annotation a = readAnnotation(); 321 typeDecl.getModifiers().addModifier(a); 322 } 323 } 324 else if(attribute_name.equals("RuntimeInvisibleAnnotations")) { 325 int num_annotations = p.u2(); 326 //System.out.println("RuntimeInvisibleAnnotations: " + num_annotations); 327 for(int j = 0; j < num_annotations; j++) { 328 Annotation a = readAnnotation(); 329 typeDecl.getModifiers().addModifier(a); 330 } 331 } 332 else { 333 super.processAttribute(attribute_name, attribute_length); 334 } 335 } 336 337 protected void innerClasses() { 338 int number_of_classes = this.p.u2(); 339 if(BytecodeParser.VERBOSE) 340 p.println(" Number of classes: " + number_of_classes); 341 for (int i = 0; i < number_of_classes; i++) { 342 if(BytecodeParser.VERBOSE) 343 p.print(" " + i + "(" + number_of_classes + ")" + ":"); 344 int inner_class_info_index = this.p.u2(); 345 int outer_class_info_index = this.p.u2(); 346 int inner_name_index = this.p.u2(); 347 int inner_class_access_flags = this.p.u2(); 348 if(inner_class_info_index > 0) { 349 CONSTANT_Class_Info inner_class_info = this.p.getCONSTANT_Class_Info(inner_class_info_index); 350 String inner_class_name = inner_class_info.name(); 351 String inner_name = inner_class_name.substring(inner_class_name.lastIndexOf("$")+1); 352 String outer_class_name; 353 if (outer_class_info_index > 0) { 354 CONSTANT_Class_Info outer_class_info = this.p.getCONSTANT_Class_Info(outer_class_info_index); 355 if(inner_class_info == null || outer_class_info == null) { 356 System.out.println("Null"); 357 } 358 outer_class_name = outer_class_info.name(); 359 360 if(BytecodeParser.VERBOSE) 361 this.p.println(" inner: " + inner_class_name + ", outer: " + outer_class_name); 362 363 } else { 364 //anonymous inner class; need to infer outer_class_name from inner_class_name 365 outer_class_name = inner_class_name.substring(0,inner_class_name.lastIndexOf("$")); 366 } 367 if (inner_class_info.name().equals(p.classInfo.name())) { 368 if(BytecodeParser.VERBOSE) 369 p.println(" Class " + inner_class_name + " is inner (" + inner_name + ")"); 370 typeDecl.setID(inner_name); 371 typeDecl.setModifiers(BytecodeParser.modifiers(inner_class_access_flags & 0x041f)); 372 if (this.p.outerClassName != null && this.p.outerClassName.equals(outer_class_name)) { 373 MemberTypeDecl m = null; 374 if (typeDecl instanceof ClassDecl) { 375 m = new MemberClassDecl((ClassDecl)typeDecl); 376 outerTypeDecl.addBodyDecl(m); 377 } else if (typeDecl instanceof InterfaceDecl) { 378 m = new MemberInterfaceDecl((InterfaceDecl)typeDecl); 379 outerTypeDecl.addBodyDecl(m); 380 } 381 } else { 382 isInnerClass = true; 383 } 384 } 385 if (outer_class_name.equals(this.p.classInfo.name())) { 386 if(BytecodeParser.VERBOSE) 387 p.println(" Class " + this.p.classInfo.name() 388 + " has inner class: " + inner_class_name); 389 if(BytecodeParser.VERBOSE) 390 p.println("Begin processing: " + inner_class_name); 391 try { 392 java.io.InputStream is=null; 393 try{ 394 is = classPath.getInputStream(inner_class_name); 395 } catch(Error e) { 396 if(e.getMessage().startsWith("Could not find nested type")) { 397 //ignore 398 } else { 399 throw e; 400 } 401 } 402 if(is != null) { 403 BytecodeParser p = new BytecodeParser(is, this.p.name); 404 p.parse(typeDecl, outer_class_name, classPath, (inner_class_access_flags & Flags.ACC_STATIC) == 0); 405 is.close(); 406 } 407 else { 408 p.println("Error: ClassFile " + inner_class_name 409 + " not found"); 410 } 411 } catch (FileNotFoundException e) { 412 System.out.println("Error: " + inner_class_name 413 + " not found"); 414 } catch (Exception e) { 415 e.printStackTrace(); 416 System.exit(1); 417 } 418 if(BytecodeParser.VERBOSE) 419 p.println("End processing: " + inner_class_name); 420 } 421 } 422 423 } 424 if(BytecodeParser.VERBOSE) 425 p.println(" end"); 426 } 427 } 428 429 430 }