KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > util > Disassembler


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.core.util;
12
13 import java.io.PrintWriter JavaDoc;
14 import java.io.StringWriter JavaDoc;
15
16 import org.eclipse.jdt.core.JavaCore;
17 import org.eclipse.jdt.core.Signature;
18 import org.eclipse.jdt.core.compiler.CharOperation;
19 import org.eclipse.jdt.core.util.*;
20 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
21 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
22
23 /**
24  * Disassembler of .class files. It generates an output in the Writer that looks close to
25  * the javap output.
26  */

27 public class Disassembler extends ClassFileBytesDisassembler {
28
29     private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray();
30     private static final String JavaDoc VERSION_UNKNOWN = Messages.classfileformat_versionUnknown;
31
32     private boolean appendModifier(StringBuffer JavaDoc buffer, int accessFlags, int modifierConstant, String JavaDoc modifier, boolean firstModifier) {
33         if ((accessFlags & modifierConstant) != 0) {
34             if (!firstModifier) {
35                 buffer.append(Messages.disassembler_space);
36             }
37             if (firstModifier) {
38                 firstModifier = false;
39             }
40             buffer.append(modifier);
41         }
42         return firstModifier;
43     }
44     
45     private void decodeModifiers(StringBuffer JavaDoc buffer, int accessFlags, int[] checkBits) {
46         decodeModifiers(buffer, accessFlags, false, false, checkBits);
47     }
48     
49     private void decodeModifiers(StringBuffer JavaDoc buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) {
50         if (checkBits == null) return;
51         boolean firstModifier = true;
52         for (int i = 0, max = checkBits.length; i < max; i++) {
53             switch(checkBits[i]) {
54                 case IModifierConstants.ACC_PUBLIC :
55                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
56
break;
57                 case IModifierConstants.ACC_PROTECTED :
58                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
59
break;
60                 case IModifierConstants.ACC_PRIVATE :
61                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
62
break;
63                 case IModifierConstants.ACC_ABSTRACT :
64                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
65
break;
66                 case IModifierConstants.ACC_STATIC :
67                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
68
break;
69                 case IModifierConstants.ACC_FINAL :
70                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
71
break;
72                 case IModifierConstants.ACC_SYNCHRONIZED :
73                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$
74
break;
75                 case IModifierConstants.ACC_NATIVE :
76                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$
77
break;
78                 case IModifierConstants.ACC_STRICT :
79                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$
80
break;
81                 case IModifierConstants.ACC_TRANSIENT :
82                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$
83
break;
84                 case IModifierConstants.ACC_VOLATILE :
85                 // case IModifierConstants.ACC_BRIDGE :
86
if (asBridge) {
87                         firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$
88
} else {
89                         firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$
90
}
91                     break;
92                 case IModifierConstants.ACC_ENUM :
93                     firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$
94
break;
95             }
96         }
97         if (!firstModifier) {
98             if (!printDefault) buffer.append(Messages.disassembler_space);
99         } else if (printDefault) {
100             // no modifier: package default visibility
101
buffer.append("default"); //$NON-NLS-1$
102
}
103     }
104     
105     private void decodeModifiersForField(StringBuffer JavaDoc buffer, int accessFlags) {
106         decodeModifiers(buffer, accessFlags, new int[] {
107                 IModifierConstants.ACC_PUBLIC,
108                 IModifierConstants.ACC_PROTECTED,
109                 IModifierConstants.ACC_PRIVATE,
110                 IModifierConstants.ACC_STATIC,
111                 IModifierConstants.ACC_FINAL,
112                 IModifierConstants.ACC_TRANSIENT,
113                 IModifierConstants.ACC_VOLATILE,
114                 IModifierConstants.ACC_ENUM
115         });
116     }
117
118     private void decodeModifiersForFieldForWorkingCopy(StringBuffer JavaDoc buffer, int accessFlags) {
119         decodeModifiers(buffer, accessFlags, new int[] {
120                 IModifierConstants.ACC_PUBLIC,
121                 IModifierConstants.ACC_PROTECTED,
122                 IModifierConstants.ACC_PRIVATE,
123                 IModifierConstants.ACC_STATIC,
124                 IModifierConstants.ACC_FINAL,
125                 IModifierConstants.ACC_TRANSIENT,
126                 IModifierConstants.ACC_VOLATILE,
127         });
128     }
129     
130     private final void decodeModifiersForInnerClasses(StringBuffer JavaDoc buffer, int accessFlags, boolean printDefault) {
131         decodeModifiers(buffer, accessFlags, printDefault, false, new int[] {
132                 IModifierConstants.ACC_PUBLIC,
133                 IModifierConstants.ACC_PROTECTED,
134                 IModifierConstants.ACC_PRIVATE,
135                 IModifierConstants.ACC_ABSTRACT,
136                 IModifierConstants.ACC_STATIC,
137                 IModifierConstants.ACC_FINAL,
138         });
139     }
140
141     private final void decodeModifiersForMethod(StringBuffer JavaDoc buffer, int accessFlags) {
142         decodeModifiers(buffer, accessFlags, false, true, new int[] {
143                 IModifierConstants.ACC_PUBLIC,
144                 IModifierConstants.ACC_PROTECTED,
145                 IModifierConstants.ACC_PRIVATE,
146                 IModifierConstants.ACC_ABSTRACT,
147                 IModifierConstants.ACC_STATIC,
148                 IModifierConstants.ACC_FINAL,
149                 IModifierConstants.ACC_SYNCHRONIZED,
150                 IModifierConstants.ACC_NATIVE,
151                 IModifierConstants.ACC_STRICT,
152                 IModifierConstants.ACC_BRIDGE,
153         });
154     }
155
156     private final void decodeModifiersForType(StringBuffer JavaDoc buffer, int accessFlags) {
157         decodeModifiers(buffer, accessFlags, new int[] {
158                 IModifierConstants.ACC_PUBLIC,
159                 IModifierConstants.ACC_ABSTRACT,
160                 IModifierConstants.ACC_FINAL,
161         });
162     }
163     public static String JavaDoc escapeString(String JavaDoc s) {
164         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
165         for (int i = 0, max = s.length(); i < max; i++) {
166             char c = s.charAt(i);
167             switch(c) {
168                 case '\b' :
169                     buffer.append("\\b"); //$NON-NLS-1$
170
break;
171                 case '\t' :
172                     buffer.append("\\t"); //$NON-NLS-1$
173
break;
174                 case '\n' :
175                     buffer.append("\\n"); //$NON-NLS-1$
176
break;
177                 case '\f' :
178                     buffer.append("\\f"); //$NON-NLS-1$
179
break;
180                 case '\r' :
181                     buffer.append("\\r"); //$NON-NLS-1$
182
break;
183                 case '\0' :
184                     buffer.append("\\0"); //$NON-NLS-1$
185
break;
186                 case '\1' :
187                     buffer.append("\\1"); //$NON-NLS-1$
188
break;
189                 case '\2' :
190                     buffer.append("\\2"); //$NON-NLS-1$
191
break;
192                 case '\3' :
193                     buffer.append("\\3"); //$NON-NLS-1$
194
break;
195                 case '\4' :
196                     buffer.append("\\4"); //$NON-NLS-1$
197
break;
198                 case '\5' :
199                     buffer.append("\\5"); //$NON-NLS-1$
200
break;
201                 case '\6' :
202                     buffer.append("\\6"); //$NON-NLS-1$
203
break;
204                 case '\7' :
205                     buffer.append("\\7"); //$NON-NLS-1$
206
break;
207                 default:
208                     buffer.append(c);
209             }
210         }
211         return buffer.toString();
212     }
213
214     static String JavaDoc decodeStringValue(char[] chars) {
215         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
216         for (int i = 0, max = chars.length; i < max; i++) {
217             char c = chars[i];
218             switch(c) {
219                 case '\b' :
220                     buffer.append("\\b"); //$NON-NLS-1$
221
break;
222                 case '\t' :
223                     buffer.append("\\t"); //$NON-NLS-1$
224
break;
225                 case '\n' :
226                     buffer.append("\\n"); //$NON-NLS-1$
227
break;
228                 case '\f' :
229                     buffer.append("\\f"); //$NON-NLS-1$
230
break;
231                 case '\r' :
232                     buffer.append("\\r"); //$NON-NLS-1$
233
break;
234                 case '\0' :
235                     buffer.append("\\0"); //$NON-NLS-1$
236
break;
237                 case '\1' :
238                     buffer.append("\\1"); //$NON-NLS-1$
239
break;
240                 case '\2' :
241                     buffer.append("\\2"); //$NON-NLS-1$
242
break;
243                 case '\3' :
244                     buffer.append("\\3"); //$NON-NLS-1$
245
break;
246                 case '\4' :
247                     buffer.append("\\4"); //$NON-NLS-1$
248
break;
249                 case '\5' :
250                     buffer.append("\\5"); //$NON-NLS-1$
251
break;
252                 case '\6' :
253                     buffer.append("\\6"); //$NON-NLS-1$
254
break;
255                 case '\7' :
256                     buffer.append("\\7"); //$NON-NLS-1$
257
break;
258                 default:
259                     buffer.append(c);
260             }
261         }
262         return buffer.toString();
263     }
264
265     static String JavaDoc decodeStringValue(String JavaDoc s) {
266         return decodeStringValue(s.toCharArray());
267     }
268
269     /**
270      * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String)
271      */

272     public String JavaDoc disassemble(byte[] classFileBytes, String JavaDoc lineSeparator) throws ClassFormatException {
273         try {
274             return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT);
275         } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
276             StringWriter JavaDoc stringWriter = new StringWriter JavaDoc();
277             PrintWriter JavaDoc writer = new PrintWriter JavaDoc(stringWriter);
278             e.printStackTrace(writer);
279             writer.flush();
280             writer.close();
281             throw new ClassFormatException(String.valueOf(stringWriter.getBuffer()));
282         }
283     }
284
285     /**
286      * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String, int)
287      */

288     public String JavaDoc disassemble(byte[] classFileBytes, String JavaDoc lineSeparator, int mode) throws ClassFormatException {
289         try {
290             return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode);
291         } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
292             StringWriter JavaDoc stringWriter = new StringWriter JavaDoc();
293             PrintWriter JavaDoc writer = new PrintWriter JavaDoc(stringWriter);
294             e.printStackTrace(writer);
295             writer.flush();
296             writer.close();
297             throw new ClassFormatException(String.valueOf(stringWriter.getBuffer()));
298         }
299     }
300
301     private void disassemble(IAnnotation annotation, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
302         writeNewLine(buffer, lineSeparator, tabNumber + 1);
303         final int typeIndex = annotation.getTypeIndex();
304         final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
305         buffer.append(
306             Messages.bind(Messages.disassembler_annotationentrystart, new String JavaDoc[] {
307                 Integer.toString(typeIndex),
308                 new String JavaDoc(Signature.toCharArray(typeName))
309             }));
310         final IAnnotationComponent[] components = annotation.getComponents();
311         for (int i = 0, max = components.length; i < max; i++) {
312             disassemble(components[i], buffer, lineSeparator, tabNumber + 1);
313         }
314         writeNewLine(buffer, lineSeparator, tabNumber + 1);
315         buffer.append(Messages.disassembler_annotationentryend);
316     }
317
318     private void disassemble(IAnnotationComponent annotationComponent, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
319         writeNewLine(buffer, lineSeparator, tabNumber + 1);
320         buffer.append(
321             Messages.bind(Messages.disassembler_annotationcomponent,
322                 new String JavaDoc[] {
323                     Integer.toString(annotationComponent.getComponentNameIndex()),
324                     new String JavaDoc(annotationComponent.getComponentName())
325                 }));
326         disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1);
327     }
328
329     private void disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
330         switch(annotationComponentValue.getTag()) {
331             case IAnnotationComponentValue.BYTE_TAG:
332             case IAnnotationComponentValue.CHAR_TAG:
333             case IAnnotationComponentValue.DOUBLE_TAG:
334             case IAnnotationComponentValue.FLOAT_TAG:
335             case IAnnotationComponentValue.INTEGER_TAG:
336             case IAnnotationComponentValue.LONG_TAG:
337             case IAnnotationComponentValue.SHORT_TAG:
338             case IAnnotationComponentValue.BOOLEAN_TAG:
339             case IAnnotationComponentValue.STRING_TAG:
340                 IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
341                 String JavaDoc value = null;
342                 switch(constantPoolEntry.getKind()) {
343                     case IConstantPoolConstant.CONSTANT_Long :
344                         value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
345
break;
346                     case IConstantPoolConstant.CONSTANT_Float :
347                         value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
348
break;
349                     case IConstantPoolConstant.CONSTANT_Double :
350                         value = Double.toString(constantPoolEntry.getDoubleValue());
351                         break;
352                     case IConstantPoolConstant.CONSTANT_Integer:
353                         switch(annotationComponentValue.getTag()) {
354                             case IAnnotationComponentValue.CHAR_TAG :
355                                 value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
356
break;
357                             case IAnnotationComponentValue.BOOLEAN_TAG :
358                                 value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
359
break;
360                             case IAnnotationComponentValue.BYTE_TAG :
361                                 value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
362
break;
363                             case IAnnotationComponentValue.SHORT_TAG :
364                                 value = "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
365
break;
366                             case IAnnotationComponentValue.INTEGER_TAG :
367                                 value = "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
368
}
369                         break;
370                     case IConstantPoolConstant.CONSTANT_Utf8:
371                         value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
372
}
373                 buffer.append(Messages.bind(Messages.disassembler_annotationdefaultvalue, value));
374                 break;
375             case IAnnotationComponentValue.ENUM_TAG:
376                 final int enumConstantTypeNameIndex = annotationComponentValue.getEnumConstantTypeNameIndex();
377                 final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
378                 final int enumConstantNameIndex = annotationComponentValue.getEnumConstantNameIndex();
379                 final char[] constantName = annotationComponentValue.getEnumConstantName();
380                 buffer.append(Messages.bind(Messages.disassembler_annotationenumvalue,
381                     new String JavaDoc[] {
382                         Integer.toString(enumConstantTypeNameIndex),
383                         Integer.toString(enumConstantNameIndex),
384                         new String JavaDoc(Signature.toCharArray(typeName)),
385                         new String JavaDoc(constantName)
386                     }));
387                 break;
388             case IAnnotationComponentValue.CLASS_TAG:
389                 final int classIndex = annotationComponentValue.getClassInfoIndex();
390                 constantPoolEntry = annotationComponentValue.getClassInfo();
391                 final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
392                 buffer.append(Messages.bind(Messages.disassembler_annotationclassvalue,
393                     new String JavaDoc[] {
394                         Integer.toString(classIndex),
395                         new String JavaDoc(Signature.toCharArray(className))
396                     }));
397                 break;
398             case IAnnotationComponentValue.ANNOTATION_TAG:
399                 buffer.append(Messages.disassembler_annotationannotationvalue);
400                 IAnnotation annotation = annotationComponentValue.getAnnotationValue();
401                 disassemble(annotation, buffer, lineSeparator, tabNumber + 1);
402                 break;
403             case IAnnotationComponentValue.ARRAY_TAG:
404                 buffer.append(Messages.disassembler_annotationarrayvaluestart);
405                 final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
406                 for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
407                     writeNewLine(buffer, lineSeparator, tabNumber + 1);
408                     disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1);
409                 }
410                 writeNewLine(buffer, lineSeparator, tabNumber + 1);
411                 buffer.append(Messages.disassembler_annotationarrayvalueend);
412         }
413     }
414     
415     private void disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
416         writeNewLine(buffer, lineSeparator, tabNumber + 1);
417         buffer.append(Messages.disassembler_annotationdefaultheader);
418         IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
419         writeNewLine(buffer, lineSeparator, tabNumber + 2);
420         disassemble(componentValue, buffer, lineSeparator, tabNumber + 1);
421     }
422
423     private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
424         writeNewLine(buffer, lineSeparator, tabNumber + 1);
425         buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
426             new String JavaDoc[] {
427                 new String JavaDoc(classFileAttribute.getAttributeName()),
428                 Long.toString(classFileAttribute.getAttributeLength())
429             }));
430     }
431
432     private void disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
433         writeNewLine(buffer, lineSeparator, tabNumber);
434         final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
435         char[] methodDescriptor = methodInfo.getDescriptor();
436         final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
437         final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
438         // disassemble compact version of annotations
439
if (runtimeInvisibleAnnotationsAttribute != null) {
440             disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
441             writeNewLine(buffer, lineSeparator, tabNumber);
442         }
443         if (runtimeVisibleAnnotationsAttribute != null) {
444             disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
445             writeNewLine(buffer, lineSeparator, tabNumber);
446         }
447         final int accessFlags = methodInfo.getAccessFlags();
448         decodeModifiersForMethod(buffer, accessFlags & IModifierConstants.ACC_PRIVATE);
449         CharOperation.replace(methodDescriptor, '/', '.');
450         final boolean isVarArgs = (accessFlags & IModifierConstants.ACC_VARARGS) != 0;
451         final char[] signature = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs);
452         int index = CharOperation.indexOf(',', signature);
453         index = CharOperation.indexOf(',', signature, index + 1);
454         buffer.append(signature, 0, CharOperation.indexOf('(', signature) + 1);
455         buffer.append(signature, index + 2, signature.length - index - 2);
456         IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
457         if (exceptionAttribute != null) {
458             buffer.append(" throws "); //$NON-NLS-1$
459
char[][] exceptionNames = exceptionAttribute.getExceptionNames();
460             int length = exceptionNames.length;
461             for (int i = 0; i < length; i++) {
462                 if (i != 0) {
463                     buffer
464                         .append(Messages.disassembler_comma)
465                         .append(Messages.disassembler_space);
466                 }
467                 char[] exceptionName = exceptionNames[i];
468                 CharOperation.replace(exceptionName, '/', '.');
469                 buffer.append(returnClassName(exceptionName, '.', mode));
470             }
471         }
472         if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
473                 && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
474             buffer.append(" {"); //$NON-NLS-1$
475
final char[] returnType = Signature.getReturnType(methodDescriptor);
476             if (returnType.length == 1) {
477                 switch(returnType[0]) {
478                     case 'V' :
479                         writeNewLine(buffer, lineSeparator, tabNumber);
480                         break;
481                     case 'I' :
482                     case 'B' :
483                     case 'J' :
484                     case 'D' :
485                     case 'F' :
486                     case 'S' :
487                     case 'C' :
488                         writeNewLine(buffer, lineSeparator, tabNumber + 1);
489                         buffer.append("return 0;"); //$NON-NLS-1$
490
writeNewLine(buffer, lineSeparator, tabNumber);
491                         break;
492                     default :
493                         // boolean
494
writeNewLine(buffer, lineSeparator, tabNumber + 1);
495                         buffer.append("return false;"); //$NON-NLS-1$
496
writeNewLine(buffer, lineSeparator, tabNumber);
497                 }
498             } else {
499                 // object
500
writeNewLine(buffer, lineSeparator, tabNumber + 1);
501                 buffer.append("return null;"); //$NON-NLS-1$
502
writeNewLine(buffer, lineSeparator, tabNumber);
503             }
504             buffer.append('}');
505         } else {
506             buffer.append(';');
507         }
508     }
509     
510     /**
511      * Disassemble a method info header
512      */

513     private void disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
514         writeNewLine(buffer, lineSeparator, tabNumber);
515         final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
516         final char[] methodDescriptor = methodInfo.getDescriptor();
517         final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE);
518         final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
519         final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
520         final IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
521         final IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
522         final IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT);
523         if (checkMode(mode, SYSTEM | DETAILED)) {
524             buffer.append(Messages.bind(Messages.classfileformat_methoddescriptor,
525                 new String JavaDoc[] {
526                     Integer.toString(methodInfo.getDescriptorIndex()),
527                     new String JavaDoc(methodDescriptor)
528                 }));
529             if (methodInfo.isDeprecated()) {
530                 buffer.append(Messages.disassembler_deprecated);
531             }
532             writeNewLine(buffer, lineSeparator, tabNumber);
533             if (signatureAttribute != null) {
534                 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String JavaDoc(signatureAttribute.getSignature())));
535                 writeNewLine(buffer, lineSeparator, tabNumber);
536             }
537             if (codeAttribute != null) {
538                 buffer.append(Messages.bind(Messages.classfileformat_stacksAndLocals,
539                     new String JavaDoc[] {
540                         Integer.toString(codeAttribute.getMaxStack()),
541                         Integer.toString(codeAttribute.getMaxLocals())
542                     }));
543                 writeNewLine(buffer, lineSeparator, tabNumber);
544             }
545         }
546         if (checkMode(mode, DETAILED)) {
547             // disassemble compact version of annotations
548
if (runtimeInvisibleAnnotationsAttribute != null) {
549                 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
550                 writeNewLine(buffer, lineSeparator, tabNumber);
551             }
552             if (runtimeVisibleAnnotationsAttribute != null) {
553                 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
554                 writeNewLine(buffer, lineSeparator, tabNumber);
555             }
556         }
557         final int accessFlags = methodInfo.getAccessFlags();
558         decodeModifiersForMethod(buffer, accessFlags);
559         if (methodInfo.isSynthetic() && !checkMode(mode, WORKING_COPY)) {
560             buffer.append("synthetic"); //$NON-NLS-1$
561
buffer.append(Messages.disassembler_space);
562         }
563         CharOperation.replace(methodDescriptor, '/', '.');
564         final boolean isVarArgs = isVarArgs(methodInfo);
565         if (methodInfo.isConstructor()) {
566             if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
567                 final char[] signature = signatureAttribute.getSignature();
568                 CharOperation.replace(signature, '/', '.');
569                 disassembleGenericSignature(mode, buffer, signature);
570                 buffer.append(' ');
571                 buffer.append(Signature.toCharArray(signature, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs));
572             } else {
573                 buffer.append(Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs));
574             }
575         } else if (methodInfo.isClinit()) {
576             buffer.append(Messages.bind(Messages.classfileformat_clinitname));
577         } else {
578             if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
579                 final char[] signature = signatureAttribute.getSignature();
580                 CharOperation.replace(signature, '/', '.');
581                 disassembleGenericSignature(mode, buffer, signature);
582                 buffer.append(' ');
583                 buffer.append(Signature.toCharArray(signature, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs));
584             } else {
585                 buffer.append(Signature.toCharArray(methodDescriptor, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs));
586             }
587         }
588         IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
589         if (exceptionAttribute != null) {
590             buffer.append(" throws "); //$NON-NLS-1$
591
char[][] exceptionNames = exceptionAttribute.getExceptionNames();
592             int length = exceptionNames.length;
593             for (int i = 0; i < length; i++) {
594                 if (i != 0) {
595                     buffer
596                         .append(Messages.disassembler_comma)
597                         .append(Messages.disassembler_space);
598                 }
599                 char[] exceptionName = exceptionNames[i];
600                 CharOperation.replace(exceptionName, '/', '.');
601                 buffer.append(returnClassName(exceptionName, '.', mode));
602             }
603         }
604         if (checkMode(mode, DETAILED)) {
605             if (annotationDefaultAttribute != null) {
606                 buffer.append(" default "); //$NON-NLS-1$
607
disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
608             }
609         }
610         if (checkMode(mode, WORKING_COPY)) {
611             // put the annotation default attribute if needed
612
if (annotationDefaultAttribute != null) {
613                 buffer.append(" default "); //$NON-NLS-1$
614
disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
615             }
616             if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
617                     && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
618                 buffer.append(" {"); //$NON-NLS-1$
619
final char[] returnType = Signature.getReturnType(methodDescriptor);
620                 if (returnType.length == 1) {
621                     switch(returnType[0]) {
622                         case 'V' :
623                             writeNewLine(buffer, lineSeparator, tabNumber);
624