package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import com.coderising.jvm.attr.InvalidAttributeInfoException; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantInfoFactory; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.InvalidConstantInfoTypeException; import com.coderising.jvm.constant.MethodRefInfo; import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.interfaze.Interfaze; import com.coderising.jvm.interfaze.InvalidInterfaceException; import com.coderising.jvm.method.InvalidMethodInfoException; import com.coderising.jvm.method.Method; public class ClassFileParser { ClassFile clz = null; public ClassFile parse(byte[] codes) { clz = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); String magicHex = iter.getNextNHexString(4); System.out.println("Magic Number: "+magicHex); try{ String minorHex = iter.getNextHexString() + iter.getNextHexString(); int minorVersionInt = Integer.parseInt(minorHex, 16); String majorHex = iter.getNextHexString() + iter.getNextHexString(); int majorVersionInt = Integer.parseInt(majorHex, 16); clz.setMajorVersion(majorVersionInt);clz.setMinorVersion(minorVersionInt); System.out.println("Major version: " + majorVersionInt + " minor version: " + minorVersionInt); clz.setConstPool(parseConstantPool(iter)); fillClassInfo(clz, clz.getConstantPool()); System.out.println(iter.peekNextNHex(8)); parseAccessFlag(iter); parseClassInfex(iter);parseClassInfex(iter); parseInterface(iter); parseFields(iter); parseMethods(iter); } catch(Exception e){ e.printStackTrace(); } return clz; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { ConstantPool cp = clz.getConstantPool(); int visitFlagIndex = iter.getNextNBytesInteger(2); System.out.println("visit flag index: " + visitFlagIndex + " variable value: " + cp.getUTF8String(visitFlagIndex)); return null; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { int classInfIndex = iter.getNextNBytesInteger(2); System.out.println("class info: " + classInfIndex); return null; } private List<Interfaze> parseInterface(ByteCodeIterator iter) throws InvalidInterfaceException{ int interfaceCount = iter.getNextNBytesInteger(2); if(interfaceCount>0){ throw new InvalidInterfaceException("Unimplemented interface parser: " + interfaceCount); } return null; } private void parseFields(ByteCodeIterator iter){ int fieldsCount = iter.getNextNBytesInteger(2); System.out.println("Fields count: " + fieldsCount); List<Field> fields = new LinkedList<>(); for(int i = 0; i<fieldsCount; i++){ Field f = null; try { f = Field.parse(clz.getConstantPool(), iter); } catch (InvalidAttributeInfoException e) { // TODO Auto-generated catch block e.printStackTrace(); } fields.add(f); } clz.setFields(fields); } private void parseMethods(ByteCodeIterator iter){ int methodCount = iter.getNextNBytesInteger(2); System.out.println("Methods count: " + methodCount); List<Method> methods = new ArrayList<>(); for(int i = 0; i<methodCount; i++){ Method m = null; try{ m = Method.parse(clz, iter); System.out.println("dumpping method: " + m); methods.add(m); } catch(InvalidMethodInfoException e){ e.printStackTrace(); } } for(int i = 0; i<methods.size(); i++){ System.out.println("class method dump: " + methods.get(i) ); } clz.setMethods(methods); } private void fillClassInfo(ClassFile clz, ConstantPool pool){ ClassIndex newClassIndex = new ClassIndex(); clz.setClassIndex(newClassIndex); for(int i = 0; i< pool.getSize(); i++){ if(pool.getConstantInfo(i) instanceof ClassInfo){ if(clz.getClzIndex().getThisClassIndex() == 0){ System.out.println("class"); clz.getClzIndex().setThisClassIndex(i); } else if(clz.getClzIndex().getSuperClassIndex() == 0){ clz.getClzIndex().setSuperClassIndex(i); } else{ break; } } } } private ConstantPool parseConstantPool(ByteCodeIterator iter) { String constantPoolSizeHex = iter.getNextHexString() + iter.getNextHexString(); //System.out.println("hex string: " + constantPoolSizeHex + " integer value: " + Integer.parseInt(constantPoolSizeHex, 16)); int constantCount = Integer.parseInt(constantPoolSizeHex, 16); ConstantPool constantPool = new ConstantPool(); constantPool.addConstantInfo(new NullConstantInfo()); ConstantInfoFactory constantInfoFactory = new ConstantInfoFactory(iter, constantPool); while(constantCount-- > 1){ try { constantInfoFactory.fillNextConstantInfo(); } catch ( Exception e) { // TODO Auto-generated catch block e.printStackTrace(); break; } } // for(int i = 0; i<constantPool.getSize(); i++){ // System.out.println("constant pool variable: " + i ); // ConstantInfo c = constantPool.getConstantInfo(i); // System.out.println(c.getClass().getName()); // } return constantPool; } }