| 1 21 package proguard.classfile; 22 23 import proguard.classfile.util.*; 24 import proguard.classfile.visitor.*; 25 import proguard.classfile.attribute.*; 26 import proguard.classfile.attribute.visitor.AttributeVisitor; 27 import proguard.classfile.constant.*; 28 import proguard.classfile.constant.visitor.ConstantVisitor; 29 30 35 public class ProgramClass implements Clazz 36 { 37 public int u4magic; 38 public int u4version; 39 public int u2constantPoolCount; 40 public Constant[] constantPool; 41 public int u2accessFlags; 42 public int u2thisClass; 43 public int u2superClass; 44 public int u2interfacesCount; 45 public int[] u2interfaces; 46 public int u2fieldsCount; 47 public ProgramField[] fields; 48 public int u2methodsCount; 49 public ProgramMethod[] methods; 50 public int u2attributesCount; 51 public Attribute[] attributes; 52 53 57 public Clazz[] subClasses; 58 59 62 public Object visitorInfo; 63 64 65 68 public ProgramClass() {} 69 70 71 74 public Constant getConstant(int constantIndex) 75 { 76 return constantPool[constantIndex]; 77 } 78 79 80 82 public int getAccessFlags() 83 { 84 return u2accessFlags; 85 } 86 87 public String getName() 88 { 89 return getClassName(u2thisClass); 90 } 91 92 public String getSuperName() 93 { 94 return u2superClass == 0 ? null : getClassName(u2superClass); 95 } 96 97 public int getInterfaceCount() 98 { 99 return u2interfacesCount; 100 } 101 102 public String getInterfaceName(int index) 103 { 104 return getClassName(u2interfaces[index]); 105 } 106 107 public int getTag(int constantIndex) 108 { 109 return constantPool[constantIndex].getTag(); 110 } 111 112 public String getString(int constantIndex) 113 { 114 try 115 { 116 return ((Utf8Constant)constantPool[constantIndex]).getString(); 117 } 118 catch (ClassCastException ex) 119 { 120 new ClassPrinter().visitProgramClass(this); 121 throw new ClassCastException ("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]"); 122 } 123 } 124 125 public String getStringString(int constantIndex) 126 { 127 try 128 { 129 return ((StringConstant)constantPool[constantIndex]).getString(this); 130 } 131 catch (ClassCastException ex) 132 { 133 throw new ClassCastException ("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]"); 134 } 135 } 136 137 public String getClassName(int constantIndex) 138 { 139 try 140 { 141 return ((ClassConstant)constantPool[constantIndex]).getName(this); 142 } 143 catch (ClassCastException ex) 144 { 145 throw new ClassCastException ("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]"); 146 } 147 } 148 149 public String getName(int constantIndex) 150 { 151 try 152 { 153 return ((NameAndTypeConstant)constantPool[constantIndex]).getName(this); 154 } 155 catch (ClassCastException ex) 156 { 157 throw new ClassCastException ("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]"); 158 } 159 } 160 161 public String getType(int constantIndex) 162 { 163 try 164 { 165 return ((NameAndTypeConstant)constantPool[constantIndex]).getType(this); 166 } 167 catch (ClassCastException ex) 168 { 169 throw new ClassCastException ("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]"); 170 } 171 } 172 173 174 public void addSubClass(Clazz clazz) 175 { 176 if (subClasses == null) 177 { 178 subClasses = new Clazz[1]; 179 } 180 else 181 { 182 Clazz[] temp = new Clazz[subClasses.length+1]; 184 System.arraycopy(subClasses, 0, temp, 0, subClasses.length); 185 subClasses = temp; 186 } 187 188 subClasses[subClasses.length-1] = clazz; 189 } 190 191 192 public Clazz getSuperClass() 193 { 194 return u2superClass != 0 ? 195 ((ClassConstant)constantPool[u2superClass]).referencedClass : 196 null; 197 } 198 199 200 public Clazz getInterface(int index) 201 { 202 return ((ClassConstant)constantPool[u2interfaces[index]]).referencedClass; 203 } 204 205 206 public boolean extends_(Clazz clazz) 207 { 208 if (this.equals(clazz)) 209 { 210 return true; 211 } 212 213 Clazz superClass = getSuperClass(); 214 return superClass != null && 215 superClass.extends_(clazz); 216 } 217 218 219 public boolean extendsOrImplements(Clazz clazz) 220 { 221 if (this.equals(clazz)) 222 { 223 return true; 224 } 225 226 Clazz superClass = getSuperClass(); 227 if (superClass != null && 228 superClass.extendsOrImplements(clazz)) 229 { 230 return true; 231 } 232 233 for (int index = 0; index < u2interfacesCount; index++) 234 { 235 Clazz interfaceClass = getInterface(index); 236 if (interfaceClass != null && 237 interfaceClass.extendsOrImplements(clazz)) 238 { 239 return true; 240 } 241 } 242 243 return false; 244 } 245 246 247 public Field findField(String name, String descriptor) 248 { 249 for (int index = 0; index < u2fieldsCount; index++) 250 { 251 Field field = fields[index]; 252 if ((name == null || field.getName(this).equals(name)) && 253 (descriptor == null || field.getDescriptor(this).equals(descriptor))) 254 { 255 return field; 256 } 257 } 258 259 return null; 260 } 261 262 263 public Method findMethod(String name, String descriptor) 264 { 265 for (int index = 0; index < u2methodsCount; index++) 266 { 267 Method method = methods[index]; 268 if ((name == null || method.getName(this).equals(name)) && 269 (descriptor == null || method.getDescriptor(this).equals(descriptor))) 270 { 271 return method; 272 } 273 } 274 275 return null; 276 } 277 278 279 public void accept(ClassVisitor classVisitor) 280 { 281 classVisitor.visitProgramClass(this); 282 } 283 284 285 public void hierarchyAccept(boolean visitThisClass, 286 boolean visitSuperClass, 287 boolean visitInterfaces, 288 boolean visitSubclasses, 289 ClassVisitor classVisitor) 290 { 291 if (visitThisClass) 293 { 294 accept(classVisitor); 295 } 296 297 if (visitSuperClass) 299 { 300 Clazz superClass = getSuperClass(); 301 if (superClass != null) 302 { 303 superClass.hierarchyAccept(true, 304 true, 305 visitInterfaces, 306 false, 307 classVisitor); 308 } 309 } 310 311 if (visitInterfaces) 313 { 314 for (int index = 0; index < u2interfacesCount; index++) 315 { 316 Clazz interfaceClass = getInterface(index); 317 if (interfaceClass != null) 318 { 319 interfaceClass.hierarchyAccept(true, 320 true, 321 true, 322 false, 323 classVisitor); 324 } 325 } 326 } 327 328 if (visitSubclasses) 330 { 331 if (subClasses != null) 332 { 333 for (int index = 0; index < subClasses.length; index++) 334 { 335 Clazz subClass = subClasses[index]; 336 subClass.hierarchyAccept(true, 337 false, 338 false, 339 true, 340 classVisitor); 341 } 342 } 343 } 344 } 345 346 347 public void constantPoolEntriesAccept(ConstantVisitor constantVisitor) 348 { 349 for (int index = 1; index < u2constantPoolCount; index++) 350 { 351 if (constantPool[index] != null) 352 { 353 constantPool[index].accept(this, constantVisitor); 354 } 355 } 356 } 357 358 359 public void constantPoolEntryAccept(int index, ConstantVisitor constantVisitor) 360 { 361 constantPool[index].accept(this, constantVisitor); 362 } 363 364 365 public void fieldsAccept(MemberVisitor memberVisitor) 366 { 367 for (int index = 0; index < u2fieldsCount; index++) 368 { 369 fields[index].accept(this, memberVisitor); 370 } 371 } 372 373 374 public void fieldAccept(String name, String descriptor, MemberVisitor memberVisitor) 375 { 376 Field field = findField(name, descriptor); 377 if (field != null) 378 { 379 field.accept(this, memberVisitor); 380 } 381 } 382 383 384 public void methodsAccept(MemberVisitor memberVisitor) 385 { 386 for (int index = 0; index < u2methodsCount; index++) 387 { 388 methods[index].accept(this, memberVisitor); 389 } 390 } 391 392 393 public void methodAccept(String name, String descriptor, MemberVisitor memberVisitor) 394 { 395 Method method = findMethod(name, descriptor); 396 if (method != null) 397 { 398 method.accept(this, memberVisitor); 399 } 400 } 401 402 403 public boolean mayHaveImplementations(Method method) 404 { 405 return 406 (u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 && 407 (method == null || 408 ((method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE | 409 ClassConstants.INTERNAL_ACC_STATIC | 410 ClassConstants.INTERNAL_ACC_FINAL)) == 0 && 411 !method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))); 412 } 413 414 415 private boolean isSpecial(Method method) 416 { 417 return 418 (method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE | 419 ClassConstants.INTERNAL_ACC_STATIC)) != 0 || 420 method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); 421 } 422 423 424 public void methodImplementationsAccept(Method method, 425 boolean visitThisMethod, 426 MemberVisitor memberVisitor) 427 { 428 methodImplementationsAccept(method.getName(this), 429 method.getDescriptor(this), 430 method, 431 visitThisMethod, 432 true, 433 true, 434 true, 435 memberVisitor); 436 } 437 438 439 public void methodImplementationsAccept(String name, 440 String descriptor, 441 boolean visitThisMethod, 442 MemberVisitor memberVisitor) 443 { 444 methodImplementationsAccept(name, 445 descriptor, 446 visitThisMethod, 447 true, 448 true, 449 true, 450 memberVisitor); 451 } 452 453 454 public void methodImplementationsAccept(String name, 455 String descriptor, 456 boolean visitThisMethod, 457 boolean visitSpecialMethods, 458 boolean visitSuperMethods, 459 boolean visitOverridingMethods, 460 MemberVisitor memberVisitor) 461 { 462 methodImplementationsAccept(name, 463 descriptor, 464 findMethod(name, descriptor), 465 visitThisMethod, 466 visitSpecialMethods, 467 visitSuperMethods, 468 visitOverridingMethods, 469 memberVisitor); 470 } 471 472 473 public void methodImplementationsAccept(String name, 474 String descriptor, 475 Method method, 476 boolean visitThisMethod, 477 boolean visitSpecialMethods, 478 boolean visitSuperMethods, 479 boolean visitOverridingMethods, 480 MemberVisitor memberVisitor) 481 { 482 if (method != null) 484 { 485 if (isSpecial(method)) 487 { 488 if (visitSpecialMethods) 490 { 491 method.accept(this, memberVisitor); 492 493 return; 495 } 496 } 497 else 498 { 499 if (visitThisMethod) 501 { 502 method.accept(this, memberVisitor); 503 } 504 505 if (!mayHaveImplementations(method)) 508 { 509 visitOverridingMethods = false; 510 } 511 512 if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_ABSTRACT) == 0) 515 { 516 visitSuperMethods = false; 517 } 518 } 519 } 520 521 if (visitOverridingMethods) 523 { 524 if (subClasses != null) 526 { 527 for (int index = 0; index < subClasses.length; index++) 528 { 529 Clazz subClass = subClasses[index]; 530 subClass.methodImplementationsAccept(name, 531 descriptor, 532 true, 533 false, 534 visitSuperMethods, 535 true, 536 memberVisitor); 537 } 538 } 539 540 if ((u2accessFlags & (ClassConstants.INTERNAL_ACC_INTERFACE | 543 ClassConstants.INTERNAL_ACC_ABSTRACT)) != 0) 544 { 545 visitSuperMethods = false; 546 } 547 } 548 549 if (visitSuperMethods) 551 { 552 Clazz superClass = getSuperClass(); 553 if (superClass != null) 554 { 555 superClass.methodImplementationsAccept(name, 556 descriptor, 557 true, 558 false, 559 true, 560 false, 561 memberVisitor); 562 } 563 } 564 } 565 566 567 public void attributesAccept(AttributeVisitor attributeVisitor) 568 { 569 for (int index = 0; index < u2attributesCount; index++) 570 { 571 attributes[index].accept(this, attributeVisitor); 572 } 573 } 574 575 576 578 public Object getVisitorInfo() 579 { 580 return visitorInfo; 581 } 582 583 public void setVisitorInfo(Object visitorInfo) 584 { 585 this.visitorInfo = visitorInfo; 586 } 587 } 588 | Popular Tags |