1 11 package org.eclipse.jdt.internal.compiler.classfmt; 12 13 import java.io.File ; 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 import java.util.Arrays ; 17 18 import org.eclipse.jdt.core.compiler.CharOperation; 19 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; 20 import org.eclipse.jdt.internal.compiler.env.*; 21 import org.eclipse.jdt.internal.compiler.impl.Constant; 22 import org.eclipse.jdt.internal.compiler.lookup.TagBits; 23 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 24 import org.eclipse.jdt.internal.compiler.util.Util; 25 26 public class ClassFileReader extends ClassFileStruct implements IBinaryType { 27 private static String printTypeModifiers(int modifiers) { 28 java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream (); 29 java.io.PrintWriter print = new java.io.PrintWriter (out); 30 31 if ((modifiers & ClassFileConstants.AccPublic) != 0) print.print("public "); if ((modifiers & ClassFileConstants.AccPrivate) != 0) print.print("private "); if ((modifiers & ClassFileConstants.AccFinal) != 0) print.print("final "); if ((modifiers & ClassFileConstants.AccSuper) != 0) print.print("super "); if ((modifiers & ClassFileConstants.AccInterface) != 0) print.print("interface "); if ((modifiers & ClassFileConstants.AccAbstract) != 0) print.print("abstract "); print.flush(); 38 return out.toString(); 39 } 40 public static ClassFileReader read(InputStream stream, String fileName) throws ClassFormatException, IOException { 41 return read(stream, fileName, false); 42 } 43 public static ClassFileReader read(File file) throws ClassFormatException, IOException { 44 return read(file, false); 45 } 46 public static ClassFileReader read(InputStream stream, String fileName, boolean fullyInitialize) throws ClassFormatException, IOException { 47 byte classFileBytes[] = Util.getInputStreamAsByteArray(stream, -1); 48 ClassFileReader classFileReader = new ClassFileReader(classFileBytes, fileName.toCharArray()); 49 if (fullyInitialize) { 50 classFileReader.initialize(); 51 } 52 return classFileReader; 53 } 54 public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException { 55 byte classFileBytes[] = Util.getFileByteContent(file); 56 ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray()); 57 if (fullyInitialize) { 58 classFileReader.initialize(); 59 } 60 return classFileReader; 61 } 62 public static ClassFileReader read( 63 java.util.zip.ZipFile zip, 64 String filename) 65 throws ClassFormatException, java.io.IOException { 66 return read(zip, filename, false); 67 } 68 public static ClassFileReader read( 69 java.util.zip.ZipFile zip, 70 String filename, 71 boolean fullyInitialize) 72 throws ClassFormatException, java.io.IOException { 73 java.util.zip.ZipEntry ze = zip.getEntry(filename); 74 if (ze == null) 75 return null; 76 byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip); 77 ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray()); 78 if (fullyInitialize) { 79 classFileReader.initialize(); 80 } 81 return classFileReader; 82 } 83 public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException { 84 return read(fileName, false); 85 } 86 public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException { 87 return read(new File (fileName), fullyInitialize); 88 } 89 private int accessFlags; 90 private char[] classFileName; 91 private char[] className; 92 private int classNameIndex; 93 private int constantPoolCount; 94 private AnnotationInfo[] annotations; 95 private FieldInfo[] fields; 96 private int fieldsCount; 97 private InnerClassInfo innerInfo; 99 private int innerInfoIndex; 100 private InnerClassInfo[] innerInfos; 101 private char[][] interfaceNames; 102 private int interfacesCount; 103 private MethodInfo[] methods; 104 private int methodsCount; 105 private char[] signature; 106 private char[] sourceName; 107 private char[] sourceFileName; 108 private char[] superclassName; 109 private long tagBits; 110 private long version; 111 112 private char[] enclosingTypeName; 113 114 120 public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException { 121 this(classFileBytes, fileName, false); 122 } 123 124 135 public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInitialize) throws ClassFormatException { 136 super(classFileBytes, null, 0); 141 this.classFileName = fileName; 142 int readOffset = 10; 143 try { 144 this.version = ((long)this.u2At(6) << 16) + this.u2At(4); constantPoolCount = this.u2At(8); 146 this.constantPoolOffsets = new int[constantPoolCount]; 148 for (int i = 1; i < constantPoolCount; i++) { 149 int tag = this.u1At(readOffset); 150 switch (tag) { 151 case ClassFileConstants.Utf8Tag : 152 this.constantPoolOffsets[i] = readOffset; 153 readOffset += u2At(readOffset + 1); 154 readOffset += ClassFileConstants.ConstantUtf8FixedSize; 155 break; 156 case ClassFileConstants.IntegerTag : 157 this.constantPoolOffsets[i] = readOffset; 158 readOffset += ClassFileConstants.ConstantIntegerFixedSize; 159 break; 160 case ClassFileConstants.FloatTag : 161 this.constantPoolOffsets[i] = readOffset; 162 readOffset += ClassFileConstants.ConstantFloatFixedSize; 163 break; 164 case ClassFileConstants.LongTag : 165 this.constantPoolOffsets[i] = readOffset; 166 readOffset += ClassFileConstants.ConstantLongFixedSize; 167 i++; 168 break; 169 case ClassFileConstants.DoubleTag : 170 this.constantPoolOffsets[i] = readOffset; 171 readOffset += ClassFileConstants.ConstantDoubleFixedSize; 172 i++; 173 break; 174 case ClassFileConstants.ClassTag : 175 this.constantPoolOffsets[i] = readOffset; 176 readOffset += ClassFileConstants.ConstantClassFixedSize; 177 break; 178 case ClassFileConstants.StringTag : 179 this.constantPoolOffsets[i] = readOffset; 180 readOffset += ClassFileConstants.ConstantStringFixedSize; 181 break; 182 case ClassFileConstants.FieldRefTag : 183 this.constantPoolOffsets[i] = readOffset; 184 readOffset += ClassFileConstants.ConstantFieldRefFixedSize; 185 break; 186 case ClassFileConstants.MethodRefTag : 187 this.constantPoolOffsets[i] = readOffset; 188 readOffset += ClassFileConstants.ConstantMethodRefFixedSize; 189 break; 190 case ClassFileConstants.InterfaceMethodRefTag : 191 this.constantPoolOffsets[i] = readOffset; 192 readOffset += ClassFileConstants.ConstantInterfaceMethodRefFixedSize; 193 break; 194 case ClassFileConstants.NameAndTypeTag : 195 this.constantPoolOffsets[i] = readOffset; 196 readOffset += ClassFileConstants.ConstantNameAndTypeFixedSize; 197 } 198 } 199 this.accessFlags = u2At(readOffset); 201 readOffset += 2; 202 203 this.classNameIndex = u2At(readOffset); 205 this.className = getConstantClassNameAt(this.classNameIndex); 206 readOffset += 2; 207 208 int superclassNameIndex = u2At(readOffset); 210 readOffset += 2; 211 if (superclassNameIndex != 0) { 214 this.superclassName = getConstantClassNameAt(superclassNameIndex); 215 } 216 217 this.interfacesCount = u2At(readOffset); 219 readOffset += 2; 220 if (this.interfacesCount != 0) { 221 this.interfaceNames = new char[this.interfacesCount][]; 222 for (int i = 0; i < this.interfacesCount; i++) { 223 this.interfaceNames[i] = getConstantClassNameAt(u2At(readOffset)); 224 readOffset += 2; 225 } 226 } 227 this.fieldsCount = u2At(readOffset); 229 readOffset += 2; 230 if (this.fieldsCount != 0) { 231 FieldInfo field; 232 this.fields = new FieldInfo[this.fieldsCount]; 233 for (int i = 0; i < this.fieldsCount; i++) { 234 field = FieldInfo.createField(reference, this.constantPoolOffsets, readOffset); 235 this.fields[i] = field; 236 readOffset += field.sizeInBytes(); 237 } 238 } 239 this.methodsCount = u2At(readOffset); 241 readOffset += 2; 242 if (this.methodsCount != 0) { 243 this.methods = new MethodInfo[this.methodsCount]; 244 boolean isAnnotationType = (this.accessFlags & ClassFileConstants.AccAnnotation) != 0; 245 for (int i = 0; i < this.methodsCount; i++) { 246 this.methods[i] = isAnnotationType 247 ? AnnotationMethodInfo.createAnnotationMethod(reference, this.constantPoolOffsets, readOffset) 248 : MethodInfo.createMethod(reference, this.constantPoolOffsets, readOffset); 249 readOffset += this.methods[i].sizeInBytes(); 250 } 251 } 252 253 int attributesCount = u2At(readOffset); 255 readOffset += 2; 256 257 for (int i = 0; i < attributesCount; i++) { 258 int utf8Offset = this.constantPoolOffsets[u2At(readOffset)]; 259 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 260 if (attributeName.length == 0) { 261 readOffset += (6 + u4At(readOffset + 2)); 262 continue; 263 } 264 switch(attributeName[0] ) { 265 case 'E' : 266 if (CharOperation.equals(attributeName, AttributeNamesConstants.EnclosingMethodName)) { 267 utf8Offset = 268 constantPoolOffsets[u2At(constantPoolOffsets[u2At(readOffset + 6)] - structOffset + 1)] - structOffset; 269 this.enclosingTypeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 270 } 271 break; 272 case 'D' : 273 if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName)) { 274 this.accessFlags |= ClassFileConstants.AccDeprecated; 275 } 276 break; 277 case 'I' : 278 if (CharOperation.equals(attributeName, AttributeNamesConstants.InnerClassName)) { 279 int innerOffset = readOffset + 6; 280 int number_of_classes = u2At(innerOffset); 281 if (number_of_classes != 0) { 282 innerOffset+= 2; 283 this.innerInfos = new InnerClassInfo[number_of_classes]; 284 for (int j = 0; j < number_of_classes; j++) { 285 this.innerInfos[j] = 286 new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset); 287 if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) { 288 this.innerInfo = this.innerInfos[j]; 289 this.innerInfoIndex = j; 290 } 291 innerOffset += 8; 292 } 293 if (this.innerInfo != null) { 294 char[] enclosingType = this.innerInfo.getEnclosingTypeName(); 295 if (enclosingType != null) { 296 this.enclosingTypeName = enclosingType; 297 } 298 } 299 } 300 } else if (CharOperation.equals(attributeName, AttributeNamesConstants.InconsistentHierarchy)) { 301 this.tagBits |= TagBits.HasInconsistentHierarchy; 302 } 303 break; 304 case 'S' : 305 if (attributeName.length > 2) { 306 switch(attributeName[1]) { 307 case 'o' : 308 if (CharOperation.equals(attributeName, AttributeNamesConstants.SourceName)) { 309 utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; 310 this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 311 } 312 break; 313 case 'y' : 314 if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) { 315 this.accessFlags |= ClassFileConstants.AccSynthetic; 316 } 317 break; 318 case 'i' : 319 if (CharOperation.equals(attributeName, AttributeNamesConstants.SignatureName)) { 320 utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; 321 this.signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 322 } 323 } 324 } 325 break; 326 case 'R' : 327 if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { 328 decodeAnnotations(readOffset, true); 329 } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { 330 decodeAnnotations(readOffset, false); 331 } 332 break; 333 } 334 readOffset += (6 + u4At(readOffset + 2)); 335 } 336 if (fullyInitialize) { 337 this.initialize(); 338 } 339 } catch(ClassFormatException e) { 340 throw e; 341 } catch (Exception e) { 342 throw new ClassFormatException( 343 ClassFormatException.ErrTruncatedInput, 344 readOffset); 345 } 346 } 347 348 353 public int accessFlags() { 354 return this.accessFlags; 355 } 356 private void decodeAnnotations(int offset, boolean runtimeVisible) { 357 int numberOfAnnotations = u2At(offset + 6); 358 if (numberOfAnnotations > 0) { 359 int readOffset = offset + 8; 360 AnnotationInfo[] newInfos = null; 361 int newInfoCount = 0; 362 for (int i = 0; i < numberOfAnnotations; i++) { 363 AnnotationInfo newInfo = new AnnotationInfo(this.reference, this.constantPoolOffsets, readOffset, runtimeVisible, false); 365 readOffset += newInfo.readOffset; 366 long standardTagBits = newInfo.standardAnnotationTagBits; 367 if (standardTagBits != 0) { 368 this.tagBits |= standardTagBits; 369 } else { 370 if (newInfos == null) 371 newInfos = new AnnotationInfo[numberOfAnnotations - i]; 372 newInfos[newInfoCount++] = newInfo; 373 } 374 } 375 if (newInfos == null) 376 return; 378 if (this.annotations == null) { 379 if (newInfoCount != newInfos.length) 380 System.arraycopy(newInfos, 0, newInfos = new AnnotationInfo[newInfoCount], 0, newInfoCount); 381 this.annotations = newInfos; 382 } else { 383 int length = this.annotations.length; 384 AnnotationInfo[] temp = new AnnotationInfo[length + newInfoCount]; 385 System.arraycopy(this.annotations, 0, temp, 0, length); 386 System.arraycopy(newInfos, 0, temp, length, newInfoCount); 387 this.annotations = temp; 388 } 389 } 390 } 391 398 private char[] getConstantClassNameAt(int constantPoolIndex) { 399 int utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[constantPoolIndex] + 1)]; 400 return utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 401 } 402 407 public int[] getConstantPoolOffsets() { 408 return this.constantPoolOffsets; 409 } 410 414 public char[] getEnclosingTypeName() { 415 return this.enclosingTypeName; 416 } 417 421 public IBinaryField[] getFields() { 422 return this.fields; 423 } 424 427 public char[] getFileName() { 428 return this.classFileName; 429 } 430 public char[] getGenericSignature() { 431 return this.signature; 432 } 433 454 public char[] getInnerSourceName() { 455 if (this.innerInfo != null) 456 return this.innerInfo.getSourceName(); 457 return null; 458 } 459 467 public char[][] getInterfaceNames() { 468 return this.interfaceNames; 469 } 470 471 479 public IBinaryNestedType[] getMemberTypes() { 480 if (this.innerInfos == null) return null; 482 483 int length = this.innerInfos.length; 484 int startingIndex = this.innerInfo != null ? this.innerInfoIndex + 1 : 0; 485 if (length != startingIndex) { 486 IBinaryNestedType[] memberTypes = 487 new IBinaryNestedType[length - this.innerInfoIndex]; 488 int memberTypeIndex = 0; 489 for (int i = startingIndex; i < length; i++) { 490 InnerClassInfo currentInnerInfo = this.innerInfos[i]; 491 int outerClassNameIdx = currentInnerInfo.outerClassNameIndex; 492 int innerNameIndex = currentInnerInfo.innerNameIndex; 493 506 if (outerClassNameIdx != 0 507 && innerNameIndex != 0 508 && outerClassNameIdx == this.classNameIndex 509 && currentInnerInfo.getSourceName().length != 0) { 510 memberTypes[memberTypeIndex++] = currentInnerInfo; 511 } 512 } 513 if (memberTypeIndex == 0) return null; 514 if (memberTypeIndex != memberTypes.length) { 515 System.arraycopy( 518 memberTypes, 519 0, 520 (memberTypes = new IBinaryNestedType[memberTypeIndex]), 521 0, 522 memberTypeIndex); 523 } 524 return memberTypes; 525 } 526 return null; 527 } 528 532 public IBinaryMethod[] getMethods() { 533 return this.methods; 534 } 535 538 public IBinaryAnnotation[] getAnnotations() { 539 return this.annotations; 540 } 541 547 public int getModifiers() { 548 if (this.innerInfo != null) { 549 return this.innerInfo.getModifiers() | (this.accessFlags & ClassFileConstants.AccDeprecated); 550 } 551 return this.accessFlags; 552 } 553 560 public char[] getName() { 561 return this.className; 562 } 563 public char[] getSourceName() { 564 if (this.sourceName != null) 565 return this.sourceName; 566 567 char[] name = getInnerSourceName(); if (name == null) { 569 name = getName(); int start; 571 if (isAnonymous()) { 572 start = CharOperation.indexOf('$', name, CharOperation.lastIndexOf('/', name) + 1) + 1; 573 } else { 574 start = CharOperation.lastIndexOf('/', name) + 1; 575 } 576 if (start > 0) { 577 char[] newName = new char[name.length - start]; 578 System.arraycopy(name, start, newName, 0, newName.length); 579 name = newName; 580 } 581 } 582 return this.sourceName = name; 583 } 584 592 public char[] getSuperclassName() { 593 return this.superclassName; 594 } 595 public long getTagBits() { 596 return this.tagBits; 597 } 598 603 public long getVersion() { 604 return this.version; 605 } 606 private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) { 607 int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length; 608 int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length; 609 int index1 = 0; 610 int index2 = 0; 611 612 end : while (index1 < length1 && index2 < length2) { 613 while (currentFieldInfos[index1].isSynthetic()) { 614 if (++index1 >= length1) break end; 615 } 616 while (otherFieldInfos[index2].isSynthetic()) { 617 if (++index2 >= length2) break end; 618 } 619 if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++])) 620 return true; 621 } 622 623 while (index1 < length1) { 624 if (!currentFieldInfos[index1++].isSynthetic()) return true; 625 } 626 while (index2 < length2) { 627 if (!otherFieldInfos[index2++].isSynthetic()) return true; 628 } 629 return false; 630 } 631 private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) { 632 int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length; 633 int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length; 634 int index1 = 0; 635 int index2 = 0; 636 637 MethodInfo m; 638 end : while (index1 < length1 && index2 < length2) { 639 while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) { 640 if (++index1 >= length1) break end; 641 } 642 while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) { 643 if (++index2 >= length2) break end; 644 } 645 if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++])) 646 return true; 647 } 648 649 while (index1 < length1) { 650 if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true; 651 } 652 while (index2 < length2) { 653 if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true; 654 } 655 return false; 656 } 657 672 public boolean hasStructuralChanges(byte[] newBytes) { 673 return hasStructuralChanges(newBytes, true, true); 674 } 675 691 public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, boolean excludesSynthetic) { 692 try { 693 ClassFileReader newClassFile = 694 new ClassFileReader(newBytes, this.classFileName); 695 if (this.getModifiers() != newClassFile.getModifiers()) 698 return true; 699 700 long OnlyStructuralTagBits = TagBits.AnnotationTargetMASK | TagBits.AnnotationDeprecated | TagBits.AnnotationRetentionMASK | TagBits.HasInconsistentHierarchy; 707 if ((this.getTagBits() & OnlyStructuralTagBits) != (newClassFile.getTagBits() & OnlyStructuralTagBits)) 709 return true; 710 711 if (!CharOperation.equals(this.getGenericSignature(), newClassFile.getGenericSignature())) 713 return true; 714 if (!CharOperation.equals(this.getSuperclassName(), newClassFile.getSuperclassName())) 716 return true; 717 char[][] newInterfacesNames = newClassFile.getInterfaceNames(); 719 if (this.interfaceNames != newInterfacesNames) { int newInterfacesLength = newInterfacesNames == null ? 0 : newInterfacesNames.length; 721 if (newInterfacesLength != this.interfacesCount) 722 return true; 723 for (int i = 0, max = this.interfacesCount; i < max; i++) 724 if (!CharOperation.equals(this.interfaceNames[i], newInterfacesNames[i])) 725 return true; 726 } 727 728 IBinaryNestedType[] currentMemberTypes = this.getMemberTypes(); 730 IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes(); 731 if (currentMemberTypes != otherMemberTypes) { int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length; 733 int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length; 734 if (currentMemberTypeLength != otherMemberTypeLength) 735 return true; 736 for (int i = 0; i < currentMemberTypeLength; i++) 737 if (!CharOperation.equals(currentMemberTypes[i].getName(), otherMemberTypes[i].getName()) 738 || currentMemberTypes[i].getModifiers() != otherMemberTypes[i].getModifiers()) 739 return true; 740 } 741 742 FieldInfo[] otherFieldInfos = (FieldInfo[]) newClassFile.getFields(); 744 int otherFieldInfosLength = otherFieldInfos == null ? 0 : otherFieldInfos.length; 745 boolean compareFields = true; 746 if (this.fieldsCount == otherFieldInfosLength) { 747 int i = 0; 748 for (; i < this.fieldsCount; i++) 749 if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) break; 750 if ((compareFields = i != this.fieldsCount) && !orderRequired && !excludesSynthetic) 751 return true; 752 } 753 if (compareFields) { 754 if (this.fieldsCount != otherFieldInfosLength && !excludesSynthetic) 755 return true; 756 if (orderRequired) { 757 if (this.fieldsCount != 0) 758 Arrays.sort(this.fields); 759 if (otherFieldInfosLength != 0) 760 Arrays.sort(otherFieldInfos); 761 } 762 if (excludesSynthetic) { 763 if (hasNonSyntheticFieldChanges(this.fields, otherFieldInfos)) 764 return true; 765 } else { 766 for (int i = 0; i < this.fieldsCount; i++) 767 if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) 768 return true; 769 } 770 } 771 772 MethodInfo[] otherMethodInfos = (MethodInfo[]) newClassFile.getMethods(); 774 int otherMethodInfosLength = otherMethodInfos == null ? 0 : otherMethodInfos.length; 775 boolean compareMethods = true; 776 if (this.methodsCount == otherMethodInfosLength) { 777 int i = 0; 778 for (; i < this.methodsCount; i++) 779 if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) break; 780 if ((compareMethods = i != this.methodsCount) && !orderRequired && !excludesSynthetic) 781 return true; 782 } 783 if (compareMethods) { 784 if (this.methodsCount != otherMethodInfosLength && !excludesSynthetic) 785 return true; 786 if (orderRequired) { 787 if (this.methodsCount != 0) 788 Arrays.sort(this.methods); 789 if (otherMethodInfosLength != 0) 790 Arrays.sort(otherMethodInfos); 791 } 792 if (excludesSynthetic) { 793 if (hasNonSyntheticMethodChanges(this.methods, otherMethodInfos)) 794 return true; 795 } else { 796 for (int i = 0; i < this.methodsCount; i++) 797 if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) 798 return true; 799 } 800 } 801 802 return false; 803 } catch (ClassFormatException e) { 804 return true; 805 } 806 } 807 private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo otherFieldInfo) { 808 if (!CharOperation.equals(currentFieldInfo.getGenericSignature(), otherFieldInfo.getGenericSignature())) 810 return true; 811 if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers()) 812 return true; 813 if ((currentFieldInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherFieldInfo.getTagBits() & TagBits.AnnotationDeprecated)) 814 return true; 815 if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName())) 816 return true; 817 if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName())) 818 return true; 819 if (currentFieldInfo.hasConstant() != otherFieldInfo.hasConstant()) 820 return true; 821 if (currentFieldInfo.hasConstant()) { 822 Constant currentConstant = currentFieldInfo.getConstant(); 823 Constant otherConstant = otherFieldInfo.getConstant(); 824 if (currentConstant.typeID() != otherConstant.typeID()) 825 return true; 826 if (!currentConstant.getClass().equals(otherConstant.getClass())) 827 return true; 828 switch (currentConstant.typeID()) { 829 case TypeIds.T_int : 830 return currentConstant.intValue() != otherConstant.intValue(); 831 case TypeIds.T_byte : 832 return currentConstant.byteValue() != otherConstant.byteValue(); 833 case TypeIds.T_short : 834 return currentConstant.shortValue() != otherConstant.shortValue(); 835 case TypeIds.T_char : 836 return currentConstant.charValue() != otherConstant.charValue(); 837 case TypeIds.T_long : 838 return currentConstant.longValue() != otherConstant.longValue(); 839 case TypeIds.T_float : 840 return currentConstant.floatValue() != otherConstant.floatValue(); 841 case TypeIds.T_double : 842 return currentConstant.doubleValue() != otherConstant.doubleValue(); 843 case TypeIds.T_boolean : 844 return currentConstant.booleanValue() != otherConstant.booleanValue(); 845 case TypeIds.T_JavaLangString : 846 return !currentConstant.stringValue().equals(otherConstant.stringValue()); 847 } 848 } 849 return false; 850 } 851 private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfo, MethodInfo otherMethodInfo) { 852 if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature())) 854 return true; 855 if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers()) 856 return true; 857 if ((currentMethodInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherMethodInfo.getTagBits() & TagBits.AnnotationDeprecated)) 858 return true; 859 if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector())) 860 return true; 861 if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor())) 862 return true; 863 if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature())) 864 return true; 865 866 char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames(); 867 char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames(); 868 if (currentThrownExceptions != otherThrownExceptions) { int currentThrownExceptionsLength = currentThrownExceptions == null ? 0 : currentThrownExceptions.length; 870 int otherThrownExceptionsLength = otherThrownExceptions == null ? 0 : otherThrownExceptions.length; 871 if (currentThrownExceptionsLength != otherThrownExceptionsLength) 872 return true; 873 for (int k = 0; k < currentThrownExceptionsLength; k++) 874 if (!CharOperation.equals(currentThrownExceptions[k], otherThrownExceptions[k])) 875 return true; 876 } 877 return false; 878 } 879 883 private void initialize() throws ClassFormatException { 884 try { 885 for (int i = 0, max = fieldsCount; i < max; i++) { 886 fields[i].initialize(); 887 } 888 for (int i = 0, max = methodsCount; i < max; i++) { 889 methods[i].initialize(); 890 } 891 if (innerInfos != null) { 892 for (int i = 0, max = innerInfos.length; i < max; i++) { 893 innerInfos[i].initialize(); 894 } 895 } 896 if (annotations != null) { 897 for (int i = 0, max = annotations.length; i < max; i++) { 898 annotations[i].initialize(); 899 } 900 } 901 this.reset(); 902 } catch(RuntimeException e) { 903 ClassFormatException exception = new ClassFormatException(e, this.classFileName); 904 throw exception; 905 } 906 } 907 912 public boolean isAnonymous() { 913 if (this.innerInfo == null) return false; 914 char[] innerSourceName = this.innerInfo.getSourceName(); 915 return (innerSourceName == null || innerSourceName.length == 0); 916 } 917 922 public boolean isBinaryType() { 923 return true; 924 } 925 926 931 public boolean isLocal() { 932 if (this.innerInfo == null) return false; 933 if (this.innerInfo.getEnclosingTypeName() != null) return false; 934 char[] innerSourceName = this.innerInfo.getSourceName(); 935 return (innerSourceName != null && innerSourceName.length > 0); 936 } 937 942 public boolean isMember() { 943 if (this.innerInfo == null) return false; 944 if (this.innerInfo.getEnclosingTypeName() == null) return false; 945 char[] innerSourceName = this.innerInfo.getSourceName(); 946 return (innerSourceName != null && innerSourceName.length > 0); } 948 953 public boolean isNestedType() { 954 return this.innerInfo != null; 955 } 956 961 public char[] sourceFileName() { 962 return this.sourceFileName; 963 } 964 public String toString() { 965 java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream (); 966 java.io.PrintWriter print = new java.io.PrintWriter (out); 967 print.println(this.getClass().getName() + "{"); print.println(" this.className: " + new String (getName())); print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String (getSuperclassName()))); print.println(" access_flags: " + printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); print.flush(); 972 return out.toString(); 973 } 974 975 1022} 1023 | Popular Tags |