All pastes #219663 Raw Edit

nedm

public text v1 · immutable
#219663 ·published 2006-10-24 20:21 UTC
rendered paste body
package org.nedm;
 
import java.io.*;
 
/**
* <p>Created by NEDM.</p>
* <p>Date: 24-Oct-2006</p>
* <p>Time: 17:21:12</p>
* <p>Intellectual Property of NEDM</p>
* <p>Redistribution or modification of this work is strictly prohibited.</p>
* <p>Removal or modification of this notice in any way is also breaching copyright.</p>
* <p>Copyright 2006 NEDM, All Rights Reserved.</p>
*
* @author NEDM
*/
public final class ClassParser {
    public static ClassFile parse(byte[] bytes) throws IOException, ClassFormatException {
        return parse(new ByteArrayInputStream(bytes));
    }
 
    public static ClassFile parse(InputStream is) throws IOException, ClassFormatException {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
 
        /* Check magic number */
        ClassFile cf = new ClassFile();
        cf.magic = dis.readInt();
        if (cf.magic != 0xCAFEBABE)
            throw new ClassFormatException("Not a valid java class file");
 
        /* Read class version */
        cf.minor = dis.readUnsignedShort();
        cf.major = dis.readUnsignedShort();
 
        /* Read constant pool data */
        cf.constant_pool_count = dis.readUnsignedShort();
        cf.constant_pool = new ConstantPool(new Constant[cf.constant_pool_count]);
        for (int i = 1; i < cf.constant_pool_count; i++) {
            byte b = dis.readByte();
            switch (b) {
                case Constants.CONSTANT_Class:
                    cf.constant_pool.setConstant(i, new ConstantClass(cf.constant_pool, dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_Double:
                    cf.constant_pool.setConstant(i++, new ConstantDouble(cf.constant_pool, dis.readDouble()));
                    break;
                case Constants.CONSTANT_Fieldref:
                    cf.constant_pool.setConstant(i, new ConstantFieldRef(cf.constant_pool, dis.readUnsignedShort(), dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_Float:
                    cf.constant_pool.setConstant(i, new ConstantFloat(cf.constant_pool, dis.readFloat()));
                    break;
                case Constants.CONSTANT_Integer:
                    cf.constant_pool.setConstant(i, new ConstantInteger(cf.constant_pool, dis.readInt()));
                    break;
                case Constants.CONSTANT_InterfaceMethodref:
                    cf.constant_pool.setConstant(i, new ConstantInterfaceMethodRef(cf.constant_pool, dis.readUnsignedShort(), dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_Long:
                    cf.constant_pool.setConstant(i++, new ConstantLong(cf.constant_pool, dis.readLong()));
                    break;
                case Constants.CONSTANT_Methodref:
                    cf.constant_pool.setConstant(i, new ConstantMethodRef(cf.constant_pool, dis.readUnsignedShort(), dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_NameAndType:
                    cf.constant_pool.setConstant(i, new ConstantNameAndType(cf.constant_pool, dis.readUnsignedShort(), dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_String:
                    cf.constant_pool.setConstant(i, new ConstantString(cf.constant_pool, dis.readUnsignedShort()));
                    break;
                case Constants.CONSTANT_Utf8:
                    cf.constant_pool.setConstant(i, new ConstantUtf8(cf.constant_pool, dis.readUTF()));
                    break;
                default:
                    throw new ClassFormatException("Unknown Constant tag");
            }
        }
        /* Read class info */
        cf.access_flags = dis.readUnsignedShort();
        if(cf.isInterface())
            cf.setAbstract(true);
        if (cf.isAbstract() && cf.isFinal())
            throw new ClassFormatException("Class can't be abstract and final");
 
        cf.this_class = dis.readUnsignedShort();
 
        if(cf.this_class < 0 || cf.this_class >= cf.constant_pool_count)
            throw new ClassFormatException("this_class is not an index within the constant pool");
        if(!(cf.constant_pool.getConstant(cf.this_class) instanceof ConstantClass))
            throw new ClassFormatException("Invalid index into constant pool for this_class");
 
        cf.super_class = dis.readUnsignedShort();
 
        if(cf.super_class < 0 || cf.super_class >= cf.constant_pool_count)
            throw new ClassFormatException("super_class is not an index within the constant pool");
        if(!(cf.constant_pool.getConstant(cf.super_class) instanceof ConstantClass))
            throw new ClassFormatException("Invalid index into constant pool for super_class");
 
        /* Read interface info */
        cf.interfaces_count = dis.readUnsignedShort();
        cf.interfaces = new int[cf.interfaces_count];
        for (int interfaces_index = 0; interfaces_index < cf.interfaces_count; interfaces_index++) {
            cf.interfaces[interfaces_index] = dis.readUnsignedShort();
 
            if(cf.interfaces[interfaces_index] < 0 || cf.interfaces[interfaces_index] >= cf.constant_pool_count)
                throw new ClassFormatException("interfaces is not an index within the constant pool");
 
            if(!(cf.constant_pool.getConstant(cf.interfaces[interfaces_index]) instanceof ConstantClass))
                throw new ClassFormatException("Invalid index into constant pool for index");
        }
 
        /* Read field info */
        cf.fields_count = dis.readUnsignedShort();
        cf.field_info = new Field[cf.fields_count];
        for (int i = 0; i < cf.fields_count; i++) {
            Field f = cf.field_info[i] = new Field();
            f.access_flags = dis.readUnsignedShort();
            f.name_index = dis.readUnsignedShort();
            if (f.name_index < 0 || f.name_index >= cf.constant_pool.size())
                throw new ArrayIndexOutOfBoundsException("Field.name_index is giving an invalid pointer into the constant_pool");
            else if(!(cf.constant_pool.getConstant(f.name_index) instanceof ConstantUtf8))
                throw new RuntimeException("Invalid value in constant_pool, type is " + cf.constant_pool.getConstant(f.name_index).getClass().getName().substring(22) + ", should be ConstantUtf8");
            f.descriptor_index = dis.readUnsignedShort();
            f.attributes_count = dis.readUnsignedShort();
            f.attribute_info = new Attribute[f.attributes_count];
            for (int i1 = 0; i1< f.attributes_count; i1++)
                f.attribute_info[i1] = readAttribute(dis, cf.constant_pool);
        }
 
        /* Read method info */
        cf.methods_count = dis.readUnsignedShort();
        cf.method_info = new Method[cf.methods_count];
        for (Method m : cf.method_info) {
            m = new Method();
            m.access_flags = dis.readUnsignedShort();
            m.name_index = dis.readUnsignedShort();
            if (m.name_index < 0 || m.name_index >= cf.constant_pool.size() || !(cf.constant_pool.getConstant(m.name_index) instanceof ConstantUtf8))
                throw new ClassFormatException("Method.name_index is giving an invalid pointer into the constant_pool");
            else if(!(cf.constant_pool.getConstant(m.name_index) instanceof ConstantUtf8))
            throw new RuntimeException("Invalid value in constant_pool, type is " + cf.constant_pool.getConstant(m.name_index).getClass().getName() + ", should be ConstantUtf8");
            m.descriptor_index = dis.readUnsignedShort();
            m.attributes_count = dis.readUnsignedShort();
            m.attribute_info = new Attribute[m.attributes_count];
            for (Attribute a : m.attribute_info) {
                a = readAttribute(dis, cf.constant_pool);
            }
        }
 
        /* Read class Atributes */
        int attributes_count = dis.readUnsignedShort();
        Attribute[] attribute_info = new Attribute[attributes_count];
        for (Attribute a : attribute_info)
            a = readAttribute(dis, cf.constant_pool);
 
        /* Close DataInput Stream */
        dis.close();
        return cf;
    }
 
    public static Attribute readAttribute(DataInputStream dis, ConstantPool constant_pool) throws IOException, ClassFormatException {
        Attribute a;
        int name_index = dis.readUnsignedShort();
 
        if (name_index < 0 || name_index >= constant_pool.size())
            throw new ClassFormatException("Attribute.name_index is giving an invalid pointer into the constant_pool");
        else if(!(constant_pool.getConstant(name_index) instanceof ConstantUtf8))
            throw new RuntimeException("Invalid value in constant_pool, type is " + constant_pool.getConstant(name_index).getClass().getName().substring(22) + ", should be ConstantUtf8");
 
        int length = dis.readInt();
        byte tag = Constants.ATTR_UNKNOWN;
        String name = ((ConstantUtf8) constant_pool.getConstant(name_index)).bytes;
        for (byte idx = 0; idx < Constants.ATTRIBUTE_NAMES.length; idx++)
            if (Constants.ATTRIBUTE_NAMES[idx].equals(name)) tag = idx;
        switch (tag) {
            case Constants.ATTR_UNKNOWN:
                System.out.println("Unknown Attribute: " + name);
                a = new Unknown(name_index, length);
                break;
            case Constants.ATTR_CODE:
                /* Initialize some default values which will be overwritten later */
                Code c = new Code(name_index, length, dis.readUnsignedShort(), dis.readUnsignedShort(), -1, null, -1,
                        null, -1, null);
                c.code_length = dis.readInt();
                c.code = new byte[c.code_length];
                dis.readFully(c.code);
                /* Read Exception table of this code */
                c.exception_table_length = dis.readUnsignedShort();
                c.exception_table = new CodeException[c.exception_table_length];
                for (int i = 0; i < c.exception_table_length; i++)
                    c.exception_table[i] = new CodeException(dis.readUnsignedShort(), dis.readUnsignedShort(), dis.readUnsignedShort(), dis.readUnsignedShort());
                c.attributes_count = dis.readUnsignedShort();
                c.attributes = new Attribute[c.attributes_count];
                for (Attribute a1 : c.attributes)
                    a1 = readAttribute(dis, constant_pool);
                a = c;
                break;
            case Constants.ATTR_CONSTANT_VALUE:
                int loc = dis.readUnsignedShort();
                a = new ConstantValue(name_index, length, loc);
                break;
            case Constants.ATTR_DEPRECATED:
                a = new Deprecated(name_index, length);
                break;
            case Constants.ATTR_EXCEPTIONS:
                Exceptions e = new Exceptions(name_index, length, -1, new int[]{});
                e.number_of_exceptions = dis.readUnsignedShort();
                e.exception_index_table = new int[e.number_of_exceptions];
                for(int i = 0; i < e.number_of_exceptions; i++)
                    e.exception_index_table[i] = dis.readUnsignedShort();
                a = e;
                break;
            case Constants.ATTR_INNER_CLASSES:
                InnerClasses ic = new InnerClasses(name_index, length, -1, new Classes[]{});
                ic.number_of_classes = dis.readUnsignedShort();
                ic.classes = new Classes[ic.number_of_classes];
                for(int i = 0; i < ic.number_of_classes; i++)
                    ic.classes[i] = new Classes(dis.readUnsignedShort(), dis.readUnsignedShort(),
                            dis.readUnsignedShort(), dis.readUnsignedShort());
                a = ic;
                break;
            case Constants.ATTR_LINE_NUMBER_TABLE:
                LineNumberTable lnt = new LineNumberTable(name_index, length, -1, new LineNumber[]{});
                lnt.line_number_table_length = dis.readUnsignedShort();
                lnt.line_number_table = new LineNumber[lnt.line_number_table_length];
                for(int i = 0; i < lnt.line_number_table_length; i++)
                    lnt.line_number_table[i] = new LineNumber(dis.readUnsignedShort(), dis.readUnsignedShort());
                a = lnt;
                break;
            case Constants.ATTR_LOCAL_VARIABLE_TABLE:
                LocalVariableTable lvt = new LocalVariableTable(name_index, length, -1, new LocalVariable[]{});
                lvt.local_variable_table_length = dis.readUnsignedShort();
                lvt.local_variable_table = new LocalVariable[lvt.local_variable_table_length];
                for(int i = 0; i < lvt.local_variable_table_length; i++)
                    lvt.local_variable_table[i] = new LocalVariable(dis.readUnsignedShort(), dis.readUnsignedShort(),
                            dis.readUnsignedShort(), dis.readUnsignedShort(), dis.readUnsignedShort());
                a = lvt;
                break;
            case Constants.ATTR_SOURCE_FILE:
                a = new SourceFile(name_index, length, dis.readUnsignedShort());
                break;
            case Constants.ATTR_SYNTHETIC:
                a = new Synthetic(name_index, length);
                break;
            default:
                System.out.println("Unknown Attribute: " + name);
                a = new Unknown(name_index, length);
        }
        return a;
    }
}