1 11 package org.eclipse.jdt.internal.core.util; 12 13 16 import org.eclipse.jdt.core.compiler.CharOperation; 17 import org.eclipse.jdt.core.util.ClassFormatException; 18 import org.eclipse.jdt.core.util.IAttributeNamesConstants; 19 import org.eclipse.jdt.core.util.IClassFileAttribute; 20 import org.eclipse.jdt.core.util.IClassFileReader; 21 import org.eclipse.jdt.core.util.IConstantPool; 22 import org.eclipse.jdt.core.util.IConstantPoolConstant; 23 import org.eclipse.jdt.core.util.IFieldInfo; 24 import org.eclipse.jdt.core.util.IInnerClassesAttribute; 25 import org.eclipse.jdt.core.util.IMethodInfo; 26 import org.eclipse.jdt.core.util.IModifierConstants; 27 import org.eclipse.jdt.core.util.ISourceAttribute; 28 import org.eclipse.jdt.internal.compiler.util.Util; 29 30 public class ClassFileReader extends ClassFileStruct implements IClassFileReader { 31 private static final IFieldInfo[] NO_FIELD_INFOS = new IFieldInfo[0]; 32 private static final char[][] NO_INTERFACES_NAMES = CharOperation.NO_CHAR_CHAR; 33 private static final IMethodInfo[] NO_METHOD_INFOS = new IMethodInfo[0]; 34 private int accessFlags; 35 private IClassFileAttribute[] attributes; 36 private int attributesCount; 37 private char[] className; 38 private int classNameIndex; 39 40 private IConstantPool constantPool; 41 private IFieldInfo[] fields; 42 private int fieldsCount; 43 private IInnerClassesAttribute innerClassesAttribute; 44 private int[] interfaceIndexes; 45 private char[][] interfaceNames; 46 private int interfacesCount; 47 private int magicNumber; 48 private int majorVersion; 49 private IMethodInfo[] methods; 50 private int methodsCount; 51 private int minorVersion; 52 private ISourceAttribute sourceFileAttribute; 53 private char[] superclassName; 54 private int superclassNameIndex; 55 56 67 public ClassFileReader(byte[] classFileBytes, int decodingFlags) throws ClassFormatException { 68 69 int constantPoolCount; 74 int[] constantPoolOffsets; 75 try { 76 this.magicNumber = (int) u4At(classFileBytes, 0, 0); 77 if (this.magicNumber != 0xCAFEBABE) { 78 throw new ClassFormatException(ClassFormatException.INVALID_MAGIC_NUMBER); 79 } 80 81 int readOffset = 10; 82 this.minorVersion = this.u2At(classFileBytes, 4, 0); 83 this.majorVersion = this.u2At(classFileBytes, 6, 0); 84 85 if ((decodingFlags & IClassFileReader.CONSTANT_POOL) == 0) { 86 return; 88 } 89 90 constantPoolCount = this.u2At(classFileBytes, 8, 0); 91 constantPoolOffsets = new int[constantPoolCount]; 93 for (int i = 1; i < constantPoolCount; i++) { 94 int tag = this.u1At(classFileBytes, readOffset, 0); 95 switch (tag) { 96 case IConstantPoolConstant.CONSTANT_Utf8 : 97 constantPoolOffsets[i] = readOffset; 98 readOffset += u2At(classFileBytes, readOffset + 1, 0); 99 readOffset += IConstantPoolConstant.CONSTANT_Utf8_SIZE; 100 break; 101 case IConstantPoolConstant.CONSTANT_Integer : 102 constantPoolOffsets[i] = readOffset; 103 readOffset += IConstantPoolConstant.CONSTANT_Integer_SIZE; 104 break; 105 case IConstantPoolConstant.CONSTANT_Float : 106 constantPoolOffsets[i] = readOffset; 107 readOffset += IConstantPoolConstant.CONSTANT_Float_SIZE; 108 break; 109 case IConstantPoolConstant.CONSTANT_Long : 110 constantPoolOffsets[i] = readOffset; 111 readOffset += IConstantPoolConstant.CONSTANT_Long_SIZE; 112 i++; 113 break; 114 case IConstantPoolConstant.CONSTANT_Double : 115 constantPoolOffsets[i] = readOffset; 116 readOffset += IConstantPoolConstant.CONSTANT_Double_SIZE; 117 i++; 118 break; 119 case IConstantPoolConstant.CONSTANT_Class : 120 constantPoolOffsets[i] = readOffset; 121 readOffset += IConstantPoolConstant.CONSTANT_Class_SIZE; 122 break; 123 case IConstantPoolConstant.CONSTANT_String : 124 constantPoolOffsets[i] = readOffset; 125 readOffset += IConstantPoolConstant.CONSTANT_String_SIZE; 126 break; 127 case IConstantPoolConstant.CONSTANT_Fieldref : 128 constantPoolOffsets[i] = readOffset; 129 readOffset += IConstantPoolConstant.CONSTANT_Fieldref_SIZE; 130 break; 131 case IConstantPoolConstant.CONSTANT_Methodref : 132 constantPoolOffsets[i] = readOffset; 133 readOffset += IConstantPoolConstant.CONSTANT_Methodref_SIZE; 134 break; 135 case IConstantPoolConstant.CONSTANT_InterfaceMethodref : 136 constantPoolOffsets[i] = readOffset; 137 readOffset += IConstantPoolConstant.CONSTANT_InterfaceMethodref_SIZE; 138 break; 139 case IConstantPoolConstant.CONSTANT_NameAndType : 140 constantPoolOffsets[i] = readOffset; 141 readOffset += IConstantPoolConstant.CONSTANT_NameAndType_SIZE; 142 break; 143 default: 144 throw new ClassFormatException(ClassFormatException.INVALID_TAG_CONSTANT); 145 } 146 } 147 148 this.constantPool = new ConstantPool(classFileBytes, constantPoolOffsets); 149 this.accessFlags = u2At(classFileBytes, readOffset, 0); 151 readOffset += 2; 152 153 this.classNameIndex = u2At(classFileBytes, readOffset, 0); 155 this.className = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.classNameIndex); 156 readOffset += 2; 157 158 this.superclassNameIndex = u2At(classFileBytes, readOffset, 0); 160 readOffset += 2; 161 if (superclassNameIndex != 0) { 164 this.superclassName = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.superclassNameIndex); 165 } 166 167 this.interfacesCount = u2At(classFileBytes, readOffset, 0); 169 readOffset += 2; 170 this.interfaceNames = NO_INTERFACES_NAMES; 171 this.interfaceIndexes = Util.EMPTY_INT_ARRAY; 172 if (this.interfacesCount != 0) { 173 if ((decodingFlags & IClassFileReader.SUPER_INTERFACES) != IClassFileReader.CONSTANT_POOL) { 174 this.interfaceNames = new char[this.interfacesCount][]; 175 this.interfaceIndexes = new int[this.interfacesCount]; 176 for (int i = 0; i < this.interfacesCount; i++) { 177 this.interfaceIndexes[i] = u2At(classFileBytes, readOffset, 0); 178 this.interfaceNames[i] = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.interfaceIndexes[i]); 179 readOffset += 2; 180 } 181 } else { 182 readOffset += (2 * this.interfacesCount); 183 } 184 } 185 this.fieldsCount = u2At(classFileBytes, readOffset, 0); 187 readOffset += 2; 188 this.fields = NO_FIELD_INFOS; 189 if (this.fieldsCount != 0) { 190 if ((decodingFlags & IClassFileReader.FIELD_INFOS) != IClassFileReader.CONSTANT_POOL) { 191 FieldInfo field; 192 this.fields = new FieldInfo[this.fieldsCount]; 193 for (int i = 0; i < this.fieldsCount; i++) { 194 field = new FieldInfo(classFileBytes, this.constantPool, readOffset); 195 this.fields[i] = field; 196 readOffset += field.sizeInBytes(); 197 } 198 } else { 199 for (int i = 0; i < this.fieldsCount; i++) { 200 int attributeCountForField = u2At(classFileBytes, 6, readOffset); 201 readOffset += 8; 202 if (attributeCountForField != 0) { 203 for (int j = 0; j < attributeCountForField; j++) { 204 int attributeLength = (int) u4At(classFileBytes, 2, readOffset); 205 readOffset += (6 + attributeLength); 206 } 207 } 208 } 209 } 210 } 211 this.methodsCount = u2At(classFileBytes, readOffset, 0); 213 readOffset += 2; 214 this.methods = NO_METHOD_INFOS; 215 if (this.methodsCount != 0) { 216 if ((decodingFlags & IClassFileReader.METHOD_INFOS) != IClassFileReader.CONSTANT_POOL) { 217 this.methods = new MethodInfo[this.methodsCount]; 218 MethodInfo method; 219 for (int i = 0; i < this.methodsCount; i++) { 220 method = new MethodInfo(classFileBytes, this.constantPool, readOffset, decodingFlags); 221 this.methods[i] = method; 222 readOffset += method.sizeInBytes(); 223 } 224 } else { 225 for (int i = 0; i < this.methodsCount; i++) { 226 int attributeCountForMethod = u2At(classFileBytes, 6, readOffset); 227 readOffset += 8; 228 if (attributeCountForMethod != 0) { 229 for (int j = 0; j < attributeCountForMethod; j++) { 230 int attributeLength = (int) u4At(classFileBytes, 2, readOffset); 231 readOffset += (6 + attributeLength); 232 } 233 } 234 } 235 } 236 } 237 238 this.attributesCount = u2At(classFileBytes, readOffset, 0); 240 readOffset += 2; 241 242 int attributesIndex = 0; 243 this.attributes = ClassFileAttribute.NO_ATTRIBUTES; 244 if (this.attributesCount != 0) { 245 if ((decodingFlags & IClassFileReader.CLASSFILE_ATTRIBUTES) != IClassFileReader.CONSTANT_POOL) { 246 this.attributes = new IClassFileAttribute[this.attributesCount]; 247 for (int i = 0; i < attributesCount; i++) { 248 int utf8Offset = constantPoolOffsets[u2At(classFileBytes, readOffset, 0)]; 249 char[] attributeName = utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0)); 250 if (equals(attributeName, IAttributeNamesConstants.INNER_CLASSES)) { 251 this.innerClassesAttribute = new InnerClassesAttribute(classFileBytes, this.constantPool, readOffset); 252 this.attributes[attributesIndex++] = this.innerClassesAttribute; 253 } else if (equals(attributeName, IAttributeNamesConstants.SOURCE)) { 254 this.sourceFileAttribute = new SourceFileAttribute(classFileBytes, this.constantPool, readOffset); 255 this.attributes[attributesIndex++] = this.sourceFileAttribute; 256 } else if (equals(attributeName, IAttributeNamesConstants.ENCLOSING_METHOD)) { 257 this.attributes[attributesIndex++] = new EnclosingMethodAttribute(classFileBytes, this.constantPool, readOffset); 258 } else if (equals(attributeName, IAttributeNamesConstants.SIGNATURE)) { 259 this.attributes[attributesIndex++] = new SignatureAttribute(classFileBytes, this.constantPool, readOffset); 260 } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS)) { 261 this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset); 262 } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) { 263 this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset); 264 } else { 265 this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset); 266 } 267 readOffset += (6 + u4At(classFileBytes, readOffset + 2, 0)); 268 } 269 } else { 270 for (int i = 0; i < attributesCount; i++) { 271 readOffset += (6 + u4At(classFileBytes, readOffset + 2, 0)); 272 } 273 } 274 } 275 if (readOffset != classFileBytes.length) { 276 throw new ClassFormatException(ClassFormatException.TOO_MANY_BYTES); 277 } 278 } catch(ClassFormatException e) { 279 throw e; 280 } catch (Exception e) { 281 e.printStackTrace(); 282 throw new ClassFormatException(ClassFormatException.ERROR_TRUNCATED_INPUT); 283 } 284 } 285 286 289 public int getAccessFlags() { 290 return this.accessFlags; 291 } 292 295 public int getAttributeCount() { 296 return this.attributesCount; 297 } 298 299 302 public IClassFileAttribute[] getAttributes() { 303 return this.attributes; 304 } 305 306 309 public int getClassIndex() { 310 return this.classNameIndex; 311 } 312 313 316 public char[] getClassName() { 317 return this.className; 318 } 319 320 private char[] getConstantClassNameAt(byte[] classFileBytes, int[] constantPoolOffsets, int constantPoolIndex) { 321 int utf8Offset = constantPoolOffsets[u2At(classFileBytes, constantPoolOffsets[constantPoolIndex] + 1, 0)]; 322 return utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0)); 323 } 324 325 328 public IConstantPool getConstantPool() { 329 return this.constantPool; 330 } 331 334 public IFieldInfo[] getFieldInfos() { 335 return this.fields; 336 } 337 338 341 public int getFieldsCount() { 342 return this.fieldsCount; 343 } 344 345 348 public IInnerClassesAttribute getInnerClassesAttribute() { 349 return this.innerClassesAttribute; 350 } 351 352 355 public int[] getInterfaceIndexes() { 356 return this.interfaceIndexes; 357 } 358 359 362 public char[][] getInterfaceNames() { 363 return this.interfaceNames; 364 } 365 366 369 public int getMagic() { 370 return this.magicNumber; 371 } 372 373 376 public int getMajorVersion() { 377 return this.majorVersion; 378 } 379 380 383 public IMethodInfo[] getMethodInfos() { 384 return this.methods; 385 } 386 387 390 public int getMethodsCount() { 391 return this.methodsCount; 392 } 393 394 397 public int getMinorVersion() { 398 return this.minorVersion; 399 } 400 401 404 public ISourceAttribute getSourceFileAttribute() { 405 return this.sourceFileAttribute; 406 } 407 408 411 public int getSuperclassIndex() { 412 return this.superclassNameIndex; 413 } 414 415 418 public char[] getSuperclassName() { 419 return this.superclassName; 420 } 421 424 public boolean isClass() { 425 return !isInterface(); 426 } 427 428 431 public boolean isInterface() { 432 return (getAccessFlags() & IModifierConstants.ACC_INTERFACE) != 0; 433 } 434 } 435 | Popular Tags |