com.hfg.util.BasicClassFileInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.util;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
//------------------------------------------------------------------------------
/**
Currently this is just a simple helper class used by ClassExplorer to extract
information from Java class files about the superclass and interfaces implemented.
@author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
// See: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
public class BasicClassFileInfo
{
private int mMajorVersion;
private int mMinorVersion;
private int mConstantPoolCount;
private int mInterfacesCount;
private String mClassname;
private String mSuperclassname;
private String[] mInterfaces;
// Constant Pool tag values
private enum ConstantPoolTag
{
CONSTANT_Utf8(1),
CONSTANT_Integer(3),
CONSTANT_Float(4),
CONSTANT_Long(5),
CONSTANT_Double(6),
CONSTANT_Class(7),
CONSTANT_String(8),
CONSTANT_Fieldref(9),
CONSTANT_Methodref(10),
CONSTANT_InterfaceMethodref(11),
CONSTANT_NameAndType(12),
CONSTANT_MethodHandle(15),
CONSTANT_MethodType(16),
CONSTANT_InvokeDynamic(18);
private int mValue;
private ConstantPoolTag(int inValue)
{
mValue = inValue;
}
public int getValue()
{
return mValue;
}
public static ConstantPoolTag valueOf(int inValue)
{
ConstantPoolTag tag = null;
for (ConstantPoolTag poolTag : values())
{
if (poolTag.getValue() == inValue)
{
tag = poolTag;
break;
}
}
return tag;
}
}
//--------------------------------------------------------------------------
public BasicClassFileInfo(DataInputStream inStream)
throws IOException
{
int magic = inStream.readInt();
if (magic != 0xCAFEBABE)
{
throw new IOException("Bad magic number: " + Integer.toHexString(magic));
}
mMinorVersion = inStream.readUnsignedShort();
mMajorVersion = inStream.readUnsignedShort();
mConstantPoolCount = inStream.readUnsignedShort();
List entries = new ArrayList<>(mConstantPoolCount);
for (int idx = 1; idx < mConstantPoolCount; idx++)
{
ConstantPoolTag tag = ConstantPoolTag.valueOf(inStream.readUnsignedByte());
switch (tag)
{
case CONSTANT_Utf8:
entries.add(new Utf8Entry(inStream));
break;
case CONSTANT_Integer:
entries.add(new IntegerEntry(inStream));
break;
case CONSTANT_Float:
entries.add(new FloatEntry(inStream));
break;
case CONSTANT_Long:
entries.add(new LongEntry(inStream));
break;
case CONSTANT_Double:
entries.add(new DoubleEntry(inStream));
break;
case CONSTANT_Class:
entries.add(new ClassEntry(inStream));
break;
case CONSTANT_String:
entries.add(new StringEntry(inStream));
break;
case CONSTANT_Fieldref:
entries.add(new FieldrefEntry(inStream));
break;
case CONSTANT_Methodref:
entries.add(new MethodrefEntry(inStream));
break;
case CONSTANT_InterfaceMethodref:
entries.add(new InterfaceMethodrefEntry(inStream));
break;
case CONSTANT_NameAndType:
entries.add(new NameAndTypeEntry(inStream));
break;
case CONSTANT_MethodHandle:
entries.add(new MethodHandleEntry(inStream));
break;
case CONSTANT_MethodType:
entries.add(new MethodTypeEntry(inStream));
break;
case CONSTANT_InvokeDynamic:
entries.add(new InvokeDynamicEntry(inStream));
break;
}
}
// Access flags
inStream.readUnsignedShort();
// Class name
int classIdx = inStream.readUnsignedShort();
ClassEntry classEntry = (ClassEntry) entries.get(classIdx - 1);
mClassname = ((Utf8Entry) entries.get(classEntry.getNameIndex() - 1)).getString().replace(File.separator, ".");
// Super class
int superclassIdx = inStream.readUnsignedShort();
ClassEntry superclassEntry = (ClassEntry) entries.get(superclassIdx - 1);
mSuperclassname = ((Utf8Entry) entries.get(superclassEntry.getNameIndex() - 1)).getString().replace(File.separator, ".");
mInterfacesCount = inStream.readUnsignedShort();
if (mInterfacesCount > 0)
{
mInterfaces = new String[mInterfacesCount];
for (int i = 0; i < mInterfacesCount; i++)
{
int index = inStream.readUnsignedShort();
ClassEntry interfaceEntry = (ClassEntry) entries.get(index - 1);
mInterfaces[i] = ((Utf8Entry) entries.get(interfaceEntry.getNameIndex() - 1)).getString().replace(File.separator, ".");
}
}
}
//--------------------------------------------------------------------------
public String getClassname()
{
return mClassname;
}
//--------------------------------------------------------------------------
public String getSuperClassname()
{
return mSuperclassname;
}
//--------------------------------------------------------------------------
public String[] getInterfaceClassnames()
{
return mInterfaces;
}
abstract class ConstantPoolEntry
{
}
private class Utf8Entry extends ConstantPoolEntry
{
private String mString;
//-----------------------------------------------------------------------
public Utf8Entry(DataInputStream inStream)
throws IOException
{
mString = inStream.readUTF();
}
//-----------------------------------------------------------------------
public String getString()
{
return mString;
}
}
private class IntegerEntry extends ConstantPoolEntry
{
private int mValue;
//-----------------------------------------------------------------------
public IntegerEntry(DataInputStream inStream)
throws IOException
{
mValue = inStream.readInt();
}
//-----------------------------------------------------------------------
public int getValue()
{
return mValue;
}
}
private class FloatEntry extends ConstantPoolEntry
{
private float mValue;
//-----------------------------------------------------------------------
public FloatEntry(DataInputStream inStream)
throws IOException
{
mValue = inStream.readFloat();
}
//-----------------------------------------------------------------------
public float getValue()
{
return mValue;
}
}
private class LongEntry extends ConstantPoolEntry
{
private long mValue;
//-----------------------------------------------------------------------
public LongEntry(DataInputStream inStream)
throws IOException
{
mValue = inStream.readLong();
}
//-----------------------------------------------------------------------
public long getValue()
{
return mValue;
}
}
private class DoubleEntry extends ConstantPoolEntry
{
private double mValue;
//-----------------------------------------------------------------------
public DoubleEntry(DataInputStream inStream)
throws IOException
{
mValue = inStream.readDouble();
}
//-----------------------------------------------------------------------
public double getValue()
{
return mValue;
}
}
private class StringEntry extends ConstantPoolEntry
{
private int mIndex;
//-----------------------------------------------------------------------
public StringEntry(DataInputStream inStream)
throws IOException
{
mIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getIndex()
{
return mIndex;
}
}
private class ClassEntry extends ConstantPoolEntry
{
private int mNameIndex;
//-----------------------------------------------------------------------
public ClassEntry(DataInputStream inStream)
throws IOException
{
mNameIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getNameIndex()
{
return mNameIndex;
}
}
private class NameAndTypeEntry extends ConstantPoolEntry
{
private int mMemberNameIndex;
private int mTypeDescriptorIndex;
//-----------------------------------------------------------------------
public NameAndTypeEntry(DataInputStream inStream)
throws IOException
{
mMemberNameIndex = inStream.readUnsignedShort();
mTypeDescriptorIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getMemberNameIndex()
{
return mMemberNameIndex;
}
//-----------------------------------------------------------------------
public int getTypeDescriptorIndex()
{
return mTypeDescriptorIndex;
}
}
private class InterfaceMethodrefEntry extends ConstantPoolEntry
{
private int mClassIndex;
private int mNameAndTypeIndex;
//-----------------------------------------------------------------------
public InterfaceMethodrefEntry(DataInputStream inStream)
throws IOException
{
mClassIndex = inStream.readUnsignedShort();
mNameAndTypeIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getClassIndex()
{
return mClassIndex;
}
//-----------------------------------------------------------------------
public int getNameAndTypeIndex()
{
return mNameAndTypeIndex;
}
}
private class MethodrefEntry extends ConstantPoolEntry
{
private int mClassIndex;
private int mNameAndTypeIndex;
//-----------------------------------------------------------------------
public MethodrefEntry(DataInputStream inStream)
throws IOException
{
mClassIndex = inStream.readUnsignedShort();
mNameAndTypeIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getClassIndex()
{
return mClassIndex;
}
//-----------------------------------------------------------------------
public int getNameAndTypeIndex()
{
return mNameAndTypeIndex;
}
}
private class FieldrefEntry extends ConstantPoolEntry
{
private int mClassIndex;
private int mNameAndTypeIndex;
//-----------------------------------------------------------------------
public FieldrefEntry(DataInputStream inStream)
throws IOException
{
mClassIndex = inStream.readUnsignedShort();
mNameAndTypeIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getClassIndex()
{
return mClassIndex;
}
//-----------------------------------------------------------------------
public int getNameAndTypeIndex()
{
return mNameAndTypeIndex;
}
}
private class MethodHandleEntry extends ConstantPoolEntry
{
private int mKind;
private int mIndex;
//-----------------------------------------------------------------------
public MethodHandleEntry(DataInputStream inStream)
throws IOException
{
mKind = inStream.readUnsignedByte();
mIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getKind()
{
return mKind;
}
//-----------------------------------------------------------------------
public int getIndex()
{
return mIndex;
}
}
private class MethodTypeEntry extends ConstantPoolEntry
{
private int mDescriptorIndex;
//-----------------------------------------------------------------------
public MethodTypeEntry(DataInputStream inStream)
throws IOException
{
mDescriptorIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getDescriptorIndex()
{
return mDescriptorIndex;
}
}
private class InvokeDynamicEntry extends ConstantPoolEntry
{
private int mBootstrapMethodAttrIndex;
private int mNameAndTypeIndex;
//-----------------------------------------------------------------------
public InvokeDynamicEntry(DataInputStream inStream)
throws IOException
{
mBootstrapMethodAttrIndex = inStream.readUnsignedShort();
mNameAndTypeIndex = inStream.readUnsignedShort();
}
//-----------------------------------------------------------------------
public int getBootstrapMethodAttrIndex()
{
return mBootstrapMethodAttrIndex;
}
//-----------------------------------------------------------------------
public int getNameAndTypeIndex()
{
return mNameAndTypeIndex;
}
}
}