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                             break;
625                         case 'I' :
626                         case 'B' :
627                         case 'J' :
628                         case 'D' :
629                         case 'F' :
630                         case 'S' :
631                         case 'C' :
632                             writeNewLine(buffer, lineSeparator, tabNumber + 1);
633                             buffer.append("return 0;"); //$NON-NLS-1$
634
writeNewLine(buffer, lineSeparator, tabNumber);
635                             break;
636                         default :
637                             // boolean
638
writeNewLine(buffer, lineSeparator, tabNumber + 1);
639                             buffer.append("return false;"); //$NON-NLS-1$
640
writeNewLine(buffer, lineSeparator, tabNumber);
641                     }
642                 } else {
643                     // object
644
writeNewLine(buffer, lineSeparator, tabNumber + 1);
645                     buffer.append("return null;"); //$NON-NLS-1$
646
writeNewLine(buffer, lineSeparator, tabNumber);
647                 }
648                 buffer.append('}');
649             } else {
650                 buffer.append(';');
651             }
652         } else {
653             buffer.append(Messages.disassembler_endofmethodheader);
654         }
655         
656         if (checkMode(mode, SYSTEM | DETAILED)) {
657             if (codeAttribute != null) {
658                 disassemble(codeAttribute, buffer, lineSeparator, tabNumber, mode);
659             }
660         }
661         if (checkMode(mode, SYSTEM)) {
662             IClassFileAttribute[] attributes = methodInfo.getAttributes();
663             int length = attributes.length;
664             if (length != 0) {
665                 for (int i = 0; i < length; i++) {
666                     IClassFileAttribute attribute = attributes[i];
667                     if (attribute != codeAttribute
668                             && attribute != exceptionAttribute
669                             && attribute != signatureAttribute
670                             && attribute != annotationDefaultAttribute
671                             && attribute != runtimeInvisibleAnnotationsAttribute
672                             && attribute != runtimeVisibleAnnotationsAttribute
673                             && attribute != runtimeInvisibleParameterAnnotationsAttribute
674                             && attribute != runtimeVisibleParameterAnnotationsAttribute
675                             && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
676                             && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
677                         disassemble(attribute, buffer, lineSeparator, tabNumber);
678                         writeNewLine(buffer, lineSeparator, tabNumber);
679                     }
680                 }
681             }
682             if (annotationDefaultAttribute != null) {
683                 disassemble((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
684             }
685             if (runtimeVisibleAnnotationsAttribute != null) {
686                 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
687             }
688             if (runtimeInvisibleAnnotationsAttribute != null) {
689                 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
690             }
691             if (runtimeVisibleParameterAnnotationsAttribute != null) {
692                 disassemble((IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber);
693             }
694             if (runtimeInvisibleParameterAnnotationsAttribute != null) {
695                 disassemble((IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber);
696             }
697         }
698     }
699
700     /**
701      * @see #disassemble(org.eclipse.jdt.core.util.IClassFileReader, java.lang.String, int)
702      */

703     public String JavaDoc disassemble(IClassFileReader classFileReader, String JavaDoc lineSeparator) {
704         return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT);
705     }
706
707     /**
708      * Answers back the disassembled string of the IClassFileReader according to the
709      * mode.
710      * This is an output quite similar to the javap tool.
711      *
712      * @param classFileReader The classFileReader to be disassembled
713      * @param lineSeparator the line separator to use.
714      * @param mode the mode used to disassemble the IClassFileReader
715      *
716      * @return the disassembled string of the IClassFileReader according to the mode
717      */

718     public String JavaDoc disassemble(IClassFileReader classFileReader, String JavaDoc lineSeparator, int mode) {
719         if (classFileReader == null) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
720         char[] className = classFileReader.getClassName();
721         if (className == null) {
722             // incomplete initialization. We cannot go further.
723
return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
724         }
725         className= CharOperation.replaceOnCopy(className, '/', '.');
726         final int classNameLength = className.length;
727         final int accessFlags = classFileReader.getAccessFlags();
728         final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0;
729
730         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
731         ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
732         IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
733         ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
734         if (checkMode(mode, SYSTEM | DETAILED)) {
735             int minorVersion = classFileReader.getMinorVersion();
736             int majorVersion = classFileReader.getMajorVersion();
737             buffer.append(Messages.disassembler_begincommentline);
738             if (sourceAttribute != null) {
739                 buffer.append(Messages.disassembler_sourceattributeheader);
740                 buffer.append(sourceAttribute.getSourceFileName());
741             }
742             String JavaDoc versionNumber = VERSION_UNKNOWN;
743             if (minorVersion == 3 && majorVersion == 45) {
744                 versionNumber = JavaCore.VERSION_1_1;
745             } else if (minorVersion == 0 && majorVersion == 46) {
746                 versionNumber = JavaCore.VERSION_1_2;
747             } else if (minorVersion == 0 && majorVersion == 47) {
748                 versionNumber = JavaCore.VERSION_1_3;
749             } else if (minorVersion == 0 && majorVersion == 48) {
750                 versionNumber = JavaCore.VERSION_1_4;
751             } else if (minorVersion == 0 && majorVersion == 49) {
752                 versionNumber = JavaCore.VERSION_1_5;
753             } else if (minorVersion == 0 && majorVersion == 50) {
754                 versionNumber = JavaCore.VERSION_1_6;
755             } else if (minorVersion == 0 && majorVersion == 51) {
756                 versionNumber = JavaCore.VERSION_1_7;
757             }
758             buffer.append(
759                 Messages.bind(Messages.classfileformat_versiondetails,
760                 new String JavaDoc[] {
761                     versionNumber,
762                     Integer.toString(majorVersion),
763                     Integer.toString(minorVersion),
764                     ((accessFlags & IModifierConstants.ACC_SUPER) != 0
765                             ? Messages.classfileformat_superflagisset
766                             : Messages.classfileformat_superflagisnotset)
767                     + (isDeprecated(classFileReader) ? ", deprecated" : org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING)//$NON-NLS-1$
768
}));
769             writeNewLine(buffer, lineSeparator, 0);
770             if (signatureAttribute != null) {
771                 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String JavaDoc(signatureAttribute.getSignature())));
772                 writeNewLine(buffer, lineSeparator, 0);
773             }
774         }
775         final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className);
776         
777         if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) {
778             // we print a package declaration
779
buffer.append("package ");//$NON-NLS-1$
780
buffer.append(className, 0, lastDotIndexInClassName);
781             buffer.append(';');
782             writeNewLine(buffer, lineSeparator, 0);
783         }
784
785         IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
786         IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
787         IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
788         
789         if (checkMode(mode, DETAILED)) {
790             // disassemble compact version of annotations
791
if (runtimeInvisibleAnnotationsAttribute != null) {
792                 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
793                 writeNewLine(buffer, lineSeparator, 0);
794             }
795             if (runtimeVisibleAnnotationsAttribute != null) {
796                 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
797                 writeNewLine(buffer, lineSeparator, 0);
798             }
799         }
800         boolean decoded = false;
801         if (isEnum && checkMode(mode, WORKING_COPY)) {
802             decodeModifiersForType(buffer, accessFlags & IModifierConstants.ACC_PUBLIC);
803         } else {
804             if (innerClassesAttribute != null) {
805                 // search the right entry
806
IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
807                 for (int i = 0, max = entries.length; i < max ; i++) {
808                     IInnerClassesAttributeEntry entry = entries[i];
809                     char[] innerClassName = entry.getInnerClassName();
810                     if (innerClassName != null) {
811                         if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
812                             decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false);
813                             decoded = true;
814                         }
815                     }
816                 }
817             }
818             if (!decoded) {
819                 decodeModifiersForType(buffer, accessFlags);
820                 if (isSynthetic(classFileReader)) {
821                     buffer.append("synthetic"); //$NON-NLS-1$
822
buffer.append(Messages.disassembler_space);
823                 }
824             }
825         }
826         
827         final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0;
828         boolean isInterface = false;
829         if (isEnum) {
830             buffer.append("enum "); //$NON-NLS-1$
831
} else if (classFileReader.isClass()) {
832             buffer.append("class "); //$NON-NLS-1$
833
} else {
834             if (isAnnotation) {
835                 buffer.append("@"); //$NON-NLS-1$
836
}
837             buffer.append("interface "); //$NON-NLS-1$
838
isInterface = true;
839         }
840         
841         if (checkMode(mode, WORKING_COPY)) {
842             // we print the simple class name
843
final int start = lastDotIndexInClassName + 1;
844             buffer.append(className, start, classNameLength - start);
845             className = CharOperation.subarray(className, start, classNameLength);
846             if (signatureAttribute != null) {
847                 disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature());
848             }
849         } else {
850             buffer.append(className);
851         }
852         
853         char[] superclassName = classFileReader.getSuperclassName();
854         if (superclassName != null) {
855             CharOperation.replace(superclassName, '/', '.');
856             if (!isJavaLangObject(superclassName) && !isEnum) {
857                 buffer.append(" extends "); //$NON-NLS-1$
858
buffer.append(returnClassName(superclassName, '.', mode));
859             }
860         }
861         if (!isAnnotation || !checkMode(mode, WORKING_COPY)) {
862             char[][] superclassInterfaces = classFileReader.getInterfaceNames();
863             int length = superclassInterfaces.length;
864             if (length != 0) {
865                 if (isInterface) {
866                     buffer.append(" extends "); //$NON-NLS-1$
867
} else {
868                     buffer.append(" implements "); //$NON-NLS-1$
869
}
870                 for (int i = 0; i < length; i++) {
871                     if (i != 0) {
872                         buffer
873                             .append(Messages.disassembler_comma)
874                             .append(Messages.disassembler_space);
875                     }
876                     char[] superinterface = superclassInterfaces[i];
877                     CharOperation.replace(superinterface, '/', '.');
878                     buffer
879                         .append(returnClassName(superinterface, '.', mode));
880                 }
881             }
882         }
883         buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration));
884         if (checkMode(mode, SYSTEM)) {
885             disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1);
886         }
887         disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum);
888         if (checkMode(mode, SYSTEM | DETAILED)) {
889             IClassFileAttribute[] attributes = classFileReader.getAttributes();
890             int length = attributes.length;
891             IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader);
892             int remainingAttributesLength = length;
893             if (innerClassesAttribute != null) {
894                 remainingAttributesLength--;
895             }
896             if (enclosingMethodAttribute != null) {
897                 remainingAttributesLength--;
898             }
899             if (sourceAttribute != null) {
900                 remainingAttributesLength--;
901             }
902             if (signatureAttribute != null) {
903                 remainingAttributesLength--;
904             }
905             if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) {
906                 writeNewLine(buffer, lineSeparator, 0);
907             }
908             if (innerClassesAttribute != null) {
909                 disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
910             }
911             if (enclosingMethodAttribute != null) {
912                 disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
913             }
914             if (checkMode(mode, SYSTEM)) {
915                 if (runtimeVisibleAnnotationsAttribute != null) {
916                     disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0);
917                 }
918                 if (runtimeInvisibleAnnotationsAttribute != null) {
919                     disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0);
920                 }
921                 if (length != 0) {
922                     for (int i = 0; i < length; i++) {
923                         IClassFileAttribute attribute = attributes[i];
924                         if (attribute != innerClassesAttribute
925                             && attribute != sourceAttribute
926                             && attribute != signatureAttribute
927                             && attribute != enclosingMethodAttribute
928                             && attribute != runtimeInvisibleAnnotationsAttribute
929                             && attribute != runtimeVisibleAnnotationsAttribute
930                             && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
931                             && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
932                             disassemble(attribute, buffer, lineSeparator, 0);
933                         }
934                     }
935                 }
936             }
937         }
938         writeNewLine(buffer, lineSeparator, 0);
939         buffer.append(Messages.disassembler_closetypedeclaration);
940         return buffer.toString();
941     }
942
943     private void disassembleGenericSignature(int mode, StringBuffer JavaDoc buffer, final char[] signature) {
944         CharOperation.replace(signature, '/', '.');
945         final char[][] typeParameters = Signature.getTypeParameters(signature);
946         final int typeParametersLength = typeParameters.length;
947         if (typeParametersLength != 0) {
948             buffer.append('<');
949             for (int i = 0; i < typeParametersLength; i++) {
950                 if (i != 0) {
951                     buffer.append(Messages.disassembler_comma);
952                 }
953                 // extract the name
954
buffer.append(typeParameters[i], 0, CharOperation.indexOf(':', typeParameters[i]));
955                 final char[][] bounds = Signature.getTypeParameterBounds(typeParameters[i]);
956                 final int boundsLength = bounds.length;
957                 if (boundsLength != 0) {
958                     if (boundsLength == 1) {
959                         final char[] bound = bounds[0];
960                         // check if this is java.lang.Object
961
if (!isJavaLangObject(Signature.toCharArray(bound))) {
962                             buffer.append(" extends "); //$NON-NLS-1$
963
buffer.append(returnClassName(Signature.toCharArray(bound), '.', mode));
964                         }
965                     } else {
966                         buffer.append(" extends "); //$NON-NLS-1$
967
for (int j= 0; j < boundsLength; j++) {
968                             if (j != 0) {
969                                 buffer.append(" & "); //$NON-NLS-1$
970
}
971                             buffer.append(returnClassName(Signature.toCharArray(bounds[j]), '.', mode));
972                         }
973                     }
974                 }
975             }
976             buffer.append('>');
977         }
978     }
979
980     private boolean isJavaLangObject(final char[] className) {
981         return CharOperation.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className));
982     }
983     
984     private boolean isVarArgs(IMethodInfo methodInfo) {
985         int accessFlags = methodInfo.getAccessFlags();
986         if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) return true;
987         // check the presence of the unspecified Varargs attribute
988
return Util.getAttribute(methodInfo, AttributeNamesConstants.VarargsName) != null;
989     }
990     private void disassemble(ICodeAttribute codeAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
991         writeNewLine(buffer, lineSeparator, tabNumber - 1);
992         DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, buffer, lineSeparator, tabNumber, mode);
993         try {
994             codeAttribute.traverse(visitor);
995         } catch(ClassFormatException e) {
996             dumpTab(tabNumber + 2, buffer);
997             buffer.append(Messages.classformat_classformatexception);
998             writeNewLine(buffer, lineSeparator, tabNumber + 1);
999         }
1000        final int exceptionTableLength = codeAttribute.getExceptionTableLength();
1001        boolean isFirstAttribute = true;
1002        if (exceptionTableLength != 0) {
1003            final int tabNumberForExceptionAttribute = tabNumber + 2;
1004            isFirstAttribute = false;
1005            dumpTab(tabNumberForExceptionAttribute, buffer);
1006            final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
1007            buffer.append(Messages.disassembler_exceptiontableheader);
1008            writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
1009            for (int i = 0; i < exceptionTableLength; i++) {
1010                if (i != 0) {
1011                    writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
1012                }
1013                IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i];
1014                char[] catchType;
1015                if (exceptionTableEntry.getCatchTypeIndex() != 0) {
1016                    catchType = exceptionTableEntry.getCatchType();
1017                    CharOperation.replace(catchType, '/', '.');
1018                    catchType = returnClassName(catchType, '.', mode);
1019                } else {
1020                    catchType = ANY_EXCEPTION;
1021                }
1022                buffer.append(Messages.bind(Messages.classfileformat_exceptiontableentry,
1023                    new String JavaDoc[] {
1024                        Integer.toString(exceptionTableEntry.getStartPC()),
1025                        Integer.toString(exceptionTableEntry.getEndPC()),
1026                        Integer.toString(exceptionTableEntry.getHandlerPC()),
1027                        new String JavaDoc(catchType)
1028                    }));
1029            }
1030        }
1031        final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute();
1032        final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength();
1033        if (lineAttributeLength != 0) {
1034            int tabNumberForLineAttribute = tabNumber + 2;
1035            if (!isFirstAttribute) {
1036                writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute);
1037            } else {
1038                dumpTab(tabNumberForLineAttribute, buffer);
1039                isFirstAttribute = false;
1040            }
1041            buffer.append(Messages.disassembler_linenumberattributeheader);
1042            writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
1043            int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable();
1044            for (int i = 0; i < lineAttributeLength; i++) {
1045                if (i != 0) {
1046                    writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
1047                }
1048                buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry,
1049                    new String JavaDoc[] {
1050                        Integer.toString(lineattributesEntries[i][0]),
1051                        Integer.toString(lineattributesEntries[i][1])
1052                    }));
1053            }
1054        }
1055        final ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
1056        final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength();
1057        if (localVariableAttributeLength != 0) {
1058            int tabNumberForLocalVariableAttribute = tabNumber + 2;
1059            if (!isFirstAttribute) {
1060                writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
1061            } else {
1062                isFirstAttribute = false;
1063                dumpTab(tabNumberForLocalVariableAttribute, buffer);
1064            }
1065            buffer.append(Messages.disassembler_localvariabletableattributeheader);
1066            writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1067            ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable();
1068            for (int i = 0; i < localVariableAttributeLength; i++) {
1069                if (i != 0) {
1070                    writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1071                }
1072                ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[i];
1073                int index= localVariableTableEntry.getIndex();
1074                int startPC = localVariableTableEntry.getStartPC();
1075                int length = localVariableTableEntry.getLength();
1076                final char[] typeName = Signature.toCharArray(localVariableTableEntry.getDescriptor());
1077                CharOperation.replace(typeName, '/', '.');
1078                buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
1079                    new String JavaDoc[] {
1080                        Integer.toString(startPC),
1081                        Integer.toString(startPC + length),
1082                        new String JavaDoc(localVariableTableEntry.getName()),
1083                        Integer.toString(index),
1084                        new String JavaDoc(returnClassName(typeName, '.', mode))
1085                    }));
1086            }
1087        }
1088        final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) getAttribute(IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE, codeAttribute);
1089        final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength();
1090        if (localVariableTypeTableLength != 0) {
1091            int tabNumberForLocalVariableAttribute = tabNumber + 2;
1092            if (!isFirstAttribute) {
1093                writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
1094            } else {
1095                isFirstAttribute = false;
1096                dumpTab(tabNumberForLocalVariableAttribute, buffer);
1097            }
1098            buffer.append(Messages.disassembler_localvariabletypetableattributeheader);
1099            writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1100            ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable();
1101            for (int i = 0; i < localVariableTypeTableLength; i++) {
1102                if (i != 0) {
1103                    writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1104                }
1105                ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[i];
1106                int index= localVariableTypeTableEntry.getIndex();
1107                int startPC = localVariableTypeTableEntry.getStartPC();
1108                int length = localVariableTypeTableEntry.getLength();
1109                final char[] typeName = Signature.toCharArray(localVariableTypeTableEntry.getSignature());
1110                CharOperation.replace(typeName, '/', '.');
1111                buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
1112                    new String JavaDoc[] {
1113                        Integer.toString(startPC),
1114                        Integer.toString(startPC + length),
1115                        new String JavaDoc(localVariableTypeTableEntry.getName()),
1116                        Integer.toString(index),
1117                        new String JavaDoc(returnClassName(typeName, '.', mode))
1118                    }));
1119            }
1120        }
1121        final int length = codeAttribute.getAttributesCount();
1122        if (length != 0) {
1123            IClassFileAttribute[] attributes = codeAttribute.getAttributes();
1124            for (int i = 0; i < length; i++) {
1125                IClassFileAttribute attribute = attributes[i];
1126                if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) {
1127                    IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute;
1128                    if (!isFirstAttribute) {
1129                        writeNewLine(buffer, lineSeparator, tabNumber + 2);
1130                    } else {
1131                        isFirstAttribute = false;
1132                        dumpTab(tabNumber + 1, buffer);
1133                    }
1134                    int numberOfEntries = stackMapTableAttribute.getNumberOfEntries();
1135                    buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries)));
1136                    if (numberOfEntries != 0) {
1137                        disassemble(stackMapTableAttribute, buffer, lineSeparator, tabNumber, mode);
1138                    }
1139                } else if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP)) {
1140                    IStackMapAttribute stackMapAttribute = (IStackMapAttribute) attribute;
1141                    if (!isFirstAttribute) {
1142                        writeNewLine(buffer, lineSeparator, tabNumber + 2);
1143                    } else {
1144                        isFirstAttribute = false;
1145                        dumpTab(tabNumber + 1, buffer);
1146                    }
1147                    int numberOfEntries = stackMapAttribute.getNumberOfEntries();
1148                    buffer.append(Messages.bind(Messages.disassembler_stackmapattributeheader, Integer.toString(numberOfEntries)));
1149                    if (numberOfEntries != 0) {
1150                        disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode);
1151                    }
1152                } else if (attribute != lineNumberAttribute
1153                        && attribute != localVariableAttribute
1154                        && attribute != localVariableTypeAttribute) {
1155                    if (!isFirstAttribute) {
1156                        writeNewLine(buffer, lineSeparator, tabNumber + 2);
1157                    } else {
1158                        isFirstAttribute = false;
1159                        dumpTab(tabNumber + 1, buffer);
1160                    }
1161                    buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
1162                        new String JavaDoc[] {
1163                            new String JavaDoc(attribute.getAttributeName()),
1164                            Long.toString(attribute.getAttributeLength())
1165                        }));
1166                }
1167            }
1168        }
1169    }
1170    
1171    private void disassemble(IStackMapTableAttribute attribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1172        writeNewLine(buffer, lineSeparator, tabNumber + 3);
1173        int numberOfEntries = attribute.getNumberOfEntries();
1174        final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
1175        int absolutePC = -1;
1176        for (int j = 0; j < numberOfEntries; j++) {
1177            if (j > 0) {
1178                writeNewLine(buffer, lineSeparator, tabNumber + 3);
1179            }
1180            final IStackMapFrame frame = stackMapFrames[j];
1181            // disassemble each frame
1182
int type = frame.getFrameType();
1183            int offsetDelta = frame.getOffsetDelta();
1184            if (absolutePC == -1) {
1185                absolutePC = offsetDelta;
1186            } else {
1187                absolutePC += (offsetDelta + 1);
1188            }
1189            switch(type) {
1190                case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
1191
buffer.append(
1192                        Messages.bind(
1193                            Messages.disassembler_frame_same_locals_1_stack_item_extended,
1194                            Integer.toString(absolutePC),
1195                            disassemble(frame.getStackItems(), mode)));
1196                    break;
1197                case 248 :
1198                case 249 :
1199                case 250:
1200                    // CHOP
1201
buffer.append(
1202                            Messages.bind(
1203                                Messages.disassembler_frame_chop,
1204                                Integer.toString(absolutePC),
1205                                Integer.toString(251 - type)));
1206                    break;
1207                case 251 :
1208                    // SAME_FRAME_EXTENDED
1209
buffer.append(
1210                            Messages.bind(
1211                                Messages.disassembler_frame_same_frame_extended,
1212                                Integer.toString(absolutePC)));
1213                    break;
1214                case 252 :
1215                case 253 :
1216                case 254 :
1217                    // APPEND
1218
buffer.append(
1219                            Messages.bind(
1220                                Messages.disassembler_frame_append,
1221                                Integer.toString(absolutePC),
1222                                disassemble(frame.getLocals(), mode)));
1223                    break;
1224                case 255 :
1225                    // FULL_FRAME
1226
buffer.append(
1227                            Messages.bind(
1228                                Messages.disassembler_frame_full_frame,
1229                                new String JavaDoc[] {
1230                                    Integer.toString(absolutePC),
1231                                    Integer.toString(frame.getNumberOfLocals()),
1232                                    disassemble(frame.getLocals(), mode),
1233                                    Integer.toString(frame.getNumberOfStackItems()),
1234                                    disassemble(frame.getStackItems(), mode),
1235                                    dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
1236                                }));
1237                    break;
1238                default:
1239                    if (type <= 63) {
1240                        // SAME_FRAME
1241
offsetDelta = type;
1242                        buffer.append(
1243                                Messages.bind(
1244                                    Messages.disassembler_frame_same_frame,
1245                                    Integer.toString(absolutePC)));
1246                    } else if (type <= 127) {
1247                        // SAME_LOCALS_1_STACK_ITEM
1248
offsetDelta = type - 64;
1249                        buffer.append(
1250                                Messages.bind(
1251                                    Messages.disassembler_frame_same_locals_1_stack_item,
1252                                    Integer.toString(absolutePC),
1253                                    disassemble(frame.getStackItems(), mode)));
1254                    }
1255            }
1256        }
1257    }
1258
1259    private void disassemble(IStackMapAttribute attribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1260        writeNewLine(buffer, lineSeparator, tabNumber + 3);
1261        int numberOfEntries = attribute.getNumberOfEntries();
1262        final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
1263        int absolutePC = -1;
1264        for (int j = 0; j < numberOfEntries; j++) {
1265            if (j > 0) {
1266                writeNewLine(buffer, lineSeparator, tabNumber + 3);
1267            }
1268            final IStackMapFrame frame = stackMapFrames[j];
1269            // disassemble each frame
1270
int offsetDelta = frame.getOffsetDelta();
1271            if (absolutePC == -1) {
1272                absolutePC = offsetDelta;
1273            } else {
1274                absolutePC += (offsetDelta + 1);
1275            }
1276            // FULL_FRAME
1277
buffer.append(
1278                    Messages.bind(
1279                        Messages.disassembler_frame_full_frame,
1280                        new String JavaDoc[] {
1281                            Integer.toString(absolutePC),
1282                            Integer.toString(frame.getNumberOfLocals()),
1283                            disassemble(frame.getLocals(), mode),
1284                            Integer.toString(frame.getNumberOfStackItems()),
1285                            disassemble(frame.getStackItems(), mode),
1286                            dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
1287                        }));
1288        }
1289    }
1290
1291    private void disassemble(IConstantPool constantPool, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1292        writeNewLine(buffer, lineSeparator, tabNumber);
1293        int length = constantPool.getConstantPoolCount();
1294        buffer.append(Messages.disassembler_constantpoolheader);
1295        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1296        for (int i = 1; i < length; i++) {
1297            if (i != 1) {
1298                writeNewLine(buffer, lineSeparator, tabNumber + 1);
1299            }
1300            IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i);
1301            switch (constantPool.getEntryKind(i)) {
1302                case IConstantPoolConstant.CONSTANT_Class :
1303                    buffer.append(
1304                        Messages.bind(Messages.disassembler_constantpool_class,
1305                            new String JavaDoc[] {
1306                                Integer.toString(i),
1307                                Integer.toString(constantPoolEntry.getClassInfoNameIndex()),
1308                                new String JavaDoc(constantPoolEntry.getClassInfoName())}));
1309                    break;
1310                case IConstantPoolConstant.CONSTANT_Double :
1311                    buffer.append(
1312                        Messages.bind(Messages.disassembler_constantpool_double,
1313                            new String JavaDoc[] {
1314                                Integer.toString(i),
1315                                Double.toString(constantPoolEntry.getDoubleValue())}));
1316                    break;
1317                case IConstantPoolConstant.CONSTANT_Fieldref :
1318                    buffer.append(
1319                        Messages.bind(Messages.disassembler_constantpool_fieldref,
1320                            new String JavaDoc[] {
1321                                Integer.toString(i),
1322                                Integer.toString(constantPoolEntry.getClassIndex()),
1323                                Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
1324                                new String JavaDoc(constantPoolEntry.getClassName()),
1325                                new String JavaDoc(constantPoolEntry.getFieldName()),
1326                                new String JavaDoc(constantPoolEntry.getFieldDescriptor())
1327                            }));
1328                    break;
1329                case IConstantPoolConstant.CONSTANT_Float :
1330                    buffer.append(
1331                        Messages.bind(Messages.disassembler_constantpool_float,
1332                        new String JavaDoc[] {
1333                            Integer.toString(i),
1334                            Float.toString(constantPoolEntry.getFloatValue())}));
1335                    break;
1336                case IConstantPoolConstant.CONSTANT_Integer :
1337                    buffer.append(
1338                        Messages.bind(Messages.disassembler_constantpool_integer,
1339                            new String JavaDoc[] {
1340                                Integer.toString(i),
1341                                Integer.toString(constantPoolEntry.getIntegerValue())}));
1342                    break;
1343                case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
1344                    buffer.append(
1345                            Messages.bind(Messages.disassembler_constantpool_interfacemethodref,
1346                                new String JavaDoc[] {
1347                                    Integer.toString(i),
1348                                    Integer.toString(constantPoolEntry.getClassIndex()),
1349                                    Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
1350                                    new String JavaDoc(constantPoolEntry.getClassName()),
1351                                    new String JavaDoc(constantPoolEntry.getMethodName()),
1352                                    new String JavaDoc(constantPoolEntry.getMethodDescriptor())}));
1353                    break;
1354                case IConstantPoolConstant.CONSTANT_Long :
1355                    buffer.append(
1356                        Messages.bind(Messages.disassembler_constantpool_long,
1357                            new String JavaDoc[] {
1358                                Integer.toString(i),
1359                                Long.toString(constantPoolEntry.getLongValue())}));
1360                    break;
1361                case IConstantPoolConstant.CONSTANT_Methodref :
1362                    buffer.append(
1363                            Messages.bind(Messages.disassembler_constantpool_methodref,
1364                                new String JavaDoc[] {
1365                                    Integer.toString(i),
1366                                    Integer.toString(constantPoolEntry.getClassIndex()),
1367                                    Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
1368                                    new String JavaDoc(constantPoolEntry.getClassName()),
1369                                    new String JavaDoc(constantPoolEntry.getMethodName()),
1370                                    new String JavaDoc(constantPoolEntry.getMethodDescriptor())}));
1371                    break;
1372                case IConstantPoolConstant.CONSTANT_NameAndType :
1373                    int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex();
1374                    int typeIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex();
1375                    IConstantPoolEntry entry = constantPool.decodeEntry(nameIndex);
1376                    char[] nameValue = entry.getUtf8Value();
1377                    entry = constantPool.decodeEntry(typeIndex);
1378                    char[] typeValue = entry.getUtf8Value();
1379                    buffer.append(
1380                        Messages.bind(Messages.disassembler_constantpool_name_and_type,
1381                            new String JavaDoc[] {
1382                                Integer.toString(i),
1383                                Integer.toString(nameIndex),
1384                                Integer.toString(typeIndex),
1385                                String.valueOf(nameValue),
1386                                String.valueOf(typeValue)}));
1387                    break;
1388                case IConstantPoolConstant.CONSTANT_String :
1389                    buffer.append(
1390                        Messages.bind(Messages.disassembler_constantpool_string,
1391                            new String JavaDoc[] {
1392                                Integer.toString(i),
1393                                Integer.toString(constantPoolEntry.getStringIndex()),
1394                                decodeStringValue(constantPoolEntry.getStringValue())}));
1395                    break;
1396                case IConstantPoolConstant.CONSTANT_Utf8 :
1397                    buffer.append(
1398                        Messages.bind(Messages.disassembler_constantpool_utf8,
1399                            new String JavaDoc[] {
1400                                Integer.toString(i),
1401                                decodeStringValue(new String JavaDoc(constantPoolEntry.getUtf8Value()))}));
1402                    break;
1403            }
1404        }
1405    }
1406
1407    private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1408        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1409        buffer.append(Messages.disassembler_enclosingmethodheader);
1410        buffer
1411            .append(Messages.disassembler_constantpoolindex)
1412            .append(enclosingMethodAttribute.getEnclosingClassIndex())
1413            .append(" ")//$NON-NLS-1$
1414
.append(Messages.disassembler_constantpoolindex)
1415            .append(enclosingMethodAttribute.getMethodNameAndTypeIndex())
1416            .append(" ")//$NON-NLS-1$
1417
.append(enclosingMethodAttribute.getEnclosingClass());
1418        if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) {
1419            buffer
1420                .append(".")//$NON-NLS-1$
1421
.append(enclosingMethodAttribute.getMethodName())
1422                .append(enclosingMethodAttribute.getMethodDescriptor());
1423        }
1424    }
1425    
1426    private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, char[][] argumentTypes, int mode) {
1427        writeNewLine(buffer, lineSeparator, tabNumber);
1428        final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
1429        final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
1430        // disassemble compact version of annotations
1431
if (runtimeInvisibleAnnotationsAttribute != null) {
1432            disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
1433            writeNewLine(buffer, lineSeparator, tabNumber);
1434        }
1435        if (runtimeVisibleAnnotationsAttribute != null) {
1436            disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
1437            writeNewLine(buffer, lineSeparator, tabNumber);
1438        }
1439        buffer.append(new String JavaDoc(fieldInfo.getName()));
1440        buffer.append('(');
1441        final int length = argumentTypes.length;
1442        if (length != 0) {
1443            // insert default value for corresponding argument types
1444
for (int i = 0; i < length; i++) {
1445                if (i != 0) {
1446                    buffer.append(Messages.disassembler_comma);
1447                }
1448                final char[] type = argumentTypes[i];
1449                switch(type.length) {
1450                    case 1 :
1451                        switch(type[0]) {
1452                            case 'B' :
1453                            case 'I' :
1454                            case 'J' :
1455                            case 'D' :
1456                            case 'F' :
1457                            case 'S' :
1458                                buffer.append('0');
1459                                break;
1460                            case 'Z' :
1461                                buffer.append("false"); //$NON-NLS-1$
1462
break;
1463                            case 'C' :
1464                                buffer.append("\' \'"); //$NON-NLS-1$
1465
break;
1466                        }
1467                        break;
1468                    default :
1469                        buffer.append("null"); //$NON-NLS-1$
1470
}
1471            }
1472        }
1473        buffer.append(')').append(Messages.disassembler_comma);
1474    }
1475    
1476    /**
1477     * Disassemble a field info
1478     */

1479    private void disassemble(IFieldInfo fieldInfo, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1480        writeNewLine(buffer, lineSeparator, tabNumber);
1481        final char[] fieldDescriptor = fieldInfo.getDescriptor();
1482        final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
1483        if (checkMode(mode, SYSTEM | DETAILED)) {
1484            buffer.append(Messages.bind(Messages.classfileformat_fieldddescriptor,
1485                new String JavaDoc[] {
1486                    Integer.toString(fieldInfo.getDescriptorIndex()),
1487                    new String JavaDoc(fieldDescriptor)
1488                }));
1489            if (fieldInfo.isDeprecated()) {
1490                buffer.append(Messages.disassembler_deprecated);
1491            }
1492            writeNewLine(buffer, lineSeparator, tabNumber);
1493            if (signatureAttribute != null) {
1494                buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String JavaDoc(signatureAttribute.getSignature())));
1495                writeNewLine(buffer, lineSeparator, tabNumber);
1496            }
1497        }
1498        final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
1499        final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
1500        if (checkMode(mode, DETAILED)) {
1501            // disassemble compact version of annotations
1502
if (runtimeInvisibleAnnotationsAttribute != null) {
1503                disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
1504                writeNewLine(buffer, lineSeparator, tabNumber);
1505            }
1506            if (runtimeVisibleAnnotationsAttribute != null) {
1507                disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
1508                writeNewLine(buffer, lineSeparator, tabNumber);
1509            }
1510        }
1511        if (checkMode(mode, WORKING_COPY)) {
1512            decodeModifiersForFieldForWorkingCopy(buffer, fieldInfo.getAccessFlags());
1513            if (signatureAttribute != null) {
1514                buffer.append(returnClassName(getSignatureForField(signatureAttribute.getSignature()), '.', mode));
1515            } else {
1516                buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
1517            }
1518        } else {
1519            decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
1520            if (fieldInfo.isSynthetic()) {
1521                buffer.append("synthetic"); //$NON-NLS-1$
1522
buffer.append(Messages.disassembler_space);
1523            }
1524            buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
1525        }
1526        buffer.append(' ');
1527        buffer.append(new String JavaDoc(fieldInfo.getName()));
1528        IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
1529        if (constantValueAttribute != null) {
1530            buffer.append(Messages.disassembler_fieldhasconstant);
1531            IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue();
1532            switch(constantPoolEntry.getKind()) {
1533                case IConstantPoolConstant.CONSTANT_Long :
1534                    buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$
1535
break;
1536                case IConstantPoolConstant.CONSTANT_Float :
1537                    buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
1538
break;
1539                case IConstantPoolConstant.CONSTANT_Double :
1540                    final double doubleValue = constantPoolEntry.getDoubleValue();
1541                    if (checkMode(mode, ClassFileBytesDisassembler.WORKING_COPY)) {
1542                        if (doubleValue == Double.POSITIVE_INFINITY) {
1543                            buffer.append("1.0 / 0.0"); //$NON-NLS-1$
1544
} else if (doubleValue == Double.NEGATIVE_INFINITY) {
1545                            buffer.append("-1.0 / 0.0"); //$NON-NLS-1$
1546
} else {
1547                            buffer.append(constantPoolEntry.getDoubleValue());
1548                        }
1549                    } else {
1550                        buffer.append(constantPoolEntry.getDoubleValue());
1551                    }
1552                    break;
1553                case IConstantPoolConstant.CONSTANT_Integer:
1554                    switch(fieldDescriptor[0]) {
1555                        case 'C' :
1556                            buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$
1557
break;
1558                        case 'Z' :
1559                            buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
1560
break;
1561                        case 'B' :
1562                            buffer.append(constantPoolEntry.getIntegerValue());
1563                            break;
1564                        case 'S' :
1565                            buffer.append(constantPoolEntry.getIntegerValue());
1566                            break;
1567                        case 'I' :
1568                            buffer.append(constantPoolEntry.getIntegerValue());
1569                    }
1570                    break;
1571                case IConstantPoolConstant.CONSTANT_String:
1572                    buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" );//$NON-NLS-1$//$NON-NLS-2$
1573
}
1574        }
1575        buffer.append(Messages.disassembler_endoffieldheader);
1576        if (checkMode(mode, SYSTEM)) {
1577            IClassFileAttribute[] attributes = fieldInfo.getAttributes();
1578            int length = attributes.length;
1579            if (length != 0) {
1580                for (int i = 0; i < length; i++) {
1581                    IClassFileAttribute attribute = attributes[i];
1582                    if (attribute != constantValueAttribute
1583                        && attribute != signatureAttribute
1584                        && attribute != runtimeInvisibleAnnotationsAttribute
1585                        && attribute != runtimeVisibleAnnotationsAttribute
1586                        && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
1587                        && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
1588                        disassemble(attribute, buffer, lineSeparator, tabNumber);
1589                    }
1590                }
1591            }
1592            if (runtimeVisibleAnnotationsAttribute != null) {
1593                disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
1594            }
1595            if (runtimeInvisibleAnnotationsAttribute != null) {
1596                disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber);
1597            }
1598        }
1599    }
1600    
1601    private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1602        writeNewLine(buffer, lineSeparator, tabNumber);
1603        buffer.append(Messages.disassembler_innerattributesheader);
1604        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1605        IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries();
1606        int length = innerClassesAttributeEntries.length;
1607        int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
1608        IInnerClassesAttributeEntry innerClassesAttributeEntry;
1609        for (int i = 0; i < length; i++) {
1610            if (i != 0) {
1611                buffer.append(Messages.disassembler_comma);
1612                writeNewLine(buffer, lineSeparator, tabNumber + 1);
1613            }
1614            innerClassesAttributeEntry = innerClassesAttributeEntries[i];
1615            innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
1616            outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
1617            innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
1618            accessFlags = innerClassesAttributeEntry.getAccessFlags();
1619            buffer
1620                .append(Messages.disassembler_openinnerclassentry)
1621                .append(Messages.disassembler_inner_class_info_name)
1622                .append(Messages.disassembler_constantpoolindex)
1623                .append(innerClassNameIndex);
1624            if (innerClassNameIndex != 0) {
1625                buffer
1626                    .append(Messages.disassembler_space)
1627                    .append(innerClassesAttributeEntry.getInnerClassName());
1628            }
1629            buffer
1630                .append(Messages.disassembler_comma)
1631                .append(Messages.disassembler_space)
1632                .append(Messages.disassembler_outer_class_info_name)
1633                .append(Messages.disassembler_constantpoolindex)
1634                .append(outerClassNameIndex);
1635            if (outerClassNameIndex != 0) {
1636                buffer
1637                    .append(Messages.disassembler_space)
1638                    .append(innerClassesAttributeEntry.getOuterClassName());
1639            }
1640            writeNewLine(buffer, lineSeparator, tabNumber);
1641            dumpTab(tabNumber, buffer);
1642            buffer.append(Messages.disassembler_space);
1643            buffer
1644                .append(Messages.disassembler_inner_name)
1645                .append(Messages.disassembler_constantpoolindex)
1646                .append(innerNameIndex);
1647            if (innerNameIndex != 0) {
1648                buffer
1649                    .append(Messages.disassembler_space)
1650                    .append(innerClassesAttributeEntry.getInnerName());
1651            }
1652            buffer
1653                .append(Messages.disassembler_comma)
1654                .append(Messages.disassembler_space)
1655                .append(Messages.disassembler_inner_accessflags)
1656                .append(accessFlags)
1657                .append(Messages.disassembler_space);
1658            decodeModifiersForInnerClasses(buffer, accessFlags, true);
1659            buffer
1660                .append(Messages.disassembler_closeinnerclassentry);
1661        }
1662    }
1663
1664    private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1665        IAnnotation[] annotations = parameterAnnotation.getAnnotations();
1666        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1667        buffer.append(
1668            Messages.bind(Messages.disassembler_parameterannotationentrystart, new String JavaDoc[] {Integer.toString(index), Integer.toString(annotations.length)}));
1669        for (int i = 0, max = annotations.length; i < max; i++) {
1670            disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
1671        }
1672    }
1673
1674    private void disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1675        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1676        buffer.append(Messages.disassembler_runtimeinvisibleannotationsattributeheader);
1677        IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
1678        for (int i = 0, max = annotations.length; i < max; i++) {
1679            disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
1680        }
1681    }
1682
1683    private void disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1684        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1685        buffer.append(Messages.disassembler_runtimeinvisibleparameterannotationsattributeheader);
1686        IParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations();
1687        for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
1688            disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1);
1689        }
1690    }
1691    
1692    private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1693        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1694        buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader);
1695        IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
1696        for (int i = 0, max = annotations.length; i < max; i++) {
1697            disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1);
1698        }
1699    }
1700
1701    private void disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
1702        writeNewLine(buffer, lineSeparator, tabNumber + 1);
1703        buffer.append(Messages.disassembler_runtimevisibleparameterannotationsattributeheader);
1704        IParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations();
1705        for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
1706            disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1);
1707        }
1708    }
1709
1710    private String JavaDoc disassemble(IVerificationTypeInfo[] infos, int mode) {
1711        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1712        buffer.append('{');
1713        for (int i = 0, max = infos.length; i < max; i++) {
1714            if(i != 0) {
1715                buffer
1716                        .append(Messages.disassembler_comma)
1717                        .append(Messages.disassembler_space);
1718            }
1719            switch(infos[i].getTag()) {
1720                case IVerificationTypeInfo.ITEM_DOUBLE :
1721                    buffer.append("double"); //$NON-NLS-1$
1722
break;
1723                case IVerificationTypeInfo.ITEM_FLOAT :
1724                    buffer.append("float"); //$NON-NLS-1$
1725
break;
1726                case IVerificationTypeInfo.ITEM_INTEGER :
1727                    buffer.append("int"); //$NON-NLS-1$
1728
break;
1729                case IVerificationTypeInfo.ITEM_LONG :
1730                    buffer.append("long"); //$NON-NLS-1$
1731
break;
1732                case IVerificationTypeInfo.ITEM_NULL :
1733                    buffer.append("null"); //$NON-NLS-1$
1734
break;
1735                case IVerificationTypeInfo.ITEM_OBJECT :
1736                    char[] classTypeName = infos[i].getClassTypeName();
1737                    CharOperation.replace(classTypeName, '/', '.');
1738                    if (classTypeName.length > 0 && classTypeName[0] == '[') { // length check for resilience
1739
classTypeName = Signature.toCharArray(classTypeName);
1740                    }
1741                    buffer.append(returnClassName(classTypeName, '.', mode));
1742                    break;
1743                case IVerificationTypeInfo.ITEM_TOP :
1744                    buffer.append("_"); //$NON-NLS-1$
1745
break;
1746                case IVerificationTypeInfo.ITEM_UNINITIALIZED :
1747                    buffer.append("uninitialized("); //$NON-NLS-1$
1748
buffer.append(infos[i].getOffset());
1749                    buffer.append(')');
1750                    break;
1751                case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS :
1752                    buffer.append("uninitialized_this"); //$NON-NLS-1$
1753
}
1754        }
1755        buffer.append('}');
1756        return String.valueOf(buffer);
1757    }
1758
1759    private void disassembleAsModifier(IAnnotation annotation, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1760        final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
1761        buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode));
1762        final IAnnotationComponent[] components = annotation.getComponents();
1763        final int length = components.length;
1764        if (length != 0) {
1765            buffer.append('(');
1766            for (int i = 0; i < length; i++) {
1767                if (i > 0) {
1768                    buffer.append(',');
1769                    writeNewLine(buffer, lineSeparator, tabNumber);
1770                }
1771                disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode);
1772            }
1773            buffer.append(')');
1774        }
1775    }
1776
1777    private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1778        buffer.append(annotationComponent.getComponentName()).append('=');
1779        disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
1780    }
1781
1782    private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1783        switch(annotationComponentValue.getTag()) {
1784            case IAnnotationComponentValue.BYTE_TAG:
1785            case IAnnotationComponentValue.CHAR_TAG:
1786            case IAnnotationComponentValue.DOUBLE_TAG:
1787            case IAnnotationComponentValue.FLOAT_TAG:
1788            case IAnnotationComponentValue.INTEGER_TAG:
1789            case IAnnotationComponentValue.LONG_TAG:
1790            case IAnnotationComponentValue.SHORT_TAG:
1791            case IAnnotationComponentValue.BOOLEAN_TAG:
1792            case IAnnotationComponentValue.STRING_TAG:
1793                IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
1794                String JavaDoc value = null;
1795                switch(constantPoolEntry.getKind()) {
1796                    case IConstantPoolConstant.CONSTANT_Long :
1797                        value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
1798
break;
1799                    case IConstantPoolConstant.CONSTANT_Float :
1800                        value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
1801
break;
1802                    case IConstantPoolConstant.CONSTANT_Double :
1803                        value = Double.toString(constantPoolEntry.getDoubleValue());
1804                        break;
1805                    case IConstantPoolConstant.CONSTANT_Integer:
1806                        switch(annotationComponentValue.getTag()) {
1807                            case IAnnotationComponentValue.CHAR_TAG :
1808                                value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
1809
break;
1810                            case IAnnotationComponentValue.BOOLEAN_TAG :
1811                                value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
1812
break;
1813                            case IAnnotationComponentValue.BYTE_TAG :
1814                                value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
1815
break;
1816                            case IAnnotationComponentValue.SHORT_TAG :
1817                                value = "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
1818
break;
1819                            case IAnnotationComponentValue.INTEGER_TAG :
1820                                value = "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
1821
}
1822                        break;
1823                    case IConstantPoolConstant.CONSTANT_Utf8:
1824                        value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
1825
}
1826                buffer.append(value);
1827                break;
1828            case IAnnotationComponentValue.ENUM_TAG:
1829                final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
1830                final char[] constantName = annotationComponentValue.getEnumConstantName();
1831                buffer.append(Signature.toCharArray(typeName)).append('.').append(constantName);
1832                break;
1833            case IAnnotationComponentValue.CLASS_TAG:
1834                constantPoolEntry = annotationComponentValue.getClassInfo();
1835                final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
1836                buffer.append(Signature.toCharArray(className));
1837                break;
1838            case IAnnotationComponentValue.ANNOTATION_TAG:
1839                IAnnotation annotation = annotationComponentValue.getAnnotationValue();
1840                disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode);
1841                break;
1842            case IAnnotationComponentValue.ARRAY_TAG:
1843                final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
1844                buffer.append('{');
1845                for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
1846                    if (i > 0) {
1847                        buffer.append(',');
1848                    }
1849                    disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
1850                }
1851                buffer.append('}');
1852        }
1853    }
1854
1855    private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1856        IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
1857        disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
1858    }
1859    
1860    private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1861        IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
1862        for (int i = 0, max = annotations.length; i < max; i++) {
1863            disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
1864        }
1865    }
1866
1867    private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode) {
1868        IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
1869        for (int i = 0, max = annotations.length; i < max; i++) {
1870            disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
1871        }
1872    }
1873
1874    private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber, int mode, boolean isEnum) {
1875        IFieldInfo[] fields = classFileReader.getFieldInfos();
1876        if (isEnum && checkMode(mode, WORKING_COPY)) {
1877            int index = 0;
1878            final int fieldsLength = fields.length;
1879            IMethodInfo[] methods = classFileReader.getMethodInfos();
1880            char[][] constructorArguments = getConstructorArgumentsForEnum(methods);
1881            enumConstantLoop: for (; index < fieldsLength; index++) {
1882                final IFieldInfo fieldInfo = fields[index];
1883                final int accessFlags = fieldInfo.getAccessFlags();
1884                if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
1885                    writeNewLine(buffer, lineSeparator, tabNumber);
1886                    disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode);
1887                } else {
1888                    break enumConstantLoop;
1889                }
1890            }
1891            buffer.append(';');
1892            boolean foundSyntheticField = false;
1893            fieldLoop: for (; index < fieldsLength; index++) {
1894                if (!foundSyntheticField && CharOperation.equals(TypeConstants.SYNTHETIC_ENUM_VALUES, fields[index].getName())) {
1895                    foundSyntheticField = true;
1896                    continue fieldLoop;
1897                }
1898                writeNewLine(buffer, lineSeparator, tabNumber);
1899                disassemble(fields[index], buffer, lineSeparator, tabNumber, mode);
1900            }
1901            methodLoop: for (int i = 0, max = methods.length; i < max; i++) {
1902                final IMethodInfo methodInfo = methods[i];
1903                if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUES)) {
1904                    final char[] descriptor = methodInfo.getDescriptor();
1905                    CharOperation.replace(descriptor, '/', '.');
1906                    if (Signature.getParameterCount(descriptor) == 0) {
1907                        if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
1908                                CharOperation.concat(new char[] {'[', 'L'}, className, new char[] {';'}))) {
1909                            continue methodLoop;
1910                        }
1911                    }
1912                } else if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUEOF)) {
1913                    final char[] descriptor = methodInfo.getDescriptor();
1914                    CharOperation.replace(descriptor, '/', '.');
1915                    final char[][] parameterTypes = Signature.getParameterTypes(descriptor);
1916                    if (parameterTypes.length == 1
1917                            && CharOperation.equals(parameterTypes[0], "Ljava.lang.String;".toCharArray())) { //$NON-NLS-1$
1918
if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
1919                                CharOperation.concat('L', className, ';'))) {
1920                            continue methodLoop;
1921                        }
1922                    }
1923                } else if (methodInfo.isClinit() || methodInfo.isSynthetic()) {
1924                    continue methodLoop;
1925                } else if (methodInfo.isConstructor()) {
1926                    writeNewLine(buffer, lineSeparator, tabNumber);
1927                    disassembleEnumConstructor(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
1928                } else {
1929                    writeNewLine(buffer, lineSeparator, tabNumber);
1930                    disassemble(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
1931                }
1932            }
1933        } else {
1934            for (int i = 0, max = fields.length; i < max; i++) {
1935                writeNewLine(buffer, lineSeparator, tabNumber);
1936                disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
1937            }
1938            IMethodInfo[] methods = classFileReader.getMethodInfos();
1939            for (int i = 0, max = methods.length; i < max; i++) {
1940                writeNewLine(buffer, lineSeparator, tabNumber);
1941                disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode);
1942            }
1943        }
1944    }
1945    
1946    private char[][] getConstructorArgumentsForEnum(final IMethodInfo[] methods) {
1947        loop: for (int i = 0, max = methods.length; i < max; i++) {
1948            IMethodInfo methodInfo = methods[i];
1949            if (methodInfo.isConstructor()) {
1950                char[][] parameterTypes = Signature.getParameterTypes(methodInfo.getDescriptor());
1951                final int length = parameterTypes.length;
1952                if (length >= 2) {
1953                    return CharOperation.subarray(parameterTypes, 2, length);
1954                }
1955            } else {
1956                continue loop;
1957            }
1958        }
1959        return null;
1960    }
1961
1962    private final void dumpTab(int tabNumber, StringBuffer JavaDoc buffer) {
1963        for (int i = 0; i < tabNumber; i++) {
1964            buffer.append(Messages.disassembler_indentation);
1965        }
1966    }
1967    
1968    private final String JavaDoc dumpNewLineWithTabs(String JavaDoc lineSeparator, int tabNumber) {
1969        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1970        writeNewLine(buffer, lineSeparator, tabNumber);
1971        return String.valueOf(buffer);
1972    }
1973    
1974    /**
1975     * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#getDescription()
1976     */

1977    public String JavaDoc getDescription() {
1978        return Messages.disassembler_description;
1979    }
1980
1981    private IEnclosingMethodAttribute getEnclosingMethodAttribute(IClassFileReader classFileReader) {
1982        IClassFileAttribute[] attributes = classFileReader.getAttributes();
1983        for (int i = 0, max = attributes.length; i < max; i++) {
1984            if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.ENCLOSING_METHOD)) {
1985                return (IEnclosingMethodAttribute) attributes[i];
1986            }
1987        }
1988        return null;
1989    }
1990    private IClassFileAttribute getAttribute(final char[] attributeName, final ICodeAttribute codeAttribute) {
1991        IClassFileAttribute[] attributes = codeAttribute.getAttributes();
1992        for (int i = 0, max = attributes.length; i < max; i++) {
1993            if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
1994                return attributes[i];
1995            }
1996        }
1997        return null;
1998    }
1999    
2000    private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, int accessFlags) {
2001        int paramCount = Signature.getParameterCount(methodDescriptor);
2002        char[][] parameterNames = new char[paramCount][];
2003        // check if the code attribute has debug info for this method
2004
if (codeAttribute != null) {
2005            ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
2006            if (localVariableAttribute != null) {
2007                ILocalVariableTableEntry[] entries = localVariableAttribute.getLocalVariableTable();
2008                final int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1;
2009                for (int i = 0; i < paramCount; i++) {
2010                    ILocalVariableTableEntry searchedEntry = getEntryFor(getLocalIndex(startingIndex, i, methodDescriptor), entries);
2011                    if (searchedEntry != null) {
2012                        parameterNames[i] = searchedEntry.getName();
2013                    } else {
2014                        parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2015                    }
2016                }
2017            } else {
2018                for (int i = 0; i < paramCount; i++) {
2019                    parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2020                }
2021            }
2022        } else {
2023            for (int i = 0; i < paramCount; i++) {
2024                parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2025            }
2026        }
2027        return parameterNames;
2028    }
2029    
2030    private int getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor) {
2031        int slot = startingSlot;
2032        final char[][] types = Signature.getParameterTypes(methodDescriptor);
2033        for (int i = 0; i < index; i++) {
2034            final char[] type = types[i];
2035            switch(type.length) {
2036                case 1 :
2037                    switch(type[0]) {
2038                        case 'D' :
2039                        case 'J' :
2040                            slot += 2;
2041                            break;
2042                        default :
2043                            slot++;
2044                    }
2045                    break;
2046                default :
2047                    slot++;
2048            }
2049        }
2050        return slot;
2051    }
2052
2053    private ILocalVariableTableEntry getEntryFor(final int index, final ILocalVariableTableEntry[] entries) {
2054        for (int i = 0, max = entries.length; i < max; i++) {
2055            ILocalVariableTableEntry entry = entries[i];
2056            if (index == entry.getIndex()) {
2057                return entry;
2058            }
2059        }
2060        return null;
2061    }
2062
2063    private char[] getSignatureForField(char[] fieldDescriptor) {
2064        char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.');
2065        newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%');
2066        char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
2067        CharOperation.replace(fieldDescriptorSignature, '%', '$');
2068        return fieldDescriptorSignature;
2069    }
2070    
2071    private boolean isDeprecated(IClassFileReader classFileReader) {
2072        IClassFileAttribute[] attributes = classFileReader.getAttributes();
2073        for (int i = 0, max = attributes.length; i < max; i++) {
2074            if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) {
2075                return true;
2076            }
2077        }
2078        return false;
2079    }
2080    
2081    private boolean isSynthetic(IClassFileReader classFileReader) {
2082        int flags = classFileReader.getAccessFlags();
2083        if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
2084            return true;
2085        }
2086        IClassFileAttribute[] attributes = classFileReader.getAttributes();
2087        for (int i = 0, max = attributes.length; i < max; i++) {
2088            if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
2089                return true;
2090            }
2091        }
2092        return false;
2093    }
2094    
2095    private boolean checkMode(int mode, int flag) {
2096        return (mode & flag) != 0;
2097    }
2098    
2099    private boolean isCompact(int mode) {
2100        return (mode & ClassFileBytesDisassembler.COMPACT) != 0;
2101    }
2102
2103    private char[] returnClassName(char[] classInfoName, char separator, int mode) {
2104        if (classInfoName.length == 0) {
2105            return CharOperation.NO_CHAR;
2106        } else if (isCompact(mode)) {
2107            int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName);
2108            if (lastIndexOfSlash != -1) {
2109                return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length);
2110            }
2111        }
2112        return classInfoName;
2113    }
2114    
2115    private void writeNewLine(StringBuffer JavaDoc buffer, String JavaDoc lineSeparator, int tabNumber) {
2116        buffer.append(lineSeparator);
2117        dumpTab(tabNumber, buffer);
2118    }
2119}
2120
Popular Tags