<s> package org . eclipse . jdt . internal . compiler . classfmt ; import java . io . File ; import java . io . IOException ; import java . io . InputStream ; 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 . TagBits ; import org . eclipse . jdt . internal . compiler . lookup . TypeIds ; import org . eclipse . jdt . internal . compiler . util . Util ; public class ClassFileReader extends ClassFileStruct implements IBinaryType { private int accessFlags ; private char [ ] classFileName ; private char [ ] className ; private int classNameIndex ; private int constantPoolCount ; private AnnotationInfo [ ] annotations ; private FieldInfo [ ] fields ; private int fieldsCount ; private InnerClassInfo innerInfo ; private int innerInfoIndex ; private InnerClassInfo [ ] innerInfos ; private char [ ] [ ] interfaceNames ; private int interfacesCount ; private MethodInfo [ ] methods ; private int methodsCount ; private char [ ] signature ; private char [ ] sourceName ; private char [ ] sourceFileName ; private char [ ] superclassName ; private long tagBits ; private long version ; private char [ ] enclosingTypeName ; private char [ ] [ ] [ ] missingTypeNames ; private int enclosingNameAndTypeIndex ; private char [ ] enclosingMethod ; private static String printTypeModifiers ( int modifiers ) { java . io . ByteArrayOutputStream out = new java . io . ByteArrayOutputStream ( ) ; java . io . PrintWriter print = new java . io . PrintWriter ( out ) ; 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 ( ) ; return out . toString ( ) ; } 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 ( InputStream stream , String fileName ) throws ClassFormatException , IOException { return read ( stream , fileName , false ) ; } public static ClassFileReader read ( InputStream stream , String fileName , boolean fullyInitialize ) throws ClassFormatException , IOException { byte classFileBytes [ ] = Util . getInputStreamAsByteArray ( stream , - 1 ) ; ClassFileReader classFileReader = new ClassFileReader ( classFileBytes , fileName . toCharArray ( ) ) ; if ( fullyInitialize ) { classFileReader . initialize ( ) ; } return classFileReader ; } 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 ; } 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 ClassFileReader ( byte classFileBytes [ ] , char [ ] fileName ) throws ClassFormatException { this ( classFileBytes , fileName , false ) ; } public ClassFileReader ( byte [ ] classFileBytes , char [ ] fileName , boolean fullyInitialize ) throws ClassFormatException { super ( classFileBytes , null , 0 ) ; this . classFileName = fileName ; int readOffset = 10 ; try { this . version = ( ( long ) u2At ( 6 ) << 16 ) + u2At ( 4 ) ; this . constantPoolCount = u2At ( 8 ) ; this . constantPoolOffsets = new int [ this . constantPoolCount ] ; for ( int i = 1 ; i < this . constantPoolCount ; i ++ ) { int tag = u1At ( readOffset ) ; switch ( tag ) { case ClassFileConstants . Utf8Tag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += u2At ( readOffset + 1 ) ; readOffset += ClassFileConstants . ConstantUtf8FixedSize ; break ; case ClassFileConstants . IntegerTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantIntegerFixedSize ; break ; case ClassFileConstants . FloatTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantFloatFixedSize ; break ; case ClassFileConstants . LongTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantLongFixedSize ; i ++ ; break ; case ClassFileConstants . DoubleTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantDoubleFixedSize ; i ++ ; break ; case ClassFileConstants . ClassTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantClassFixedSize ; break ; case ClassFileConstants . StringTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantStringFixedSize ; break ; case ClassFileConstants . FieldRefTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantFieldRefFixedSize ; break ; case ClassFileConstants . MethodRefTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantMethodRefFixedSize ; break ; case ClassFileConstants . InterfaceMethodRefTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantInterfaceMethodRefFixedSize ; break ; case ClassFileConstants . NameAndTypeTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantNameAndTypeFixedSize ; break ; case ClassFileConstants . MethodHandleTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantMethodHandleFixedSize ; break ; case ClassFileConstants . MethodTypeTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantMethodTypeFixedSize ; break ; case ClassFileConstants . InvokeDynamicTag : this . constantPoolOffsets [ i ] = readOffset ; readOffset += ClassFileConstants . ConstantInvokeDynamicFixedSize ; break ; } } this . accessFlags = u2At ( readOffset ) ; readOffset += 2 ; this . classNameIndex = u2At ( readOffset ) ; this . className = getConstantClassNameAt ( this . classNameIndex ) ; readOffset += 2 ; int superclassNameIndex = u2At ( readOffset ) ; readOffset += 2 ; if ( superclassNameIndex != 0 ) { this . superclassName = getConstantClassNameAt ( superclassNameIndex ) ; } 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 ; } } 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 = FieldInfo . createField ( this . reference , this . constantPoolOffsets , readOffset ) ; this . fields [ i ] = field ; readOffset += field . sizeInBytes ( ) ; } } this . methodsCount = u2At ( readOffset ) ; readOffset += 2 ; if ( this . methodsCount != 0 ) { this . methods = new MethodInfo [ this . methodsCount ] ; boolean isAnnotationType = ( this . accessFlags & ClassFileConstants . AccAnnotation ) != 0 ; for ( int i = 0 ; i < this . methodsCount ; i ++ ) { this . methods [ i ] = isAnnotationType ? AnnotationMethodInfo . createAnnotationMethod ( this . reference , this . constantPoolOffsets , readOffset ) : MethodInfo . createMethod ( this . reference , this . constantPoolOffsets , readOffset ) ; readOffset += this . methods [ i ] . sizeInBytes ( ) ; } } 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 ( attributeName . length == 0 ) { readOffset += ( 6 + u4At ( readOffset + 2 ) ) ; continue ; } switch ( attributeName [ 0 ] ) { case 'E' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . EnclosingMethodName ) ) { utf8Offset = this . constantPoolOffsets [ u2At ( this . constantPoolOffsets [ u2At ( readOffset + 6 ) ] + 1 ) ] ; this . enclosingTypeName = utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ; this . enclosingNameAndTypeIndex = u2At ( readOffset + 8 ) ; } break ; case 'D' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . DeprecatedName ) ) { this . accessFlags |= ClassFileConstants . AccDeprecated ; } break ; case 'I' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . 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 ( this . reference , this . constantPoolOffsets , innerOffset ) ; if ( this . classNameIndex == this . innerInfos [ j ] . innerClassNameIndex ) { this . innerInfo = this . innerInfos [ j ] ; this . innerInfoIndex = j ; } innerOffset += 8 ; } if ( this . innerInfo != null ) { char [ ] enclosingType = this . innerInfo . getEnclosingTypeName ( ) ; if ( enclosingType != null ) { this . enclosingTypeName = enclosingType ; } } } } else if ( CharOperation . equals ( attributeName , AttributeNamesConstants . InconsistentHierarchy ) ) { this . tagBits |= TagBits . HierarchyHasProblems ; } break ; case 'S' : if ( attributeName . length > 2 ) { switch ( attributeName [ 1 ] ) { case 'o' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . SourceName ) ) { utf8Offset = this . constantPoolOffsets [ u2At ( readOffset + 6 ) ] ; this . sourceFileName = utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ; } break ; case 'y' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . SyntheticName ) ) { this . accessFlags |= ClassFileConstants . AccSynthetic ; } break ; case 'i' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . SignatureName ) ) { utf8Offset = this . constantPoolOffsets [ u2At ( readOffset + 6 ) ] ; this . signature = utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ; } } } break ; case 'R' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . RuntimeVisibleAnnotationsName ) ) { decodeAnnotations ( readOffset , true ) ; } else if ( CharOperation . equals ( attributeName , AttributeNamesConstants . RuntimeInvisibleAnnotationsName ) ) { decodeAnnotations ( readOffset , false ) ; } break ; case 'M' : if ( CharOperation . equals ( attributeName , AttributeNamesConstants . MissingTypesName ) ) { int missingTypeOffset = readOffset + 6 ; int numberOfMissingTypes = u2At ( missingTypeOffset ) ; if ( numberOfMissingTypes != 0 ) { this . missingTypeNames = new char [ numberOfMissingTypes ] [ ] [ ] ; missingTypeOffset += 2 ; for ( int j = 0 ; j < numberOfMissingTypes ; j ++ ) { utf8Offset = this . constantPoolOffsets [ u2At ( this . constantPoolOffsets [ u2At ( missingTypeOffset ) ] + 1 ) ] ; char [ ] missingTypeConstantPoolName = utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ; this . missingTypeNames [ j ] = CharOperation . splitOn ( '/' , missingTypeConstantPoolName ) ; missingTypeOffset += 2 ; } } } } readOffset += ( 6 + u4At ( readOffset + 2 ) ) ; } if ( fullyInitialize ) { initialize ( ) ; } } catch ( ClassFormatException e ) { throw e ; } catch ( Exception e ) { throw new ClassFormatException ( ClassFormatException . ErrTruncatedInput , readOffset ) ; } } public int accessFlags ( ) { return this . accessFlags ; } private void decodeAnnotations ( int offset , boolean runtimeVisible ) { int numberOfAnnotations = u2At ( offset + 6 ) ; if ( numberOfAnnotations > 0 ) { int readOffset = offset + 8 ; AnnotationInfo [ ] newInfos = null ; int newInfoCount = 0 ; for ( int i = 0 ; i < numberOfAnnotations ; i ++ ) { AnnotationInfo newInfo = new AnnotationInfo ( this . reference , this . constantPoolOffsets , readOffset , runtimeVisible , false ) ; readOffset += newInfo . readOffset ; long standardTagBits = newInfo . standardAnnotationTagBits ; if ( standardTagBits != 0 ) { this . tagBits |= standardTagBits ; } else { if ( newInfos == null ) newInfos = new AnnotationInfo [ numberOfAnnotations - i ] ; newInfos [ newInfoCount ++ ] = newInfo ; } } if ( newInfos == null ) return ; if ( this . annotations == null ) { if ( newInfoCount != newInfos . length ) System . arraycopy ( newInfos , 0 , newInfos = new AnnotationInfo [ newInfoCount ] , 0 , newInfoCount ) ; this . annotations = newInfos ; } else { int length = this . annotations . length ; AnnotationInfo [ ] temp = new AnnotationInfo [ length + newInfoCount ] ; System . arraycopy ( this . annotations , 0 , temp , 0 , length ) ; System . arraycopy ( newInfos , 0 , temp , length , newInfoCount ) ; this . annotations = temp ; } } } public IBinaryAnnotation [ ] getAnnotations ( ) { return this . annotations ; } private char [ ] getConstantClassNameAt ( int constantPoolIndex ) { int utf8Offset = this . constantPoolOffsets [ u2At ( this . constantPoolOffsets [ constantPoolIndex ] + 1 ) ] ; return utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ; } public int [ ] getConstantPoolOffsets ( ) { return this . constantPoolOffsets ; } public char [ ] getEnclosingMethod ( ) { if ( this . enclosingNameAndTypeIndex <= 0 ) { return null ; } if ( this . enclosingMethod == null ) { StringBuffer buffer = new StringBuffer ( ) ; int nameAndTypeOffset = this . constantPoolOffsets [ this . enclosingNameAndTypeIndex ] ; int utf8Offset = this . constantPoolOffsets [ u2At ( nameAndTypeOffset + 1 ) ] ; buffer . append ( utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ) ; utf8Offset = this . constantPoolOffsets [ u2At ( nameAndTypeOffset + 3 ) ] ; buffer . append ( utf8At ( utf8Offset + 3 , u2At ( utf8Offset + 1 ) ) ) ; this . enclosingMethod = String . valueOf ( buffer ) . toCharArray ( ) ; } return this . enclosingMethod ; } public char [ ] getEnclosingTypeName ( ) { return this . enclosingTypeName ; } public IBinaryField [ ] getFields ( ) { return this . fields ; } public char [ ] getFileName ( ) { return this . classFileName ; } public char [ ] getGenericSignature ( ) { return this . signature ; } public char [ ] getInnerSourceName ( ) { if ( this . innerInfo != null ) return this . innerInfo . getSourceName ( ) ; return null ; } public char [ ] [ ] getInterfaceNames ( ) { return this . interfaceNames ; } public IBinaryNestedType [ ] getMemberTypes ( ) { 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 ; if ( outerClassNameIdx != 0 && innerNameIndex != 0 && outerClassNameIdx == this . classNameIndex && currentInnerInfo . getSourceName ( ) . length != 0 ) { memberTypes [ memberTypeIndex ++ ] = currentInnerInfo ; } } if ( memberTypeIndex == 0 ) return null ; if ( memberTypeIndex != memberTypes . length ) { System . arraycopy ( memberTypes , 0 , ( memberTypes = new IBinaryNestedType [ memberTypeIndex ] ) , 0 , memberTypeIndex ) ; } return memberTypes ; } return null ; } public IBinaryMethod [ ] getMethods ( ) { return this . methods ; } public char [ ] [ ] [ ] getMissingTypeNames ( ) { return this . missingTypeNames ; } public int getModifiers ( ) { int modifiers ; if ( this . innerInfo != null ) { modifiers = this . innerInfo . getModifiers ( ) | ( this . accessFlags & ClassFileConstants . AccDeprecated ) | ( this . accessFlags & ClassFileConstants . AccSynthetic ) ; } else { modifiers = this . accessFlags ; } return modifiers ; } public char [ ] getName ( ) { return this . className ; } public char [ ] getSourceName ( ) { if ( this . sourceName != null ) return this . sourceName ; char [ ] name = getInnerSourceName ( ) ; if ( name == null ) { name = getName ( ) ; int start ; if ( isAnonymous ( ) ) { start = CharOperation . indexOf ( '$' , name , CharOperation . lastIndexOf ( '/' , name ) + 1 ) + 1 ; } else { start = CharOperation . lastIndexOf ( '/' , name ) + 1 ; } if ( start > 0 ) { char [ ] newName = new char [ name . length - start ] ; System . arraycopy ( name , start , newName , 0 , newName . length ) ; name = newName ; } } return this . sourceName = name ; } public char [ ] getSuperclassName ( ) { return this . superclassName ; } public long getTagBits ( ) { return this . tagBits ; } public long getVersion ( ) { return this . version ; } 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 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 ; } public boolean hasStructuralChanges ( byte [ ] newBytes ) { return hasStructuralChanges ( newBytes , true , true ) ; } public boolean hasStructuralChanges ( byte [ ] newBytes , boolean orderRequired , boolean excludesSynthetic ) { try { ClassFileReader newClassFile = new ClassFileReader ( newBytes , this . classFileName ) ; if ( getModifiers ( ) != newClassFile . getModifiers ( ) ) return true ; long OnlyStructuralTagBits = TagBits . AnnotationTargetMASK | TagBits . AnnotationDeprecated | TagBits . AnnotationRetentionMASK | TagBits . HierarchyHasProblems ; if ( ( getTagBits ( ) & OnlyStructuralTagBits ) != ( newClassFile . getTagBits ( ) & OnlyStructuralTagBits ) ) return true ; if ( hasStructuralAnnotationChanges ( getAnnotations ( ) , newClassFile . getAnnotations ( ) ) ) return true ; if ( ! CharOperation . equals ( getGenericSignature ( ) , newClassFile . getGenericSignature ( ) ) ) return true ; if ( ! CharOperation . equals ( getSuperclassName ( ) , newClassFile . getSuperclassName ( ) ) ) return true ; char [ ] [ ] newInterfacesNames = newClassFile . getInterfaceNames ( ) ; if ( this . interfaceNames != newInterfacesNames ) { 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 ; } IBinaryNestedType [ ] currentMemberTypes = getMemberTypes ( ) ; IBinaryNestedType [ ] otherMemberTypes = newClassFile . getMemberTypes ( ) ; if ( currentMemberTypes != otherMemberTypes ) { 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 ; } 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 ; } } 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 ; } } char [ ] [ ] [ ] missingTypes = getMissingTypeNames ( ) ; char [ ] [ ] [ ] newMissingTypes = newClassFile . getMissingTypeNames ( ) ; if ( missingTypes != null ) { if ( newMissingTypes == null ) { return true ; } int length = missingTypes . length ; if ( length != newMissingTypes . length ) { return true ; } for ( int i = 0 ; i < length ; i ++ ) { if ( ! CharOperation . equals ( missingTypes [ i ] , newMissingTypes [ i ] ) ) { return true ; } } } else if ( newMissingTypes != null ) { return true ; } return false ; } catch ( ClassFormatException e ) { return true ; } } private boolean hasStructuralAnnotationChanges ( IBinaryAnnotation [ ] currentAnnotations , IBinaryAnnotation [ ] otherAnnotations ) { if ( currentAnnotations == otherAnnotations ) return false ; int currentAnnotationsLength = currentAnnotations == null ? 0 : currentAnnotations . length ; int otherAnnotationsLength = otherAnnotations == null ? 0 : otherAnnotations . length ; if ( currentAnnotationsLength != otherAnnotationsLength ) return true ; for ( int i = 0 ; i < currentAnnotationsLength ; i ++ ) { if ( ! CharOperation . equals ( currentAnnotations [ i ] . getTypeName ( ) , otherAnnotations [ i ] . getTypeName ( ) ) ) return true ; IBinaryElementValuePair [ ] currentPairs = currentAnnotations [ i ] . getElementValuePairs ( ) ; IBinaryElementValuePair [ ] otherPairs = otherAnnotations [ i ] . getElementValuePairs ( ) ; int currentPairsLength = currentPairs == null ? 0 : currentPairs . length ; int otherPairsLength = otherPairs == null ? 0 : otherPairs . length ; if ( currentPairsLength != otherPairsLength ) return true ; for ( int j = 0 ; j < currentPairsLength ; j ++ ) { if ( ! CharOperation . equals ( currentPairs [ j ] . getName ( ) , otherPairs [ j ] . getName ( ) ) ) return true ; final Object value = currentPairs [ j ] . getValue ( ) ; final Object value2 = otherPairs [ j ] . getValue ( ) ; if ( value instanceof Object [ ] ) { Object [ ] currentValues = ( Object [ ] ) value ; if ( value2 instanceof Object [ ] ) { Object [ ] currentValues2 = ( Object [ ] ) value2 ; final int length = currentValues . length ; if ( length != currentValues2 . length ) { return true ; } for ( int n = 0 ; n < length ; n ++ ) { if ( ! currentValues [ n ] . equals ( currentValues2 [ n ] ) ) { return true ; } } return false ; } return true ; } else if ( ! value . equals ( value2 ) ) { return true ; } } } return false ; } private boolean hasStructuralFieldChanges ( FieldInfo currentFieldInfo , FieldInfo otherFieldInfo ) { if ( ! CharOperation . equals ( currentFieldInfo . getGenericSignature ( ) , otherFieldInfo . getGenericSignature ( ) ) ) return true ; if ( currentFieldInfo . getModifiers ( ) != otherFieldInfo . getModifiers ( ) ) return true ; if ( ( currentFieldInfo . getTagBits ( ) & TagBits . AnnotationDeprecated ) != ( otherFieldInfo . getTagBits ( ) & TagBits . AnnotationDeprecated ) ) return true ; if ( hasStructuralAnnotationChanges ( currentFieldInfo . getAnnotations ( ) , otherFieldInfo . getAnnotations ( ) ) ) 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_JavaLangString : return ! currentConstant . stringValue ( ) . equals ( otherConstant . stringValue ( ) ) ; } } return false ; } private boolean hasStructuralMethodChanges ( MethodInfo currentMethodInfo , MethodInfo otherMethodInfo ) { if ( ! CharOperation . equals ( currentMethodInfo . getGenericSignature ( ) , otherMethodInfo . getGenericSignature ( ) ) ) return true ; if ( currentMethodInfo . getModifiers ( ) != otherMethodInfo . getModifiers ( ) ) return true ; if ( ( currentMethodInfo . getTagBits ( ) & TagBits . AnnotationDeprecated ) != ( otherMethodInfo . getTagBits ( ) & TagBits . AnnotationDeprecated ) ) return true ; if ( hasStructuralAnnotationChanges ( currentMethodInfo . getAnnotations ( ) , otherMethodInfo . getAnnotations ( ) ) ) return true ; int currentAnnotatedParamsCount = currentMethodInfo . getAnnotatedParametersCount ( ) ; int otherAnnotatedParamsCount = otherMethodInfo . getAnnotatedParametersCount ( ) ; if ( currentAnnotatedParamsCount != otherAnnotatedParamsCount ) return true ; for ( int i = 0 ; i < currentAnnotatedParamsCount ; i ++ ) { if ( hasStructuralAnnotationChanges ( currentMethodInfo . getParameterAnnotations ( i ) , otherMethodInfo . getParameterAnnotations ( i ) ) ) return true ; } if ( ! CharOperation . equals ( currentMethodInfo . getSelector ( ) , otherMethodInfo . getSelector ( ) ) ) return true ; if ( ! CharOperation . equals ( currentMethodInfo . getMethodDescriptor ( ) , otherMethodInfo . getMethodDescriptor ( ) ) ) return true ; if ( ! CharOperation . equals ( currentMethodInfo . getGenericSignature ( ) , otherMethodInfo . getGenericSignature ( ) ) ) return true ; char [ ] [ ] currentThrownExceptions = currentMethodInfo . getExceptionTypeNames ( ) ; char [ ] [ ] otherThrownExceptions = otherMethodInfo . getExceptionTypeNames ( ) ; if ( currentThrownExceptions != otherThrownExceptions ) { 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 ; } private void initialize ( ) throws ClassFormatException { try { for ( int i = 0 , max = this . fieldsCount ; i < max ; i ++ ) { this . fields [ i ] . initialize ( ) ; } for ( int i = 0 , max = this . methodsCount ; i < max ; i ++ ) { this . methods [ i ] . initialize ( ) ; } if ( this . innerInfos != null ) { for ( int i = 0 , max = this . innerInfos . length ; i < max ; i ++ ) { this . innerInfos [ i ] . initialize ( ) ; } } if ( this . annotations != null ) { for ( int i = 0 , max = this . annotations . length ; i < max ; i ++ ) { this . annotations [ i ] . initialize ( ) ; } } this . getEnclosingMethod ( ) ; reset ( ) ; } catch ( RuntimeException e ) { ClassFormatException exception = new ClassFormatException ( e , this . classFileName ) ; throw exception ; } } public boolean isAnonymous ( ) { if ( this . innerInfo == null ) return false ; char [ ] innerSourceName = this . innerInfo . getSourceName ( ) ; return ( innerSourceName == null || innerSourceName . length == 0 ) ; } public boolean isBinaryType ( ) { return true ; } public boolean isLocal ( ) { if ( this . innerInfo == null ) return false ; if ( this . innerInfo . getEnclosingTypeName ( ) != null ) return false ; char [ ] innerSourceName = this . innerInfo . getSourceName ( ) ; return ( innerSourceName != null && innerSourceName . length > 0 ) ; } public boolean isMember ( ) { if ( this . innerInfo == null ) return false ; if ( this . innerInfo . getEnclosingTypeName ( ) == null ) return false ; char [ ] innerSourceName = this . innerInfo . getSourceName ( ) ; return ( innerSourceName != null && innerSourceName . length > 0 ) ; } public boolean isNestedType ( ) { return this . innerInfo != null ; } 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 ( getClass ( ) . getName ( ) + "{" ) ; print . println ( "" + new String ( getName ( ) ) ) ; print . println ( "" + ( getSuperclassName ( ) == null ? "null" : new String ( getSuperclassName ( ) ) ) ) ; print . println ( "" + printTypeModifiers ( accessFlags ( ) ) + "(" + accessFlags ( ) + ")" ) ; print . flush ( ) ; return out . toString ( ) ; } } </s>