@ -168,111 +168,116 @@ public class ClassInfo extends BinaryInfo {
ConstantPool cp ,
ConstantPool cp ,
DataInputStream input ,
DataInputStream input ,
int howMuch ) throws IOException {
int howMuch ) throws IOException {
if ( ( howMuch & KNOWNATTRIBS ) ! = 0 & & name . equals ( "SourceFile" ) ) {
if ( name . equals ( "SourceFile" ) ) {
if ( length ! = 2 )
if ( ( howMuch & KNOWNATTRIBS ) ! = 0 ) {
throw new ClassFormatException ( "SourceFile attribute"
if ( length ! = 2 )
+ " has wrong length" ) ;
throw new ClassFormatException ( "SourceFile attribute"
sourceFile = cp . getUTF8 ( input . readUnsignedShort ( ) ) ;
+ " has wrong length" ) ;
} else if ( ( howMuch & ( OUTERCLASSES | INNERCLASSES ) ) ! = 0
sourceFile = cp . getUTF8 ( input . readUnsignedShort ( ) ) ;
& & name . equals ( "InnerClasses" ) ) {
} else
int count = input . readUnsignedShort ( ) ;
input . readFully ( new byte [ length ] ) ;
if ( length ! = 2 + 8 * count )
} else if ( name . equals ( "InnerClasses" ) ) {
if ( ( howMuch & ( OUTERCLASSES | INNERCLASSES ) ) ! = 0 ) {
int count = input . readUnsignedShort ( ) ;
if ( length ! = 2 + 8 * count )
throw new ClassFormatException
throw new ClassFormatException
( "InnerClasses attribute has wrong length" ) ;
( "InnerClasses attribute has wrong length" ) ;
int innerCount = 0 , outerCount = 0 , extraCount = 0 ;
int innerCount = 0 , outerCount = 0 , extraCount = 0 ;
InnerClassInfo [ ] innerClassInfo = new InnerClassInfo [ count ] ;
InnerClassInfo [ ] innerClassInfo = new InnerClassInfo [ count ] ;
for ( int i = 0 ; i < count ; i + + ) {
for ( int i = 0 ; i < count ; i + + ) {
int innerIndex = input . readUnsignedShort ( ) ;
int innerIndex = input . readUnsignedShort ( ) ;
int outerIndex = input . readUnsignedShort ( ) ;
int outerIndex = input . readUnsignedShort ( ) ;
int nameIndex = input . readUnsignedShort ( ) ;
int nameIndex = input . readUnsignedShort ( ) ;
String inner = cp . getClassName ( innerIndex ) ;
String inner = cp . getClassName ( innerIndex ) ;
String outer =
String outer =
outerIndex ! = 0 ? cp . getClassName ( outerIndex ) : null ;
outerIndex ! = 0 ? cp . getClassName ( outerIndex ) : null ;
String innername =
String innername =
nameIndex ! = 0 ? cp . getUTF8 ( nameIndex ) : null ;
nameIndex ! = 0 ? cp . getUTF8 ( nameIndex ) : null ;
int access = input . readUnsignedShort ( ) ;
int access = input . readUnsignedShort ( ) ;
if ( innername ! = null & & innername . length ( ) = = 0 )
if ( innername ! = null & & innername . length ( ) = = 0 )
innername = null ;
innername = null ;
/ * Some compilers give method scope classes a valid
/ * Some compilers give method scope classes a valid
* outer field , but we mustn ' t handle them as inner
* outer field , but we mustn ' t handle them as inner
* classes . The best way to distinguish this case
* classes . The best way to distinguish this case
* is by the class name .
* is by the class name .
* /
if ( outer ! = null & & innername ! = null
& & inner . length ( ) > outer . length ( ) + 2 + innername . length ( )
& & inner . startsWith ( outer + "$" )
& & inner . endsWith ( "$" + innername )
& & Character . isDigit ( inner . charAt ( outer . length ( ) + 1 ) ) )
outer = null ;
InnerClassInfo ici = new InnerClassInfo
( inner , outer , innername , access ) ;
if ( outer ! = null & & outer . equals ( getName ( ) )
& & innername ! = null )
innerClassInfo [ innerCount + + ] = ici ;
else
innerClassInfo [ count - ( + + extraCount ) ] = ici ;
}
/ * Now innerClasses are at the front of innerClassInfo array
* in correct order . The other InnerClassInfos are in reverse
* order in the rest of the innerClassInfo array .
* /
* /
if ( outer ! = null & & innername ! = null
& & inner . length ( ) > outer . length ( ) + 2 + innername . length ( )
/ * We now count the outerClasses . The reverse order is the
& & inner . startsWith ( outer + "$" )
* right thing for us .
& & inner . endsWith ( "$" + innername )
* /
& & Character . isDigit ( inner . charAt ( outer . length ( ) + 1 ) ) )
{
outer = null ;
String lastOuterName = getName ( ) ;
for ( int i = count - extraCount ;
InnerClassInfo ici = new InnerClassInfo
i < count & & lastOuterName ! = null ; i + + ) {
( inner , outer , innername , access ) ;
InnerClassInfo ici = innerClassInfo [ i ] ;
if ( ici . inner . equals ( lastOuterName ) ) {
if ( outer ! = null & & outer . equals ( getName ( ) )
outerCount + + ;
& & innername ! = null )
extraCount - - ;
innerClassInfo [ innerCount + + ] = ici ;
lastOuterName = ici . outer ;
else
}
innerClassInfo [ count - ( + + extraCount ) ] = ici ;
}
/ * Now innerClasses are at the front of innerClassInfo array
* in correct order . The other InnerClassInfos are in reverse
* order in the rest of the innerClassInfo array .
* /
/ * We now count the outerClasses . The reverse order is the
* right thing for us .
* /
{
String lastOuterName = getName ( ) ;
for ( int i = count - extraCount ;
i < count & & lastOuterName ! = null ; i + + ) {
InnerClassInfo ici = innerClassInfo [ i ] ;
if ( ici . inner . equals ( lastOuterName ) ) {
outerCount + + ;
extraCount - - ;
lastOuterName = ici . outer ;
}
}
}
}
}
if ( innerCount > 0 ) {
if ( innerCount > 0 ) {
innerClasses = new InnerClassInfo [ innerCount ] ;
innerClasses = new InnerClassInfo [ innerCount ] ;
System . arraycopy ( innerClassInfo , 0 ,
System . arraycopy ( innerClassInfo , 0 ,
innerClasses , 0 , innerCount ) ;
innerClasses , 0 , innerCount ) ;
} else
} else
innerClasses = null ;
innerClasses = null ;
if ( outerCount > 0 ) {
if ( outerCount > 0 ) {
outerClasses = new InnerClassInfo [ outerCount ] ;
outerClasses = new InnerClassInfo [ outerCount ] ;
} else
} else
outerClasses = null ;
outerClasses = null ;
if ( extraCount > 0 ) {
if ( extraCount > 0 ) {
extraClasses = new InnerClassInfo [ extraCount ] ;
extraClasses = new InnerClassInfo [ extraCount ] ;
} else
} else
extraClasses = null ;
extraClasses = null ;
/ * The last part : We split between outer and extra classes .
/ * The last part : We split between outer and extra classes .
* In this step we will also revert the order of the extra
* In this step we will also revert the order of the extra
* classes .
* classes .
* /
* /
{
{
int outerPtr = 0 ;
int outerPtr = 0 ;
String lastOuterName = getName ( ) ;
String lastOuterName = getName ( ) ;
for ( int i = count - extraCount - outerCount ;
for ( int i = count - extraCount - outerCount ;
i < count ; i + + ) {
i < count ; i + + ) {
InnerClassInfo ici = innerClassInfo [ i ] ;
InnerClassInfo ici = innerClassInfo [ i ] ;
/ * If we counted correctly there is no NullPointer
/ * If we counted correctly there is no NullPointer
* or ArrayIndexOutOfBoundsException here
* or ArrayIndexOutOfBoundsException here
* /
* /
if ( ici . inner . equals ( lastOuterName ) ) {
if ( ici . inner . equals ( lastOuterName ) ) {
outerClasses [ outerPtr + + ] = ici ;
outerClasses [ outerPtr + + ] = ici ;
lastOuterName = ici . outer ;
lastOuterName = ici . outer ;
} else
} else
extraClasses [ - - extraCount ] = ici ;
extraClasses [ - - extraCount ] = ici ;
}
}
}
}
} else
input . readFully ( new byte [ length ] ) ;
} else if ( name . equals ( "Deprecated" ) ) {
} else if ( name . equals ( "Deprecated" ) ) {
deprecatedFlag = true ;
deprecatedFlag = true ;
if ( length ! = 0 )
if ( length ! = 0 )