1 20 21 package com.tonicsystems.jarjar.util; 22 23 import java.io.*; 24 import java.lang.reflect.Array ; 25 import java.util.*; 26 27 public class ClassHeaderReader 28 { 29 private int access; 30 private String thisClass; 31 private String superClass; 32 private String [] interfaces; 33 34 private InputStream in; 35 private byte[] b = new byte[0x2000]; 36 private int[] items = new int[1000]; 37 private int bsize = 0; 38 private MyByteArrayInputStream bin = new MyByteArrayInputStream(); 39 private DataInputStream data = new DataInputStream(bin); 40 41 public int getAccess() { 42 return access; 43 } 44 45 public String getClassName() { 46 return thisClass; 47 } 48 49 public String getSuperName() { 50 return superClass; 51 } 52 53 public String [] getInterfaces() { 54 return interfaces; 55 } 56 57 public void read(InputStream in) throws IOException { 58 try { 59 this.in = in; 60 bsize = 0; 61 access = 0; 62 thisClass = superClass = null; 63 interfaces = null; 64 65 buffer(10); 66 if (b[0] != (byte)0xCA || b[1] != (byte)0xFE || b[2] != (byte)0xBA || b[3] != (byte)0xBE) 67 throw new IOException("Bad magic number"); 68 69 int minorVersion = readUnsignedShort(4); 70 int majorVersion = readUnsignedShort(6); 71 int constant_pool_count = readUnsignedShort(8); 73 items = (int[])resizeArray(items, constant_pool_count); 74 75 int index = 10; 76 for (int i = 1; i < constant_pool_count; i++) { 77 int size; 78 buffer(index + 3); int tag = b[index]; 80 items[i] = index + 1; 81 switch (tag) { 82 case 9: case 10: case 11: case 3: case 4: case 12: size = 4; 89 break; 90 case 5: case 6: size = 8; 93 i++; 94 break; 95 case 1: size = 2 + readUnsignedShort(index + 1); 97 break; 98 case 7: case 8: size = 2; 101 break; 102 default: 103 throw new IllegalStateException ("Unknown constant pool tag " + tag); 104 } 105 index += size + 1; 106 } 107 buffer(index + 8); 108 access = readUnsignedShort(index); 109 thisClass = readClass(index + 2); 110 superClass = readClass(index + 4); 111 int interfaces_count = readUnsignedShort(index + 6); 112 113 index += 8; 114 buffer(index + interfaces_count * 2); 115 interfaces = new String [interfaces_count]; 116 for (int i = 0; i < interfaces_count; i++) { 117 interfaces[i] = readClass(index); 118 index += 2; 119 } 120 } finally { 121 in.close(); 122 } 123 } 124 125 private String readClass(int index) throws IOException { 126 index = readUnsignedShort(index); 127 if (index == 0) 128 return null; 129 index = readUnsignedShort(items[index]); 130 bin.readFrom(b, items[index]); 131 return data.readUTF(); 132 } 133 134 private int readUnsignedShort(int index) { 135 byte[] b = this.b; 136 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 137 } 138 139 private static final int CHUNK = 2048; 140 private void buffer(int amount) throws IOException { 141 if (amount > b.length) 142 b = (byte[])resizeArray(b, b.length * 2); 143 if (amount > bsize) { 144 int rounded = (int)(CHUNK * Math.ceil((float)amount / CHUNK)); 145 bsize += read(in, b, bsize, rounded - bsize); 146 if (amount > bsize) 147 throw new EOFException(); 148 } 149 } 150 151 private static int read(InputStream in, byte[] b, int off, int len) throws IOException { 152 int total = 0; 153 while (total < len) { 154 int result = in.read(b, off + total, len - total); 155 if (result == -1) 156 break; 157 total += result; 158 } 159 return total; 160 } 161 162 private static Object resizeArray(Object array, int length) 163 { 164 if (Array.getLength(array) < length) { 165 Object newArray = Array.newInstance(array.getClass().getComponentType(), length); 166 System.arraycopy(array, 0, newArray, 0, Array.getLength(array)); 167 return newArray; 168 } else { 169 return array; 170 } 171 } 172 173 private static class MyByteArrayInputStream extends ByteArrayInputStream 174 { 175 public MyByteArrayInputStream() { 176 super(new byte[0]); 177 } 178 179 public void readFrom(byte[] buf, int pos) { 180 this.buf = buf; 181 this.pos = pos; 182 count = buf.length; 183 } 184 } 185 } 186 | Popular Tags |