package jd.cli.util; import jd.core.CoreConstants; import jd.core.model.classfile.constant.Constant; import jd.core.model.classfile.constant.ConstantClass; import jd.core.model.classfile.constant.ConstantConstant; import jd.core.model.classfile.constant.ConstantUtf8; import jd.core.process.deserializer.ClassFormatException; import jd.core.util.StringConstants; import java.io.*; public class ClassFileUtil { private ClassFileUtil() { } /* * Lecture rapide de la structure de la classe et extraction du nom du * repoertoire de base. */ public static String ExtractDirectoryPath(String pathToClass) throws Exception { DataInputStream dis = null; String directoryPath = null; try { dis = new DataInputStream( new BufferedInputStream( new FileInputStream(pathToClass))); int magic = dis.readInt(); if (magic != CoreConstants.JAVA_MAGIC_NUMBER) throw new ClassFormatException("Invalid Java .class file"); /* int minor_version = */ dis.readUnsignedShort(); /* int major_version = */ dis.readUnsignedShort(); Constant[] constants = DeserializeConstants(dis); /* int access_flags = */ dis.readUnsignedShort(); int this_class = dis.readUnsignedShort(); Constant c = constants[this_class]; if ((c == null) || (c.tag != ConstantConstant.CONSTANT_Class)) throw new ClassFormatException("Invalid contant pool"); c = constants[((ConstantClass) c).name_index]; if ((c == null) || (c.tag != ConstantConstant.CONSTANT_Utf8)) throw new ClassFormatException("Invalid contant pool"); String internalClassName = ((ConstantUtf8) c).bytes; String pathSuffix = internalClassName.replace( StringConstants.INTERNAL_PACKAGE_SEPARATOR, File.separatorChar) + StringConstants.CLASS_FILE_SUFFIX; int index = pathToClass.indexOf(pathSuffix); if (index < 0) throw new ClassFormatException("Invalid internal class name"); directoryPath = pathToClass.substring(0, index); } finally { if (dis != null) try { dis.close(); } catch (IOException e) { } } return directoryPath; } public static String ExtractInternalPath( String directoryPath, String pathToClass) { if ((directoryPath == null) || (pathToClass == null) || !pathToClass.startsWith(directoryPath)) return null; String s = pathToClass.substring(directoryPath.length()); return s.replace(File.separatorChar, StringConstants.INTERNAL_PACKAGE_SEPARATOR); } private static Constant[] DeserializeConstants(DataInputStream dis) throws IOException { int count = dis.readUnsignedShort(); if (count == 0) return null; Constant[] constants = new Constant[count]; for (int i = 1; i < count; i++) { byte tag = dis.readByte(); switch (tag) { case ConstantConstant.CONSTANT_Class: constants[i] = new ConstantClass(tag, dis.readUnsignedShort()); break; case ConstantConstant.CONSTANT_Utf8: constants[i] = new ConstantUtf8(tag, dis.readUTF()); break; case ConstantConstant.CONSTANT_Long: case ConstantConstant.CONSTANT_Double: dis.readInt(); dis.readInt(); i++; break; case ConstantConstant.CONSTANT_Fieldref: case ConstantConstant.CONSTANT_Methodref: case ConstantConstant.CONSTANT_InterfaceMethodref: case ConstantConstant.CONSTANT_NameAndType: dis.readUnsignedShort(); dis.readUnsignedShort(); break; case ConstantConstant.CONSTANT_Integer: case ConstantConstant.CONSTANT_Float: dis.readInt(); break; case ConstantConstant.CONSTANT_String: dis.readUnsignedShort(); break; case 15: case 16: case 18: throw new IllegalArgumentException("JD-GUI does not support Java 8 as of yet"); default: throw new ClassFormatException("Invalid constant pool entry"); } } return constants; } }