X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fclassfmt%2FClassFileReader.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fclassfmt%2FClassFileReader.java;h=0000000000000000000000000000000000000000;hb=6f0cd02d46e011bd5599e1b7fefc6159cb811135;hp=6899fa0631d8a4f491fdf55be54c5acc2aa22652;hpb=622d0e5a4b1b35b6918a516a79a0cc22272a919e;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java deleted file mode 100644 index 6899fa0..0000000 --- a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java +++ /dev/null @@ -1,824 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.compiler.classfmt; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; - -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; -import org.eclipse.jdt.internal.compiler.env.*; -import org.eclipse.jdt.internal.compiler.impl.Constant; -import org.eclipse.jdt.internal.compiler.lookup.TypeIds; -import org.eclipse.jdt.internal.compiler.util.Util; - -public class ClassFileReader extends ClassFileStruct implements AttributeNamesConstants, IBinaryType { - private int constantPoolCount; - private int[] constantPoolOffsets; - private long version; - private int accessFlags; - private char[] className; - private char[] superclassName; - private int interfacesCount; - private char[][] interfaceNames; - private int fieldsCount; - private FieldInfo[] fields; - private int methodsCount; - private MethodInfo[] methods; - private InnerClassInfo[] innerInfos; - private char[] sourceFileName; - // initialized in case the .class file is a nested type - private InnerClassInfo innerInfo; - private char[] classFileName; - private int classNameIndex; - private int innerInfoIndex; -/** - * @param classFileBytes byte[] - * Actual bytes of a .class file - * - * @param fileName char[] - * Actual name of the file that contains the bytes, can be null - * - * @param fullyInitialize boolean - * Flag to fully initialize the new object - * @exception ClassFormatException - */ -public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInitialize) throws ClassFormatException { - // This method looks ugly but is actually quite simple, the constantPool is constructed - // in 3 passes. All non-primitive constant pool members that usually refer to other members - // by index are tweaked to have their value in inst vars, this minor cost at read-time makes - // all subsequent uses of the constant pool element faster. - super(classFileBytes, 0); - this.classFileName = fileName; - int readOffset = 10; - try { - this.version = ((long)this.u2At(6) << 16) + this.u2At(4); // major<<16 + minor - constantPoolCount = this.u2At(8); - // Pass #1 - Fill in all primitive constants - this.constantPoolOffsets = new int[constantPoolCount]; - for (int i = 1; i < constantPoolCount; i++) { - int tag = this.u1At(readOffset); - switch (tag) { - case Utf8Tag : - this.constantPoolOffsets[i] = readOffset; - readOffset += u2At(readOffset + 1); - readOffset += ConstantUtf8FixedSize; - break; - case IntegerTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantIntegerFixedSize; - break; - case FloatTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantFloatFixedSize; - break; - case LongTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantLongFixedSize; - i++; - break; - case DoubleTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantDoubleFixedSize; - i++; - break; - case ClassTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantClassFixedSize; - break; - case StringTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantStringFixedSize; - break; - case FieldRefTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantFieldRefFixedSize; - break; - case MethodRefTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantMethodRefFixedSize; - break; - case InterfaceMethodRefTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantInterfaceMethodRefFixedSize; - break; - case NameAndTypeTag : - this.constantPoolOffsets[i] = readOffset; - readOffset += ConstantNameAndTypeFixedSize; - } - } - // Read and validate access flags - this.accessFlags = u2At(readOffset); - readOffset += 2; - - // Read the classname, use exception handlers to catch bad format - this.classNameIndex = u2At(readOffset); - this.className = getConstantClassNameAt(this.classNameIndex); - readOffset += 2; - - // Read the superclass name, can be null for java.lang.Object - int superclassNameIndex = u2At(readOffset); - readOffset += 2; - // if superclassNameIndex is equals to 0 there is no need to set a value for the - // field this.superclassName. null is fine. - if (superclassNameIndex != 0) { - this.superclassName = getConstantClassNameAt(superclassNameIndex); - } - - // Read the interfaces, use exception handlers to catch bad format - this.interfacesCount = u2At(readOffset); - readOffset += 2; - if (this.interfacesCount != 0) { - this.interfaceNames = new char[this.interfacesCount][]; - for (int i = 0; i < this.interfacesCount; i++) { - this.interfaceNames[i] = getConstantClassNameAt(u2At(readOffset)); - readOffset += 2; - } - } - // Read the this.fields, use exception handlers to catch bad format - this.fieldsCount = u2At(readOffset); - readOffset += 2; - if (this.fieldsCount != 0) { - FieldInfo field; - this.fields = new FieldInfo[this.fieldsCount]; - for (int i = 0; i < this.fieldsCount; i++) { - field = new FieldInfo(reference, this.constantPoolOffsets, readOffset); - this.fields[i] = field; - readOffset += field.sizeInBytes(); - } - } - // Read the this.methods - this.methodsCount = u2At(readOffset); - readOffset += 2; - if (this.methodsCount != 0) { - this.methods = new MethodInfo[this.methodsCount]; - MethodInfo method; - for (int i = 0; i < this.methodsCount; i++) { - method = new MethodInfo(reference, this.constantPoolOffsets, readOffset); - this.methods[i] = method; - readOffset += method.sizeInBytes(); - } - } - - // Read the attributes - int attributesCount = u2At(readOffset); - readOffset += 2; - - for (int i = 0; i < attributesCount; i++) { - int utf8Offset = this.constantPoolOffsets[u2At(readOffset)]; - char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); - if (CharOperation.equals(attributeName, DeprecatedName)) { - this.accessFlags |= AccDeprecated; - } else { - if (CharOperation.equals(attributeName, InnerClassName)) { - int innerOffset = readOffset + 6; - int number_of_classes = u2At(innerOffset); - if (number_of_classes != 0) { - innerOffset+= 2; - this.innerInfos = new InnerClassInfo[number_of_classes]; - for (int j = 0; j < number_of_classes; j++) { - this.innerInfos[j] = - new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset); - if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) { - this.innerInfo = this.innerInfos[j]; - this.innerInfoIndex = j; - } - innerOffset += 8; - } - } - } else { - if (CharOperation.equals(attributeName, SourceName)) { - utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; - this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); - } else { - if (CharOperation.equals(attributeName, SyntheticName)) { - this.accessFlags |= AccSynthetic; - } - } - } - } - readOffset += (6 + u4At(readOffset + 2)); - } - if (fullyInitialize) { - this.initialize(); - } - } catch(ClassFormatException e) { - throw e; - } catch (Exception e) { - throw new ClassFormatException( - ClassFormatException.ErrTruncatedInput, - readOffset); - } -} - -/** - * @param classFileBytes Actual bytes of a .class file - * @param fileName Actual name of the file that contains the bytes, can be null - * - * @exception ClassFormatException - */ -public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException { - this(classFileBytes, fileName, false); -} - -/** - * Answer the receiver's access flags. The value of the access_flags - * item is a mask of modifiers used with class and interface declarations. - * @return int - */ -public int accessFlags() { - return this.accessFlags; -} -/** - * Answer the char array that corresponds to the class name of the constant class. - * constantPoolIndex is the index in the constant pool that is a constant class entry. - * - * @param constantPoolIndex int - * @return char[] - */ -private char[] getConstantClassNameAt(int constantPoolIndex) { - int utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[constantPoolIndex] + 1)]; - return utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); -} -/** - * Answer the int array that corresponds to all the offsets of each entry in the constant pool - * - * @return int[] - */ -public int[] getConstantPoolOffsets() { - return this.constantPoolOffsets; -} -/* - * Answer the resolved compoundName of the enclosing type - * or null if the receiver is a top level type. - */ -public char[] getEnclosingTypeName() { - if (this.innerInfo != null && !this.isAnonymous()) { - return this.innerInfo.getEnclosingTypeName(); - } - return null; -} -/** - * Answer the receiver's this.fields or null if the array is empty. - * @return org.eclipse.jdt.internal.compiler.api.IBinaryField[] - */ -public IBinaryField[] getFields() { - return this.fields; -} -/** - * Answer the file name which defines the type. - * The format is unspecified. - */ -public char[] getFileName() { - return this.classFileName; -} -/** - * Answer the source name if the receiver is a inner type. Return null if it is an anonymous class or if the receiver is a top-level class. - * e.g. - * public class A { - * public class B { - * } - * public void foo() { - * class C {} - * } - * public Runnable bar() { - * return new Runnable() { - * public void run() {} - * }; - * } - * } - * It returns {'B'} for the member A$B - * It returns null for A - * It returns {'C'} for the local class A$1$C - * It returns null for the anonymous A$1 - * @return char[] - */ -public char[] getInnerSourceName() { - if (this.innerInfo != null) - return this.innerInfo.getSourceName(); - return null; -} -/** - * Answer the resolved names of the receiver's interfaces in the - * class file format as specified in section 4.2 of the Java 2 VM spec - * or null if the array is empty. - * - * For example, java.lang.String is java/lang/String. - * @return char[][] - */ -public char[][] getInterfaceNames() { - return this.interfaceNames; -} -/** - * Answer the receiver's nested types or null if the array is empty. - * - * This nested type info is extracted from the inner class attributes. - * Ask the name environment to find a member type using its compound name - * @return org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[] - */ -public IBinaryNestedType[] getMemberTypes() { - // we might have some member types of the current type - if (this.innerInfos == null) return null; - - int length = this.innerInfos.length; - int startingIndex = this.innerInfo != null ? this.innerInfoIndex + 1 : 0; - if (length != startingIndex) { - IBinaryNestedType[] memberTypes = - new IBinaryNestedType[length - this.innerInfoIndex]; - int memberTypeIndex = 0; - for (int i = startingIndex; i < length; i++) { - InnerClassInfo currentInnerInfo = this.innerInfos[i]; - int outerClassNameIdx = currentInnerInfo.outerClassNameIndex; - int innerNameIndex = currentInnerInfo.innerNameIndex; - /* - * Checking that outerClassNameIDx is different from 0 should be enough to determine if an inner class - * attribute entry is a member class, but due to the bug: - * http://dev.eclipse.org/bugs/show_bug.cgi?id=14592 - * we needed to add an extra check. So we check that innerNameIndex is different from 0 as well. - * - * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49879 - * From JavaMail 1.2, the class javax.mail.Folder contains an anonymous class in the - * terminateQueue() method for which the inner attribute is boggus. - * outerClassNameIdx is not 0, innerNameIndex is not 0, but the sourceName length is 0. - * So I added this extra check to filter out this anonymous class from the - * member types. - */ - if (outerClassNameIdx != 0 - && innerNameIndex != 0 - && outerClassNameIdx == this.classNameIndex - && currentInnerInfo.getSourceName().length != 0) { - memberTypes[memberTypeIndex++] = currentInnerInfo; - } - } - if (memberTypeIndex == 0) return null; - if (memberTypeIndex != memberTypes.length) { - // we need to resize the memberTypes array. Some local or anonymous classes - // are present in the current class. - System.arraycopy( - memberTypes, - 0, - (memberTypes = new IBinaryNestedType[memberTypeIndex]), - 0, - memberTypeIndex); - } - return memberTypes; - } - return null; -} -/** - * Answer the receiver's this.methods or null if the array is empty. - * @return org.eclipse.jdt.internal.compiler.api.env.IBinaryMethod[] - */ -public IBinaryMethod[] getMethods() { - return this.methods; -} -/** - * Answer an int whose bits are set according the access constants - * defined by the VM spec. - * Set the AccDeprecated and AccSynthetic bits if necessary - * @return int - */ -public int getModifiers() { - if (this.innerInfo != null) { - if ((this.accessFlags & AccDeprecated) != 0) { - return this.innerInfo.getModifiers() | AccDeprecated; - } else { - return this.innerInfo.getModifiers(); - } - } - return this.accessFlags; -} -/** - * Answer the resolved name of the type in the - * class file format as specified in section 4.2 of the Java 2 VM spec. - * - * For example, java.lang.String is java/lang/String. - * @return char[] - */ -public char[] getName() { - return this.className; -} -/** - * Answer the resolved name of the receiver's superclass in the - * class file format as specified in section 4.2 of the Java 2 VM spec - * or null if it does not have one. - * - * For example, java.lang.String is java/lang/String. - * @return char[] - */ -public char[] getSuperclassName() { - return this.superclassName; -} -/** - * Answer the major/minor version defined in this class file according to the VM spec. - * as a long: (major<<16)+minor - * @return the major/minor version found - */ -public long getVersion() { - return this.version; -} -/** - * Answer true if the receiver is an anonymous type, false otherwise - * - * @return boolean - */ -public boolean isAnonymous() { - if (this.innerInfo == null) return false; - char[] sourceName = this.innerInfo.getSourceName(); - return (sourceName == null || sourceName.length == 0); -} -/** - * Answer whether the receiver contains the resolved binary form - * or the unresolved source form of the type. - * @return boolean - */ -public boolean isBinaryType() { - return true; -} -/** - * Answer true if the receiver is a class. False otherwise. - * @return boolean - */ -public boolean isClass() { - return (getModifiers() & AccInterface) == 0; -} -/** - * Answer true if the receiver is an interface. False otherwise. - * @return boolean - */ -public boolean isInterface() { - return (getModifiers() & AccInterface) != 0; -} -/** - * Answer true if the receiver is a local type, false otherwise - * - * @return boolean - */ -public boolean isLocal() { - if (this.innerInfo == null) return false; - if (this.innerInfo.getEnclosingTypeName() != null) return false; - char[] sourceName = this.innerInfo.getSourceName(); - return (sourceName != null && sourceName.length > 0); -} -/** - * Answer true if the receiver is a member type, false otherwise - * - * @return boolean - */ -public boolean isMember() { - if (this.innerInfo == null) return false; - if (this.innerInfo.getEnclosingTypeName() == null) return false; - char[] sourceName = this.innerInfo.getSourceName(); - return (sourceName != null && sourceName.length > 0); // protection against ill-formed attributes (67600) -} -/** - * Answer true if the receiver is a nested type, false otherwise - * - * @return boolean - */ -public boolean isNestedType() { - return this.innerInfo != null; -} -public static ClassFileReader read(File file) throws ClassFormatException, IOException { - return read(file, false); -} -public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException { - byte classFileBytes[] = Util.getFileByteContent(file); - ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray()); - if (fullyInitialize) { - classFileReader.initialize(); - } - return classFileReader; -} -public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException { - return read(fileName, false); -} -public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException { - return read(new File(fileName), fullyInitialize); -} -public static ClassFileReader read( - java.util.zip.ZipFile zip, - String filename) - throws ClassFormatException, java.io.IOException { - return read(zip, filename, false); -} -public static ClassFileReader read( - java.util.zip.ZipFile zip, - String filename, - boolean fullyInitialize) - throws ClassFormatException, java.io.IOException { - java.util.zip.ZipEntry ze = zip.getEntry(filename); - if (ze == null) - return null; - byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip); - ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray()); - if (fullyInitialize) { - classFileReader.initialize(); - } - return classFileReader; -} - -/** - * Answer the source file name attribute. Return null if there is no source file attribute for the receiver. - * - * @return char[] - */ -public char[] sourceFileName() { - return this.sourceFileName; -} -public String toString() { - java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); - java.io.PrintWriter print = new java.io.PrintWriter(out); - - print.println(this.getClass().getName() + "{"); //$NON-NLS-1$ - print.println(" this.className: " + new String(getName())); //$NON-NLS-1$ - print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$ - print.println(" access_flags: " + ClassFileStruct.printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$ - - print.flush(); - return out.toString(); -} -/** - * Check if the receiver has structural changes compare to the byte array in argument. - * Structural changes are: - * - modifiers changes for the class, the this.fields or the this.methods - * - signature changes for this.fields or this.methods. - * - changes in the number of this.fields or this.methods - * - changes for field constants - * - changes for thrown exceptions - * - change for the super class or any super interfaces. - * - changes for member types name or modifiers - * If any of these changes occurs, the method returns true. false otherwise. - * The synthetic fields are included and the members are not required to be sorted. - * @param newBytes the bytes of the .class file we want to compare the receiver to - * @return boolean Returns true is there is a structural change between the two .class files, false otherwise - */ -public boolean hasStructuralChanges(byte[] newBytes) { - return hasStructuralChanges(newBytes, true, true); -} -/** - * Check if the receiver has structural changes compare to the byte array in argument. - * Structural changes are: - * - modifiers changes for the class, the this.fields or the this.methods - * - signature changes for this.fields or this.methods. - * - changes in the number of this.fields or this.methods - * - changes for field constants - * - changes for thrown exceptions - * - change for the super class or any super interfaces. - * - changes for member types name or modifiers - * If any of these changes occurs, the method returns true. false otherwise. - * @param newBytes the bytes of the .class file we want to compare the receiver to - * @param orderRequired a boolean indicating whether the members should be sorted or not - * @param excludesSynthetic a boolean indicating whether the synthetic members should be used in the comparison - * @return boolean Returns true is there is a structural change between the two .class files, false otherwise - */ -public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, boolean excludesSynthetic) { - try { - ClassFileReader newClassFile = - new ClassFileReader(newBytes, this.classFileName); - // type level comparison - // modifiers - if (this.getModifiers() != newClassFile.getModifiers()) - return true; - // superclass - if (!CharOperation.equals(this.getSuperclassName(), newClassFile.getSuperclassName())) - return true; - // interfaces - char[][] newInterfacesNames = newClassFile.getInterfaceNames(); - if (this.interfaceNames != newInterfacesNames) { // TypeConstants.NoSuperInterfaces - int newInterfacesLength = newInterfacesNames == null ? 0 : newInterfacesNames.length; - if (newInterfacesLength != this.interfacesCount) - return true; - for (int i = 0, max = this.interfacesCount; i < max; i++) - if (!CharOperation.equals(this.interfaceNames[i], newInterfacesNames[i])) - return true; - } - - // member types - IBinaryNestedType[] currentMemberTypes = this.getMemberTypes(); - IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes(); - if (currentMemberTypes != otherMemberTypes) { // TypeConstants.NoMemberTypes - int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length; - int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length; - if (currentMemberTypeLength != otherMemberTypeLength) - return true; - for (int i = 0; i < currentMemberTypeLength; i++) - if (!CharOperation.equals(currentMemberTypes[i].getName(), otherMemberTypes[i].getName()) - || currentMemberTypes[i].getModifiers() != otherMemberTypes[i].getModifiers()) - return true; - } - - // fields - FieldInfo[] otherFieldInfos = (FieldInfo[]) newClassFile.getFields(); - int otherFieldInfosLength = otherFieldInfos == null ? 0 : otherFieldInfos.length; - boolean compareFields = true; - if (this.fieldsCount == otherFieldInfosLength) { - int i = 0; - for (; i < this.fieldsCount; i++) - if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) break; - if ((compareFields = i != this.fieldsCount) && !orderRequired && !excludesSynthetic) - return true; - } - if (compareFields) { - if (this.fieldsCount != otherFieldInfosLength && !excludesSynthetic) - return true; - if (orderRequired) { - if (this.fieldsCount != 0) - Arrays.sort(this.fields); - if (otherFieldInfosLength != 0) - Arrays.sort(otherFieldInfos); - } - if (excludesSynthetic) { - if (hasNonSyntheticFieldChanges(this.fields, otherFieldInfos)) - return true; - } else { - for (int i = 0; i < this.fieldsCount; i++) - if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) - return true; - } - } - - // methods - MethodInfo[] otherMethodInfos = (MethodInfo[]) newClassFile.getMethods(); - int otherMethodInfosLength = otherMethodInfos == null ? 0 : otherMethodInfos.length; - boolean compareMethods = true; - if (this.methodsCount == otherMethodInfosLength) { - int i = 0; - for (; i < this.methodsCount; i++) - if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) break; - if ((compareMethods = i != this.methodsCount) && !orderRequired && !excludesSynthetic) - return true; - } - if (compareMethods) { - if (this.methodsCount != otherMethodInfosLength && !excludesSynthetic) - return true; - if (orderRequired) { - if (this.methodsCount != 0) - Arrays.sort(this.methods); - if (otherMethodInfosLength != 0) - Arrays.sort(otherMethodInfos); - } - if (excludesSynthetic) { - if (hasNonSyntheticMethodChanges(this.methods, otherMethodInfos)) - return true; - } else { - for (int i = 0; i < this.methodsCount; i++) - if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) - return true; - } - } - - return false; - } catch (ClassFormatException e) { - return true; - } -} -private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) { - int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length; - int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length; - int index1 = 0; - int index2 = 0; - - end : while (index1 < length1 && index2 < length2) { - while (currentFieldInfos[index1].isSynthetic()) { - if (++index1 >= length1) break end; - } - while (otherFieldInfos[index2].isSynthetic()) { - if (++index2 >= length2) break end; - } - if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++])) - return true; - } - - while (index1 < length1) { - if (!currentFieldInfos[index1++].isSynthetic()) return true; - } - while (index2 < length2) { - if (!otherFieldInfos[index2++].isSynthetic()) return true; - } - return false; -} -private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo otherFieldInfo) { - if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers()) - return true; - if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName())) - return true; - if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName())) - return true; - if (currentFieldInfo.hasConstant() != otherFieldInfo.hasConstant()) - return true; - if (currentFieldInfo.hasConstant()) { - Constant currentConstant = currentFieldInfo.getConstant(); - Constant otherConstant = otherFieldInfo.getConstant(); - if (currentConstant.typeID() != otherConstant.typeID()) - return true; - if (!currentConstant.getClass().equals(otherConstant.getClass())) - return true; - switch (currentConstant.typeID()) { - case TypeIds.T_int : - return currentConstant.intValue() != otherConstant.intValue(); - case TypeIds.T_byte : - return currentConstant.byteValue() != otherConstant.byteValue(); - case TypeIds.T_short : - return currentConstant.shortValue() != otherConstant.shortValue(); - case TypeIds.T_char : - return currentConstant.charValue() != otherConstant.charValue(); - case TypeIds.T_long : - return currentConstant.longValue() != otherConstant.longValue(); - case TypeIds.T_float : - return currentConstant.floatValue() != otherConstant.floatValue(); - case TypeIds.T_double : - return currentConstant.doubleValue() != otherConstant.doubleValue(); - case TypeIds.T_boolean : - return currentConstant.booleanValue() != otherConstant.booleanValue(); - case TypeIds.T_String : - return !currentConstant.stringValue().equals(otherConstant.stringValue()); - } - } - return false; -} -private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) { - int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length; - int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length; - int index1 = 0; - int index2 = 0; - - MethodInfo m; - end : while (index1 < length1 && index2 < length2) { - while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) { - if (++index1 >= length1) break end; - } - while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) { - if (++index2 >= length2) break end; - } - if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++])) - return true; - } - - while (index1 < length1) { - if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true; - } - while (index2 < length2) { - if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true; - } - return false; -} -private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfo, MethodInfo otherMethodInfo) { - if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers()) - return true; - if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector())) - return true; - if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor())) - return true; - - char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames(); - char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames(); - if (currentThrownExceptions != otherThrownExceptions) { // TypeConstants.NoExceptions - int currentThrownExceptionsLength = currentThrownExceptions == null ? 0 : currentThrownExceptions.length; - int otherThrownExceptionsLength = otherThrownExceptions == null ? 0 : otherThrownExceptions.length; - if (currentThrownExceptionsLength != otherThrownExceptionsLength) - return true; - for (int k = 0; k < currentThrownExceptionsLength; k++) - if (!CharOperation.equals(currentThrownExceptions[k], otherThrownExceptions[k])) - return true; - } - return false; -} -/** - * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos - * will be therefore fully initialized and we can get rid of the bytes. - */ -private void initialize() throws ClassFormatException { - try { - for (int i = 0, max = fieldsCount; i < max; i++) { - fields[i].initialize(); - } - for (int i = 0, max = methodsCount; i < max; i++) { - methods[i].initialize(); - } - if (innerInfos != null) { - for (int i = 0, max = innerInfos.length; i < max; i++) { - innerInfos[i].initialize(); - } - } - this.reset(); - } catch(RuntimeException e) { - ClassFormatException exception = new ClassFormatException(e, this.classFileName); - throw exception; - } -} -protected void reset() { - this.constantPoolOffsets = null; - super.reset(); -} - -}