From 0803c290c5330c77132e61c39ad009f1f39f7433 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Tue, 20 Mar 2018 20:30:57 +0100 Subject: [PATCH] add getDeclaringClassFile() --- .../inetsoftware/classparser/ClassFile.java | 440 +++++++++--------- .../inetsoftware/classparser/MethodInfo.java | 10 +- 2 files changed, 229 insertions(+), 221 deletions(-) diff --git a/src/de/inetsoftware/classparser/ClassFile.java b/src/de/inetsoftware/classparser/ClassFile.java index 8983408..f2f6e78 100644 --- a/src/de/inetsoftware/classparser/ClassFile.java +++ b/src/de/inetsoftware/classparser/ClassFile.java @@ -1,220 +1,220 @@ -/* - Copyright 2011 - 2017 Volker Berlin (i-net software) - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package de.inetsoftware.classparser; - -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; - -import de.inetsoftware.classparser.Attributes.AttributeInfo; - -/** - * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html - * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html - * - * @author Volker Berlin - */ -public class ClassFile { - - private final DataInputStream input; - - private final int minorVersion; - - private final int majorVersion; - - private final ConstantPool constantPool; - - private final int accessFlags; - - private final ConstantClass thisClass; - - private final ConstantClass superClass; - - private final ConstantClass[] interfaces; - - private final FieldInfo[] fields; - - private final MethodInfo[] methods; - - private final Attributes attributes; - - private String thisSignature; - - private String superSignature; - - /** - * Load a class file and create a model of the class. - * - * @param stream - * The InputStream of the class file. Will be closed if finish. - * @throws IOException - * if this input stream reaches the end before reading the class file. - */ - public ClassFile( InputStream stream ) throws IOException { - this.input = new DataInputStream( stream ); - int magic = input.readInt(); - if( magic != 0xCAFEBABE ) { - throw new IOException( "Invalid class magic: " + Integer.toHexString( magic ) ); - } - minorVersion = input.readUnsignedShort(); - majorVersion = input.readUnsignedShort(); - - constantPool = new ConstantPool( input ); - accessFlags = input.readUnsignedShort(); - thisClass = (ConstantClass)constantPool.get( input.readUnsignedShort() ); - superClass = (ConstantClass)constantPool.get( input.readUnsignedShort() ); - interfaces = new ConstantClass[input.readUnsignedShort()]; - for( int i = 0; i < interfaces.length; i++ ) { - interfaces[i] = (ConstantClass)constantPool.get( input.readUnsignedShort() ); - } - fields = readFields(); - methods = readMethods(); - attributes = new Attributes( input, constantPool ); - - stream.close(); - - AttributeInfo info = attributes.get( "Signature" ); - if( info != null ) { - int idx = info.getDataInputStream().readShort(); - String signature = (String)constantPool.get( idx ); - int count = 0; - for( int i = 0; i < signature.length(); i++ ) { - char ch = signature.charAt( i ); - switch( ch ) { - case '<': - count++; - continue; - case '>': - count--; - continue; - } - if( count == 0 ) { - thisSignature = signature.substring( 0, i ); - superSignature = signature.substring( i ); - break; - } - } - } - } - - /** - * Get value of SourceFile if available. - * - * @return the source file name or null. - * @throws IOException - * if an I/O error occurs. - */ - public String getSourceFile() throws IOException { - return attributes.getSourceFile(); - } - - public ConstantPool getConstantPool() { - return constantPool; - } - - public ConstantClass getThisClass() { - return thisClass; - } - - public ConstantClass getSuperClass() { - return superClass; - } - - public ConstantClass[] getInterfaces(){ - return interfaces; - } - - public MethodInfo[] getMethods() { - return methods; - } - - public int getMethodCount( String name ) { - int count = 0; - for( MethodInfo method : methods ) { - if( name.equals( method.getName() ) ) { - count++; - } - } - return count; - } - - public FieldInfo getField( String name ) { - for( FieldInfo field : fields ) { - if( name.equals( field.getName() ) ) { - return field; - } - } - return null; - } - - /** - * The access flags of the class. - * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E - * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#23242 - * @see #isInterface() - */ - public int getAccessFlags() { - return accessFlags; - } - - private FieldInfo[] readFields() throws IOException { - FieldInfo[] fields = new FieldInfo[input.readUnsignedShort()]; - for( int i = 0; i < fields.length; i++ ) { - fields[i] = new FieldInfo( input, constantPool ); - } - return fields; - } - - private MethodInfo[] readMethods() throws IOException { - MethodInfo[] methods = new MethodInfo[input.readUnsignedShort()]; - for( int i = 0; i < methods.length; i++ ) { - methods[i] = new MethodInfo( input, constantPool ); - } - return methods; - } - - /** - * Get the signature of the class with generic types. - */ - public String getThisSignature() { - return thisSignature; - } - - /** - * Get the signature of the super class with generic types. - */ - public String getSuperSignature() { - return superSignature; - } - - /** - * Get the type of class. - */ - public Type getType() { - if( (accessFlags & 0x0200) > 0 ) { - return Type.Interface; - } - if( superClass.getName().equals( "java/lang/Enum" ) ) { - return Type.Enum; - } - return Type.Class; - } - - public static enum Type { - Class, Interface, Enum; - } -} +/* + Copyright 2011 - 2017 Volker Berlin (i-net software) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package de.inetsoftware.classparser; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import de.inetsoftware.classparser.Attributes.AttributeInfo; + +/** + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html + * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html + * + * @author Volker Berlin + */ +public class ClassFile { + + private final DataInputStream input; + + private final int minorVersion; + + private final int majorVersion; + + private final ConstantPool constantPool; + + private final int accessFlags; + + private final ConstantClass thisClass; + + private final ConstantClass superClass; + + private final ConstantClass[] interfaces; + + private final FieldInfo[] fields; + + private final MethodInfo[] methods; + + private final Attributes attributes; + + private String thisSignature; + + private String superSignature; + + /** + * Load a class file and create a model of the class. + * + * @param stream + * The InputStream of the class file. Will be closed if finish. + * @throws IOException + * if this input stream reaches the end before reading the class file. + */ + public ClassFile( InputStream stream ) throws IOException { + this.input = new DataInputStream( stream ); + int magic = input.readInt(); + if( magic != 0xCAFEBABE ) { + throw new IOException( "Invalid class magic: " + Integer.toHexString( magic ) ); + } + minorVersion = input.readUnsignedShort(); + majorVersion = input.readUnsignedShort(); + + constantPool = new ConstantPool( input ); + accessFlags = input.readUnsignedShort(); + thisClass = (ConstantClass)constantPool.get( input.readUnsignedShort() ); + superClass = (ConstantClass)constantPool.get( input.readUnsignedShort() ); + interfaces = new ConstantClass[input.readUnsignedShort()]; + for( int i = 0; i < interfaces.length; i++ ) { + interfaces[i] = (ConstantClass)constantPool.get( input.readUnsignedShort() ); + } + fields = readFields(); + methods = readMethods(); + attributes = new Attributes( input, constantPool ); + + stream.close(); + + AttributeInfo info = attributes.get( "Signature" ); + if( info != null ) { + int idx = info.getDataInputStream().readShort(); + String signature = (String)constantPool.get( idx ); + int count = 0; + for( int i = 0; i < signature.length(); i++ ) { + char ch = signature.charAt( i ); + switch( ch ) { + case '<': + count++; + continue; + case '>': + count--; + continue; + } + if( count == 0 ) { + thisSignature = signature.substring( 0, i ); + superSignature = signature.substring( i ); + break; + } + } + } + } + + /** + * Get value of SourceFile if available. + * + * @return the source file name or null. + * @throws IOException + * if an I/O error occurs. + */ + public String getSourceFile() throws IOException { + return attributes.getSourceFile(); + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ConstantClass getThisClass() { + return thisClass; + } + + public ConstantClass getSuperClass() { + return superClass; + } + + public ConstantClass[] getInterfaces(){ + return interfaces; + } + + public MethodInfo[] getMethods() { + return methods; + } + + public int getMethodCount( String name ) { + int count = 0; + for( MethodInfo method : methods ) { + if( name.equals( method.getName() ) ) { + count++; + } + } + return count; + } + + public FieldInfo getField( String name ) { + for( FieldInfo field : fields ) { + if( name.equals( field.getName() ) ) { + return field; + } + } + return null; + } + + /** + * The access flags of the class. + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E + * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#23242 + * @see #isInterface() + */ + public int getAccessFlags() { + return accessFlags; + } + + private FieldInfo[] readFields() throws IOException { + FieldInfo[] fields = new FieldInfo[input.readUnsignedShort()]; + for( int i = 0; i < fields.length; i++ ) { + fields[i] = new FieldInfo( input, constantPool ); + } + return fields; + } + + private MethodInfo[] readMethods() throws IOException { + MethodInfo[] methods = new MethodInfo[input.readUnsignedShort()]; + for( int i = 0; i < methods.length; i++ ) { + methods[i] = new MethodInfo( input, constantPool, this ); + } + return methods; + } + + /** + * Get the signature of the class with generic types. + */ + public String getThisSignature() { + return thisSignature; + } + + /** + * Get the signature of the super class with generic types. + */ + public String getSuperSignature() { + return superSignature; + } + + /** + * Get the type of class. + */ + public Type getType() { + if( (accessFlags & 0x0200) > 0 ) { + return Type.Interface; + } + if( superClass.getName().equals( "java/lang/Enum" ) ) { + return Type.Enum; + } + return Type.Class; + } + + public static enum Type { + Class, Interface, Enum; + } +} diff --git a/src/de/inetsoftware/classparser/MethodInfo.java b/src/de/inetsoftware/classparser/MethodInfo.java index 9f01855..f840a18 100644 --- a/src/de/inetsoftware/classparser/MethodInfo.java +++ b/src/de/inetsoftware/classparser/MethodInfo.java @@ -40,6 +40,8 @@ public class MethodInfo { private Exceptions exceptions; + private ClassFile classFile; + /** * Read the method_info structure * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6 @@ -47,14 +49,20 @@ public class MethodInfo { * * @param input * @param constantPool + * @param classFile the declaring class file * @throws IOException */ - MethodInfo( DataInputStream input, ConstantPool constantPool ) throws IOException { + MethodInfo( DataInputStream input, ConstantPool constantPool, ClassFile classFile ) throws IOException { this.accessFlags = input.readUnsignedShort(); this.name = (String)constantPool.get( input.readUnsignedShort() ); this.description = (String)constantPool.get( input.readUnsignedShort() ); this.constantPool = constantPool; this.attributes = new Attributes( input, constantPool ); + this.classFile = classFile; + } + + public ClassFile getDeclaringClassFile() { + return classFile; } /**