1 11 package org.eclipse.jdt.internal.compiler.classfmt; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; 16 import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; 17 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; 18 import org.eclipse.jdt.internal.compiler.util.Util; 19 20 public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Comparable { 21 static private final char[][] noException = CharOperation.NO_CHAR_CHAR; 22 static private final char[][] noArgumentNames = CharOperation.NO_CHAR_CHAR; 23 protected int accessFlags; 24 protected int attributeBytes; 25 protected char[] descriptor; 26 protected char[][] exceptionNames; 27 protected char[] name; 28 protected char[] signature; 29 protected int signatureUtf8Offset; 30 protected long tagBits; 31 protected char[][] argumentNames; 32 protected int argumentNamesIndex; 33 34 public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset) { 35 MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); 36 int attributesCount = methodInfo.u2At(6); 37 int readOffset = 8; 38 AnnotationInfo[] annotations = null; 39 AnnotationInfo[][] parameterAnnotations = null; 40 for (int i = 0; i < attributesCount; i++) { 41 int utf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset)] - methodInfo.structOffset; 43 char[] attributeName = methodInfo.utf8At(utf8Offset + 3, methodInfo.u2At(utf8Offset + 1)); 44 if (attributeName.length > 0) { 45 switch(attributeName[0]) { 46 case 'S' : 47 if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) 48 methodInfo.signatureUtf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset + 6)] - methodInfo.structOffset; 49 break; 50 case 'R' : 51 AnnotationInfo[] methodAnnotations = null; 52 AnnotationInfo[][] paramAnnotations = null; 53 if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { 54 methodAnnotations = decodeMethodAnnotations(readOffset, true, methodInfo); 55 } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { 56 methodAnnotations = decodeMethodAnnotations(readOffset, false, methodInfo); 57 } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName)) { 58 paramAnnotations = decodeParamAnnotations(readOffset, true, methodInfo); 59 } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName)) { 60 paramAnnotations = decodeParamAnnotations(readOffset, false, methodInfo); 61 } 62 if (methodAnnotations != null) { 63 if (annotations == null) { 64 annotations = methodAnnotations; 65 } else { 66 int length = annotations.length; 67 AnnotationInfo[] newAnnotations = new AnnotationInfo[length + methodAnnotations.length]; 68 System.arraycopy(annotations, 0, newAnnotations, 0, length); 69 System.arraycopy(methodAnnotations, 0, newAnnotations, length, methodAnnotations.length); 70 annotations = newAnnotations; 71 } 72 } else if (paramAnnotations != null) { 73 int numberOfParameters = paramAnnotations.length; 74 if (parameterAnnotations == null) { 75 parameterAnnotations = paramAnnotations; 76 } else { 77 for (int p = 0; p < numberOfParameters; p++) { 78 int numberOfAnnotations = paramAnnotations[p] == null ? 0 : paramAnnotations[p].length; 79 if (numberOfAnnotations > 0) { 80 if (parameterAnnotations[p] == null) { 81 parameterAnnotations[p] = paramAnnotations[p]; 82 } else { 83 int length = parameterAnnotations[p].length; 84 AnnotationInfo[] newAnnotations = new AnnotationInfo[length + numberOfAnnotations]; 85 System.arraycopy(parameterAnnotations[p], 0, newAnnotations, 0, length); 86 System.arraycopy(paramAnnotations[p], 0, newAnnotations, length, numberOfAnnotations); 87 parameterAnnotations[p] = newAnnotations; 88 } 89 } 90 } 91 } 92 } 93 break; 94 } 95 } 96 readOffset += (6 + methodInfo.u4At(readOffset + 2)); 97 } 98 methodInfo.attributeBytes = readOffset; 99 100 if (parameterAnnotations != null) 101 return new MethodInfoWithParameterAnnotations(methodInfo, annotations, parameterAnnotations); 102 if (annotations != null) 103 return new MethodInfoWithAnnotations(methodInfo, annotations); 104 return methodInfo; 105 } 106 static AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible, int numberOfAnnotations, MethodInfo methodInfo) { 107 AnnotationInfo[] result = new AnnotationInfo[numberOfAnnotations]; 108 int readOffset = offset; 109 for (int i = 0; i < numberOfAnnotations; i++) { 110 result[i] = new AnnotationInfo(methodInfo.reference, methodInfo.constantPoolOffsets, 111 readOffset + methodInfo.structOffset, runtimeVisible, false); 112 readOffset += result[i].readOffset; 113 } 114 return result; 115 } 116 static AnnotationInfo[] decodeMethodAnnotations(int offset, boolean runtimeVisible, MethodInfo methodInfo) { 117 int numberOfAnnotations = methodInfo.u2At(offset + 6); 118 if (numberOfAnnotations > 0) { 119 AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations, methodInfo); 120 if (runtimeVisible){ 121 int numStandardAnnotations = 0; 122 for( int i=0; i<numberOfAnnotations; i++ ){ 123 long standardAnnoTagBits = annos[i].standardAnnotationTagBits; 124 methodInfo.tagBits |= standardAnnoTagBits; 125 if(standardAnnoTagBits != 0){ 126 annos[i] = null; 127 numStandardAnnotations ++; 128 } 129 } 130 131 if( numStandardAnnotations != 0 ){ 132 if( numStandardAnnotations == numberOfAnnotations ) 133 return null; 134 135 AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ]; 137 int tmpIndex = 0; 138 for (int i = 0; i < numberOfAnnotations; i++) 139 if (annos[i] != null) 140 temp[tmpIndex ++] = annos[i]; 141 annos = temp; 142 } 143 } 144 return annos; 145 } 146 return null; 147 } 148 static AnnotationInfo[][] decodeParamAnnotations(int offset, boolean runtimeVisible, MethodInfo methodInfo) { 149 AnnotationInfo[][] allParamAnnotations = null; 150 int numberOfParameters = methodInfo.u1At(offset + 6); 151 if (numberOfParameters > 0) { 152 int readOffset = offset + 7; 154 for (int i=0 ; i < numberOfParameters; i++) { 155 int numberOfAnnotations = methodInfo.u2At(readOffset); 156 readOffset += 2; 157 if (numberOfAnnotations > 0) { 158 if (allParamAnnotations == null) 159 allParamAnnotations = new AnnotationInfo[numberOfParameters][]; 160 AnnotationInfo[] annos = decodeAnnotations(readOffset, runtimeVisible, numberOfAnnotations, methodInfo); 161 allParamAnnotations[i] = annos; 162 for (int aIndex = 0; aIndex < annos.length; aIndex++) 163 readOffset += annos[aIndex].readOffset; 164 } 165 } 166 } 167 return allParamAnnotations; 168 } 169 170 175 protected MethodInfo (byte classFileBytes[], int offsets[], int offset) { 176 super(classFileBytes, offsets, offset); 177 this.accessFlags = -1; 178 this.signatureUtf8Offset = -1; 179 } 180 public int compareTo(Object o) { 181 if (!(o instanceof MethodInfo)) { 182 throw new ClassCastException (); 183 } 184 185 MethodInfo otherMethod = (MethodInfo) o; 186 int result = new String (this.getSelector()).compareTo(new String (otherMethod.getSelector())); 187 if (result != 0) return result; 188 return new String (this.getMethodDescriptor()).compareTo(new String (otherMethod.getMethodDescriptor())); 189 } 190 193 public IBinaryAnnotation[] getAnnotations() { 194 return null; 195 } 196 199 public char[][] getArgumentNames() { 200 if (this.argumentNames == null) { 201 readCodeAttribute(); 202 } 203 return this.argumentNames; 204 } 205 public Object getDefaultValue() { 206 return null; 207 } 208 216 public char[][] getExceptionTypeNames() { 217 if (exceptionNames == null) { 218 readExceptionAttributes(); 219 } 220 return exceptionNames; 221 } 222 public char[] getGenericSignature() { 223 if (this.signatureUtf8Offset != -1) { 224 if (this.signature == null) { 225 this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1)); 227 } 228 return this.signature; 229 } 230 return null; 231 } 232 241 public char[] getMethodDescriptor() { 242 if (descriptor == null) { 243 int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset; 245 descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 246 } 247 return descriptor; 248 } 249 255 public int getModifiers() { 256 if (this.accessFlags == -1) { 257 this.accessFlags = u2At(0); 259 readModifierRelatedAttributes(); 260 } 261 return this.accessFlags; 262 } 263 public IBinaryAnnotation[] getParameterAnnotations(int index) { 264 return null; 265 } 266 272 public char[] getSelector() { 273 if (name == null) { 274 int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset; 276 name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 277 } 278 return name; 279 } 280 public long getTagBits() { 281 return this.tagBits; 282 } 283 287 protected void initialize() { 288 getModifiers(); 289 getSelector(); 290 getMethodDescriptor(); 291 getExceptionTypeNames(); 292 getGenericSignature(); 293 getArgumentNames(); 294 reset(); 295 } 296 300 public boolean isClinit() { 301 char[] selector = getSelector(); 302 return selector[0] == '<' && selector.length == 8; } 304 308 public boolean isConstructor() { 309 char[] selector = getSelector(); 310 return selector[0] == '<' && selector.length == 6; } 312 316 public boolean isSynthetic() { 317 return (getModifiers() & ClassFileConstants.AccSynthetic) != 0; 318 } 319 private void readExceptionAttributes() { 320 int attributesCount = u2At(6); 321 int readOffset = 8; 322 for (int i = 0; i < attributesCount; i++) { 323 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; 324 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 325 if (CharOperation.equals(attributeName, AttributeNamesConstants.ExceptionsName)) { 326 int entriesNumber = u2At(readOffset + 6); 328 readOffset += 8; 330 if (entriesNumber == 0) { 331 exceptionNames = noException; 332 } else { 333 exceptionNames = new char[entriesNumber][]; 334 for (int j = 0; j < entriesNumber; j++) { 335 utf8Offset = 336 constantPoolOffsets[u2At( 337 constantPoolOffsets[u2At(readOffset)] - structOffset + 1)] 338 - structOffset; 339 exceptionNames[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 340 readOffset += 2; 341 } 342 } 343 } else { 344 readOffset += (6 + u4At(readOffset + 2)); 345 } 346 } 347 if (exceptionNames == null) { 348 exceptionNames = noException; 349 } 350 } 351 private void readModifierRelatedAttributes() { 352 int attributesCount = u2At(6); 353 int readOffset = 8; 354 for (int i = 0; i < attributesCount; i++) { 355 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; 356 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 357 if (attributeName.length != 0) { 359 switch(attributeName[0]) { 360 case 'D' : 361 if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName)) 362 this.accessFlags |= ClassFileConstants.AccDeprecated; 363 break; 364 case 'S' : 365 if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) 366 this.accessFlags |= ClassFileConstants.AccSynthetic; 367 break; 368 case 'A' : 369 if (CharOperation.equals(attributeName, AttributeNamesConstants.AnnotationDefaultName)) 370 this.accessFlags |= ClassFileConstants.AccAnnotationDefault; 371 break; 372 case 'V' : 373 if (CharOperation.equals(attributeName, AttributeNamesConstants.VarargsName)) 374 this.accessFlags |= ClassFileConstants.AccVarargs; 375 } 376 } 377 readOffset += (6 + u4At(readOffset + 2)); 378 } 379 } 380 385 public int sizeInBytes() { 386 return attributeBytes; 387 } 388 389 public String toString() { 390 StringBuffer buffer = new StringBuffer (); 391 toString(buffer); 392 return buffer.toString(); 393 } 394 void toString(StringBuffer buffer) { 395 buffer.append(this.getClass().getName()); 396 toStringContent(buffer); 397 } 398 protected void toStringContent(StringBuffer buffer) { 399 int modifiers = getModifiers(); 400 char[] desc = getGenericSignature(); 401 if (desc == null) 402 desc = getMethodDescriptor(); 403 buffer 404 .append('{') 405 .append( 406 ((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : Util.EMPTY_STRING) + ((modifiers & 0x0001) == 1 ? "public " : Util.EMPTY_STRING) + ((modifiers & 0x0002) == 0x0002 ? "private " : Util.EMPTY_STRING) + ((modifiers & 0x0004) == 0x0004 ? "protected " : Util.EMPTY_STRING) + ((modifiers & 0x0008) == 0x000008 ? "static " : Util.EMPTY_STRING) + ((modifiers & 0x0010) == 0x0010 ? "final " : Util.EMPTY_STRING) + ((modifiers & 0x0040) == 0x0040 ? "bridge " : Util.EMPTY_STRING) + ((modifiers & 0x0080) == 0x0080 ? "varargs " : Util.EMPTY_STRING)) .append(getSelector()) 415 .append(desc) 416 .append('}'); 417 } 418 private void readCodeAttribute() { 419 int attributesCount = u2At(6); 420 int readOffset = 8; 421 if (attributesCount != 0) { 422 for (int i = 0; i < attributesCount; i++) { 423 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; 424 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 425 if (CharOperation.equals(attributeName, AttributeNamesConstants.CodeName)) { 426 decodeCodeAttribute(readOffset); 427 if (this.argumentNames == null) { 428 this.argumentNames = noArgumentNames; 429 } 430 return; 431 } else { 432 readOffset += (6 + u4At(readOffset + 2)); 433 } 434 } 435 } 436 this.argumentNames = noArgumentNames; 437 } 438 private void decodeCodeAttribute(int offset) { 439 int readOffset = offset + 10; 440 int codeLength = (int) u4At(readOffset); 441 readOffset += (4 + codeLength); 442 int exceptionTableLength = u2At(readOffset); 443 readOffset += 2; 444 if (exceptionTableLength != 0) { 445 for (int i = 0; i < exceptionTableLength; i++) { 446 readOffset += 8; 447 } 448 } 449 int attributesCount = u2At(readOffset); 450 readOffset += 2; 451 for (int i = 0; i < attributesCount; i++) { 452 int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; 453 char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 454 if (CharOperation.equals(attributeName, AttributeNamesConstants.LocalVariableTableName)) { 455 decodeLocalVariableAttribute(readOffset, codeLength); 456 } 457 readOffset += (6 + u4At(readOffset + 2)); 458 } 459 } 460 private void decodeLocalVariableAttribute(int offset, int codeLength) { 461 int readOffset = offset + 6; 462 final int length = u2At(readOffset); 463 if (length != 0) { 464 readOffset += 2; 465 this.argumentNames = new char[length][]; 466 this.argumentNamesIndex = 0; 467 for (int i = 0; i < length; i++) { 468 int startPC = u2At(readOffset); 469 if (startPC == 0) { 470 int nameIndex = u2At(4 + readOffset); 471 int utf8Offset = constantPoolOffsets[nameIndex] - structOffset; 472 char[] localVariableName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); 473 if (!CharOperation.equals(localVariableName, ConstantPool.This)) { 474 this.argumentNames[this.argumentNamesIndex++] = localVariableName; 475 } 476 } else { 477 break; 478 } 479 readOffset += 10; 480 } 481 if (this.argumentNamesIndex != this.argumentNames.length) { 482 System.arraycopy(this.argumentNames, 0, (this.argumentNames = new char[this.argumentNamesIndex][]), 0, this.argumentNamesIndex); 484 } 485 } 486 } 487 } 488 | Popular Tags |