KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > classfmt > MethodInfo


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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 JavaDoc {
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         // check the name of each attribute
42
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                 // need to resize
136
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         // u2 attribute_name_index + u4 attribute_length + u1 num_parameters
153
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 /**
171  * @param classFileBytes byte[]
172  * @param offsets int[]
173  * @param offset int
174  */

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 JavaDoc o) {
181     if (!(o instanceof MethodInfo)) {
182         throw new ClassCastException JavaDoc();
183     }
184
185     MethodInfo otherMethod = (MethodInfo) o;
186     int result = new String JavaDoc(this.getSelector()).compareTo(new String JavaDoc(otherMethod.getSelector()));
187     if (result != 0) return result;
188     return new String JavaDoc(this.getMethodDescriptor()).compareTo(new String JavaDoc(otherMethod.getMethodDescriptor()));
189 }
190 /**
191  * @return the annotations or null if there is none.
192  */

193 public IBinaryAnnotation[] getAnnotations() {
194     return null;
195 }
196 /**
197  * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames()
198  */

199 public char[][] getArgumentNames() {
200     if (this.argumentNames == null) {
201         readCodeAttribute();
202     }
203     return this.argumentNames;
204 }
205 public Object JavaDoc getDefaultValue() {
206     return null;
207 }
208 /**
209  * Answer the resolved names of the exception types in the
210  * class file format as specified in section 4.2 of the Java 2 VM spec
211  * or null if the array is empty.
212  *
213  * For example, java.lang.String is java/lang/String.
214  * @return char[][]
215  */

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             // decode the signature
226
this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
227         }
228         return this.signature;
229     }
230     return null;
231 }
232 /**
233  * Answer the receiver's method descriptor which describes the parameter &
234  * return types as specified in section 4.3.3 of the Java 2 VM spec.
235  *
236  * For example:
237  * - int foo(String) is (Ljava/lang/String;)I
238  * - void foo(Object[]) is (I)[Ljava/lang/Object;
239  * @return char[]
240  */

241 public char[] getMethodDescriptor() {
242     if (descriptor == null) {
243         // read the name
244
int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
245         descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
246     }
247     return descriptor;
248 }
249 /**
250  * Answer an int whose bits are set according the access constants
251  * defined by the VM spec.
252  * Set the AccDeprecated and AccSynthetic bits if necessary
253  * @return int
254  */

255 public int getModifiers() {
256     if (this.accessFlags == -1) {
257         // compute the accessflag. Don't forget the deprecated attribute
258
this.accessFlags = u2At(0);
259         readModifierRelatedAttributes();
260     }
261     return this.accessFlags;
262 }
263 public IBinaryAnnotation[] getParameterAnnotations(int index) {
264     return null;
265 }
266 /**
267  * Answer the name of the method.
268  *
269  * For a constructor, answer <init> & <clinit> for a clinit method.
270  * @return char[]
271  */

272 public char[] getSelector() {
273     if (name == null) {
274         // read the name
275
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 /**
284  * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
285  * will be therefore fully initialized and we can get rid of the bytes.
286  */

287 protected void initialize() {
288     getModifiers();
289     getSelector();
290     getMethodDescriptor();
291     getExceptionTypeNames();
292     getGenericSignature();
293     getArgumentNames();
294     reset();
295 }
296 /**
297  * Answer true if the method is a class initializer, false otherwise.
298  * @return boolean
299  */

300 public boolean isClinit() {
301     char[] selector = getSelector();
302     return selector[0] == '<' && selector.length == 8; // Can only match <clinit>
303
}
304 /**
305  * Answer true if the method is a constructor, false otherwise.
306  * @return boolean
307  */

308 public boolean isConstructor() {
309     char[] selector = getSelector();
310     return selector[0] == '<' && selector.length == 6; // Can only match <init>
311
}
312 /**
313  * Return true if the field is a synthetic method, false otherwise.
314  * @return boolean
315  */

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             // read the number of exception entries
327
int entriesNumber = u2At(readOffset + 6);
328             // place the readOffset at the beginning of the exceptions table
329
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         // test added for obfuscated .class file. See 79772
358
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 /**
381  * Answer the size of the receiver in bytes.
382  *
383  * @return int
384  */

385 public int sizeInBytes() {
386     return attributeBytes;
387 }
388
389 public String JavaDoc toString() {
390     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
391     toString(buffer);
392     return buffer.toString();
393 }
394 void toString(StringBuffer JavaDoc buffer) {
395     buffer.append(this.getClass().getName());
396     toStringContent(buffer);
397 }
398 protected void toStringContent(StringBuffer JavaDoc 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) //$NON-NLS-1$
407
+ ((modifiers & 0x0001) == 1 ? "public " : Util.EMPTY_STRING) //$NON-NLS-1$
408
+ ((modifiers & 0x0002) == 0x0002 ? "private " : Util.EMPTY_STRING) //$NON-NLS-1$
409
+ ((modifiers & 0x0004) == 0x0004 ? "protected " : Util.EMPTY_STRING) //$NON-NLS-1$
410
+ ((modifiers & 0x0008) == 0x000008 ? "static " : Util.EMPTY_STRING) //$NON-NLS-1$
411
+ ((modifiers & 0x0010) == 0x0010 ? "final " : Util.EMPTY_STRING) //$NON-NLS-1$
412
+ ((modifiers & 0x0040) == 0x0040 ? "bridge " : Util.EMPTY_STRING) //$NON-NLS-1$
413
+ ((modifiers & 0x0080) == 0x0080 ? "varargs " : Util.EMPTY_STRING)) //$NON-NLS-1$
414
.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             // resize
483
System.arraycopy(this.argumentNames, 0, (this.argumentNames = new char[this.argumentNamesIndex][]), 0, this.argumentNamesIndex);
484         }
485     }
486 }
487 }
488
Popular Tags