Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Disassembler.java')
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Disassembler.java1145
1 files changed, 1145 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Disassembler.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Disassembler.java
new file mode 100644
index 000000000..69a9bfb3c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Disassembler.java
@@ -0,0 +1,1145 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.internal.repository.comparator.java;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Disassembler of .class files. It generates an output in the Writer that looks close to
+ * the javap output.
+ */
+public class Disassembler {
+ /**
+ * The mode is the detailed mode to disassemble ClassFileReader. It returns the magic
+ * numbers, the version numbers and field and method descriptors.
+ */
+ public final static int DETAILED = 1;
+
+ /**
+ * This mode is used to compact the class name to a simple name instead of a qualified name.
+ * @since 3.1
+ */
+ public final static int COMPACT = 8;
+
+ private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray();
+ private static final String VERSION_UNKNOWN = Messages.classfileformat_versionUnknown;
+
+ private boolean appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier) {
+ if ((accessFlags & modifierConstant) != 0) {
+ if (!firstModifier) {
+ buffer.append(Messages.disassembler_space);
+ }
+ if (firstModifier) {
+ firstModifier = false;
+ }
+ buffer.append(modifier);
+ }
+ return firstModifier;
+ }
+
+ private void decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits) {
+ decodeModifiers(buffer, accessFlags, false, false, checkBits);
+ }
+
+ private void decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) {
+ if (checkBits == null)
+ return;
+ boolean firstModifier = true;
+ for (int i = 0, max = checkBits.length; i < max; i++) {
+ switch (checkBits[i]) {
+ case IModifierConstants.ACC_PUBLIC :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_PROTECTED :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_PRIVATE :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_ABSTRACT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_STATIC :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_FINAL :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_SYNCHRONIZED :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_NATIVE :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_STRICT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_TRANSIENT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_VOLATILE :
+ // case IModifierConstants.ACC_BRIDGE :
+ if (asBridge) {
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$
+ } else {
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$
+ }
+ break;
+ case IModifierConstants.ACC_ENUM :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$
+ break;
+ }
+ }
+ if (!firstModifier) {
+ if (!printDefault)
+ buffer.append(Messages.disassembler_space);
+ } else if (printDefault) {
+ // no modifier: package default visibility
+ buffer.append("default"); //$NON-NLS-1$
+ }
+ }
+
+ private void decodeModifiersForField(StringBuffer buffer, int accessFlags) {
+ decodeModifiers(buffer, accessFlags, new int[] {IModifierConstants.ACC_PUBLIC, IModifierConstants.ACC_PROTECTED, IModifierConstants.ACC_PRIVATE, IModifierConstants.ACC_STATIC, IModifierConstants.ACC_FINAL, IModifierConstants.ACC_TRANSIENT, IModifierConstants.ACC_VOLATILE, IModifierConstants.ACC_ENUM});
+ }
+
+ private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault) {
+ decodeModifiers(buffer, accessFlags, printDefault, false, new int[] {IModifierConstants.ACC_PUBLIC, IModifierConstants.ACC_PROTECTED, IModifierConstants.ACC_PRIVATE, IModifierConstants.ACC_ABSTRACT, IModifierConstants.ACC_STATIC, IModifierConstants.ACC_FINAL,});
+ }
+
+ private final void decodeModifiersForMethod(StringBuffer buffer, int accessFlags) {
+ decodeModifiers(buffer, accessFlags, false, true, new int[] {IModifierConstants.ACC_PUBLIC, IModifierConstants.ACC_PROTECTED, IModifierConstants.ACC_PRIVATE, IModifierConstants.ACC_ABSTRACT, IModifierConstants.ACC_STATIC, IModifierConstants.ACC_FINAL, IModifierConstants.ACC_SYNCHRONIZED, IModifierConstants.ACC_NATIVE, IModifierConstants.ACC_STRICT, IModifierConstants.ACC_BRIDGE,});
+ }
+
+ private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) {
+ decodeModifiers(buffer, accessFlags, new int[] {IModifierConstants.ACC_PUBLIC, IModifierConstants.ACC_ABSTRACT, IModifierConstants.ACC_FINAL,});
+ }
+
+ public static String escapeString(String s) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0, max = s.length(); i < max; i++) {
+ char c = s.charAt(i);
+ switch (c) {
+ case '\b' :
+ buffer.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ buffer.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ buffer.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ buffer.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ buffer.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ buffer.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ buffer.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ buffer.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ buffer.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ buffer.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ buffer.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ buffer.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ buffer.append("\\7"); //$NON-NLS-1$
+ break;
+ default :
+ buffer.append(c);
+ }
+ }
+ return buffer.toString();
+ }
+
+ static String decodeStringValue(char[] chars) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0, max = chars.length; i < max; i++) {
+ char c = chars[i];
+ switch (c) {
+ case '\b' :
+ buffer.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ buffer.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ buffer.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ buffer.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ buffer.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ buffer.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ buffer.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ buffer.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ buffer.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ buffer.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ buffer.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ buffer.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ buffer.append("\\7"); //$NON-NLS-1$
+ break;
+ default :
+ buffer.append(c);
+ }
+ }
+ return buffer.toString();
+ }
+
+ static String decodeStringValue(String s) {
+ return decodeStringValue(s.toCharArray());
+ }
+
+ /*
+ * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String, int)
+ */
+ public String disassemble(byte[] classFileBytes, String lineSeparator, int mode) throws ClassFormatException {
+ try {
+ return disassemble(new ClassFileReader(classFileBytes, ClassFileReader.ALL), lineSeparator, mode);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new ClassFormatException(e.getMessage(), e);
+ }
+ }
+
+ private void disassemble(Annotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
+ buffer.append(NLS.bind(Messages.disassembler_annotationentrystart, new String[] {new String(returnClassName(Signature.toCharArray(typeName), '.', mode))}));
+ final AnnotationComponent[] components = annotation.getComponents();
+ for (int i = 0, max = components.length; i < max; i++) {
+ disassemble(components[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_annotationentryend);
+ }
+
+ private void disassemble(AnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(NLS.bind(Messages.disassembler_annotationcomponent, new String[] {new String(annotationComponent.getComponentName())}));
+ disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
+ }
+
+ private void disassemble(AnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ switch (annotationComponentValue.getTag()) {
+ case AnnotationComponentValue.BYTE_TAG :
+ case AnnotationComponentValue.CHAR_TAG :
+ case AnnotationComponentValue.DOUBLE_TAG :
+ case AnnotationComponentValue.FLOAT_TAG :
+ case AnnotationComponentValue.INTEGER_TAG :
+ case AnnotationComponentValue.LONG_TAG :
+ case AnnotationComponentValue.SHORT_TAG :
+ case AnnotationComponentValue.BOOLEAN_TAG :
+ case AnnotationComponentValue.STRING_TAG :
+ ConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
+ String value = null;
+ switch (constantPoolEntry.getKind()) {
+ case ConstantPoolConstant.CONSTANT_Long :
+ value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Float :
+ value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Double :
+ value = Double.toString(constantPoolEntry.getDoubleValue());
+ break;
+ case ConstantPoolConstant.CONSTANT_Integer :
+ switch (annotationComponentValue.getTag()) {
+ case AnnotationComponentValue.CHAR_TAG :
+ value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case AnnotationComponentValue.BOOLEAN_TAG :
+ value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case AnnotationComponentValue.BYTE_TAG :
+ value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ break;
+ case AnnotationComponentValue.SHORT_TAG :
+ value = "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ break;
+ case AnnotationComponentValue.INTEGER_TAG :
+ value = "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ }
+ break;
+ case ConstantPoolConstant.CONSTANT_Utf8 :
+ value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
+ }
+ buffer.append(NLS.bind(Messages.disassembler_annotationdefaultvalue, value));
+ break;
+ case AnnotationComponentValue.ENUM_TAG :
+ final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
+ final char[] constantName = annotationComponentValue.getEnumConstantName();
+ buffer.append(NLS.bind(Messages.disassembler_annotationenumvalue, new String[] {new String(returnClassName(Signature.toCharArray(typeName), '.', mode)), new String(constantName)}));
+ break;
+ case AnnotationComponentValue.CLASS_TAG :
+ constantPoolEntry = annotationComponentValue.getClassInfo();
+ final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
+ buffer.append(NLS.bind(Messages.disassembler_annotationclassvalue, new String[] {new String(returnClassName(Signature.toCharArray(className), '.', mode))}));
+ break;
+ case AnnotationComponentValue.ANNOTATION_TAG :
+ buffer.append(Messages.disassembler_annotationannotationvalue);
+ Annotation annotation = annotationComponentValue.getAnnotationValue();
+ disassemble(annotation, buffer, lineSeparator, tabNumber + 1, mode);
+ break;
+ case AnnotationComponentValue.ARRAY_TAG :
+ buffer.append(Messages.disassembler_annotationarrayvaluestart);
+ final AnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
+ for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_annotationarrayvalueend);
+ }
+ }
+
+ private void disassemble(AnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_annotationdefaultheader);
+ AnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
+ writeNewLine(buffer, lineSeparator, tabNumber + 2);
+ disassemble(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
+ }
+
+ /**
+ * Disassemble a method info header
+ */
+ private void disassemble(ClassFileReader classFileReader, char[] className, MethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ final CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
+ final char[] methodDescriptor = methodInfo.getDescriptor();
+ final SignatureAttribute signatureAttribute = (SignatureAttribute) Utility.getAttribute(methodInfo, AttributeNamesConstants.SIGNATURE);
+ final ClassFileAttribute runtimeVisibleAnnotationsAttribute = Utility.getAttribute(methodInfo, AttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final ClassFileAttribute runtimeInvisibleAnnotationsAttribute = Utility.getAttribute(methodInfo, AttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ final ClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Utility.getAttribute(methodInfo, AttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
+ final ClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Utility.getAttribute(methodInfo, AttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
+ final ClassFileAttribute annotationDefaultAttribute = Utility.getAttribute(methodInfo, AttributeNamesConstants.ANNOTATION_DEFAULT);
+ if (checkMode(mode, DETAILED)) {
+ buffer.append(NLS.bind(Messages.classfileformat_methoddescriptor, new String[] {new String(methodDescriptor)}));
+ if (methodInfo.isDeprecated()) {
+ buffer.append(Messages.disassembler_deprecated);
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ if (signatureAttribute != null) {
+ buffer.append(NLS.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ if (codeAttribute != null) {
+ buffer.append(NLS.bind(Messages.classfileformat_stacksAndLocals, new String[] {Integer.toString(codeAttribute.getMaxStack()), Integer.toString(codeAttribute.getMaxLocals())}));
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ // disassemble compact version of annotations
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ }
+ final int accessFlags = methodInfo.getAccessFlags();
+ decodeModifiersForMethod(buffer, accessFlags);
+ if (methodInfo.isSynthetic()) {
+ buffer.append("synthetic"); //$NON-NLS-1$
+ buffer.append(Messages.disassembler_space);
+ }
+ CharOperation.replace(methodDescriptor, '/', '.');
+ final boolean isVarArgs = isVarArgs(methodInfo);
+ char[] methodHeader = null;
+ if (methodInfo.isConstructor()) {
+ methodHeader = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), null, !checkMode(mode, COMPACT), false, isVarArgs);
+ } else if (methodInfo.isClinit()) {
+ methodHeader = Messages.classfileformat_clinitname.toCharArray();
+ } else {
+ methodHeader = Signature.toCharArray(methodDescriptor, methodInfo.getName(), null, !checkMode(mode, COMPACT), true, isVarArgs);
+ }
+ if (checkMode(mode, DETAILED) && (runtimeInvisibleParameterAnnotationsAttribute != null || runtimeVisibleParameterAnnotationsAttribute != null)) {
+ ParameterAnnotation[] invisibleParameterAnnotations = null;
+ ParameterAnnotation[] visibleParameterAnnotations = null;
+ int length = -1;
+ if (runtimeInvisibleParameterAnnotationsAttribute != null) {
+ RuntimeInvisibleParameterAnnotationsAttribute attribute = (RuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute;
+ invisibleParameterAnnotations = attribute.getParameterAnnotations();
+ length = invisibleParameterAnnotations.length;
+ }
+ if (runtimeVisibleParameterAnnotationsAttribute != null) {
+ RuntimeVisibleParameterAnnotationsAttribute attribute = (RuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute;
+ visibleParameterAnnotations = attribute.getParameterAnnotations();
+ length = visibleParameterAnnotations.length;
+ }
+ int insertionPosition = CharOperation.indexOf('(', methodHeader) + 1;
+ int start = 0;
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(methodHeader, 0, insertionPosition);
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ stringBuffer.append(' ');
+ }
+ int stringBufferSize = stringBuffer.length();
+ if (runtimeVisibleParameterAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, stringBuffer, i, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeInvisibleParameterAnnotationsAttribute != null) {
+ if (stringBuffer.length() != stringBufferSize) {
+ stringBuffer.append(' ');
+ stringBufferSize = stringBuffer.length();
+ }
+ disassembleAsModifier((RuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, stringBuffer, i, lineSeparator, tabNumber, mode);
+ }
+ if (i == 0 && stringBuffer.length() != stringBufferSize) {
+ stringBuffer.append(' ');
+ }
+ start = insertionPosition;
+ insertionPosition = CharOperation.indexOf(',', methodHeader, start + 1) + 1;
+ if (insertionPosition == 0) {
+ stringBuffer.append(methodHeader, start, methodHeader.length - start);
+ } else {
+ stringBuffer.append(methodHeader, start, insertionPosition - start);
+ }
+ }
+ buffer.append(stringBuffer);
+ } else {
+ buffer.append(methodHeader);
+ }
+ ExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
+ if (exceptionAttribute != null) {
+ buffer.append(" throws "); //$NON-NLS-1$
+ char[][] exceptionNames = exceptionAttribute.getExceptionNames();
+ int length = exceptionNames.length;
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma).append(Messages.disassembler_space);
+ }
+ char[] exceptionName = exceptionNames[i];
+ CharOperation.replace(exceptionName, '/', '.');
+ buffer.append(returnClassName(exceptionName, '.', mode));
+ }
+ }
+ if (checkMode(mode, DETAILED)) {
+ if (annotationDefaultAttribute != null) {
+ buffer.append(" default "); //$NON-NLS-1$
+ disassembleAsModifier((AnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ }
+ buffer.append(Messages.disassembler_endofmethodheader);
+
+ if (checkMode(mode, DETAILED)) {
+ if (codeAttribute != null) {
+ disassemble(codeAttribute, methodDescriptor, (accessFlags & IModifierConstants.ACC_STATIC) != 0, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (annotationDefaultAttribute != null) {
+ disassemble((AnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeVisibleParameterAnnotationsAttribute != null) {
+ disassemble((RuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeInvisibleParameterAnnotationsAttribute != null) {
+ disassemble((RuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ }
+ }
+
+ /**
+ * Answers back the disassembled string of the ClassFileReader according to the
+ * mode.
+ * This is an output quite similar to the javap tool.
+ *
+ * @param classFileReader The classFileReader to be disassembled
+ * @param lineSeparator the line separator to use.
+ * @param mode the mode used to disassemble the ClassFileReader
+ *
+ * @return the disassembled string of the ClassFileReader according to the mode
+ */
+ private String disassemble(ClassFileReader classFileReader, String lineSeparator, int mode) {
+ if (classFileReader == null)
+ return Utility.EMPTY_STRING;
+ char[] className = classFileReader.getClassName();
+ if (className == null) {
+ // incomplete initialization. We cannot go further.
+ return Utility.EMPTY_STRING;
+ }
+ className = CharOperation.replaceOnCopy(className, '/', '.');
+ final int accessFlags = classFileReader.getAccessFlags();
+ final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0;
+
+ StringBuffer buffer = new StringBuffer();
+ SourceFileAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
+ ClassFileAttribute classFileAttribute = Utility.getAttribute(classFileReader, AttributeNamesConstants.SIGNATURE);
+ SignatureAttribute signatureAttribute = (SignatureAttribute) classFileAttribute;
+ if (checkMode(mode, DETAILED)) {
+ int minorVersion = classFileReader.getMinorVersion();
+ int majorVersion = classFileReader.getMajorVersion();
+ buffer.append(Messages.disassembler_begincommentline);
+ if (sourceAttribute != null) {
+ buffer.append(Messages.disassembler_sourceattributeheader);
+ buffer.append(sourceAttribute.getSourceFileName());
+ }
+ String versionNumber = VERSION_UNKNOWN;
+ if (minorVersion == 3 && majorVersion == 45) {
+ versionNumber = IModifierConstants.VERSION_1_1;
+ } else if (minorVersion == 0 && majorVersion == 46) {
+ versionNumber = IModifierConstants.VERSION_1_2;
+ } else if (minorVersion == 0 && majorVersion == 47) {
+ versionNumber = IModifierConstants.VERSION_1_3;
+ } else if (minorVersion == 0 && majorVersion == 48) {
+ versionNumber = IModifierConstants.VERSION_1_4;
+ } else if (minorVersion == 0 && majorVersion == 49) {
+ versionNumber = IModifierConstants.VERSION_1_5;
+ } else if (minorVersion == 0 && majorVersion == 50) {
+ versionNumber = IModifierConstants.VERSION_1_6;
+ } else if (minorVersion == 0 && majorVersion == 51) {
+ versionNumber = IModifierConstants.VERSION_1_7;
+ }
+ buffer.append(NLS.bind(Messages.classfileformat_versiondetails, new String[] {versionNumber, Integer.toString(majorVersion), Integer.toString(minorVersion), ((accessFlags & IModifierConstants.ACC_SUPER) != 0 ? Messages.classfileformat_superflagisset : Messages.classfileformat_superflagisnotset) + (isDeprecated(classFileReader) ? ", deprecated" : Utility.EMPTY_STRING)//$NON-NLS-1$
+ }));
+ writeNewLine(buffer, lineSeparator, 0);
+ if (signatureAttribute != null) {
+ buffer.append(NLS.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
+ writeNewLine(buffer, lineSeparator, 0);
+ }
+ }
+
+ InnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
+ ClassFileAttribute runtimeVisibleAnnotationsAttribute = Utility.getAttribute(classFileReader, AttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ ClassFileAttribute runtimeInvisibleAnnotationsAttribute = Utility.getAttribute(classFileReader, AttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+
+ if (checkMode(mode, DETAILED)) {
+ // disassemble compact version of annotations
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
+ writeNewLine(buffer, lineSeparator, 0);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
+ writeNewLine(buffer, lineSeparator, 0);
+ }
+ }
+ boolean decoded = false;
+ if (innerClassesAttribute != null) {
+ // search the right entry
+ InnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
+ for (int i = 0, max = entries.length; i < max; i++) {
+ InnerClassesAttributeEntry entry = entries[i];
+ char[] innerClassName = entry.getInnerClassName();
+ if (innerClassName != null) {
+ if (Arrays.equals(classFileReader.getClassName(), innerClassName)) {
+ decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false);
+ decoded = true;
+ }
+ }
+ }
+ }
+ if (!decoded) {
+ decodeModifiersForType(buffer, accessFlags);
+ if (isSynthetic(classFileReader)) {
+ buffer.append("synthetic"); //$NON-NLS-1$
+ buffer.append(Messages.disassembler_space);
+ }
+ }
+
+ final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0;
+ boolean isInterface = false;
+ if (isEnum) {
+ buffer.append("enum "); //$NON-NLS-1$
+ } else if (classFileReader.isClass()) {
+ buffer.append("class "); //$NON-NLS-1$
+ } else {
+ if (isAnnotation) {
+ buffer.append("@"); //$NON-NLS-1$
+ }
+ buffer.append("interface "); //$NON-NLS-1$
+ isInterface = true;
+ }
+
+ buffer.append(className);
+
+ char[] superclassName = classFileReader.getSuperclassName();
+ if (superclassName != null) {
+ CharOperation.replace(superclassName, '/', '.');
+ if (!isJavaLangObject(superclassName) && !isEnum) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ buffer.append(returnClassName(superclassName, '.', mode));
+ }
+ }
+ if (!isAnnotation) {
+ char[][] superclassInterfaces = classFileReader.getInterfaceNames();
+ int length = superclassInterfaces.length;
+ if (length != 0) {
+ if (isInterface) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ } else {
+ buffer.append(" implements "); //$NON-NLS-1$
+ }
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma).append(Messages.disassembler_space);
+ }
+ char[] superinterface = superclassInterfaces[i];
+ CharOperation.replace(superinterface, '/', '.');
+ buffer.append(returnClassName(superinterface, '.', mode));
+ }
+ }
+ }
+ buffer.append(Messages.disassembler_opentypedeclaration);
+ disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum);
+ if (checkMode(mode, DETAILED)) {
+ ClassFileAttribute[] attributes = classFileReader.getAttributes();
+ int length = attributes.length;
+ EnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader);
+ int remainingAttributesLength = length;
+ if (innerClassesAttribute != null) {
+ remainingAttributesLength--;
+ }
+ if (enclosingMethodAttribute != null) {
+ remainingAttributesLength--;
+ }
+ if (sourceAttribute != null) {
+ remainingAttributesLength--;
+ }
+ if (signatureAttribute != null) {
+ remainingAttributesLength--;
+ }
+ if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) {
+ writeNewLine(buffer, lineSeparator, 0);
+ }
+ if (innerClassesAttribute != null) {
+ disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
+ }
+ if (enclosingMethodAttribute != null) {
+ disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
+ }
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
+ }
+ }
+ writeNewLine(buffer, lineSeparator, 0);
+ buffer.append(Messages.disassembler_closetypedeclaration);
+ return buffer.toString();
+ }
+
+ private boolean isJavaLangObject(final char[] className) {
+ return Arrays.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className));
+ }
+
+ private boolean isVarArgs(MethodInfo methodInfo) {
+ int accessFlags = methodInfo.getAccessFlags();
+ if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0)
+ return true;
+ // check the presence of the unspecified Varargs attribute
+ return Utility.getAttribute(methodInfo, AttributeNamesConstants.VAR_ARGS) != null;
+ }
+
+ private void disassemble(CodeAttribute codeAttribute, char[] methodDescriptor, boolean isStatic, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber - 1);
+ DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, methodDescriptor, isStatic, buffer, lineSeparator, tabNumber, mode);
+ try {
+ codeAttribute.traverse(visitor);
+ } catch (ClassFormatException e) {
+ dumpTab(tabNumber + 2, buffer);
+ buffer.append(Messages.classformat_classformatexception);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ }
+ final int exceptionTableLength = codeAttribute.getExceptionTableLength();
+ if (exceptionTableLength != 0) {
+ final int tabNumberForExceptionAttribute = tabNumber + 2;
+ dumpTab(tabNumberForExceptionAttribute, buffer);
+ final ExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
+ buffer.append(Messages.disassembler_exceptiontableheader);
+ writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
+ for (int i = 0; i < exceptionTableLength; i++) {
+ if (i != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
+ }
+ ExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i];
+ char[] catchType;
+ if (exceptionTableEntry.getCatchTypeIndex() != 0) {
+ catchType = exceptionTableEntry.getCatchType();
+ CharOperation.replace(catchType, '/', '.');
+ catchType = returnClassName(catchType, '.', mode);
+ } else {
+ catchType = ANY_EXCEPTION;
+ }
+ buffer.append(NLS.bind(Messages.classfileformat_exceptiontableentry, new String[] {Integer.toString(exceptionTableEntry.getStartPC()), Integer.toString(exceptionTableEntry.getEndPC()), Integer.toString(exceptionTableEntry.getHandlerPC()), new String(catchType),}));
+ }
+ }
+ }
+
+ private void disassemble(EnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_enclosingmethodheader);
+ buffer.append(" ")//$NON-NLS-1$
+ .append(enclosingMethodAttribute.getEnclosingClass());
+ if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) {
+ buffer.append(".")//$NON-NLS-1$
+ .append(enclosingMethodAttribute.getMethodName()).append(enclosingMethodAttribute.getMethodDescriptor());
+ }
+ }
+
+ /**
+ * Disassemble a field info
+ */
+ private void disassemble(FieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ final char[] fieldDescriptor = fieldInfo.getDescriptor();
+ final SignatureAttribute signatureAttribute = (SignatureAttribute) Utility.getAttribute(fieldInfo, AttributeNamesConstants.SIGNATURE);
+ if (checkMode(mode, DETAILED)) {
+ buffer.append(NLS.bind(Messages.classfileformat_fieldddescriptor, new String[] {new String(fieldDescriptor)}));
+ if (fieldInfo.isDeprecated()) {
+ buffer.append(Messages.disassembler_deprecated);
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ if (signatureAttribute != null) {
+ buffer.append(NLS.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ }
+ final ClassFileAttribute runtimeVisibleAnnotationsAttribute = Utility.getAttribute(fieldInfo, AttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final ClassFileAttribute runtimeInvisibleAnnotationsAttribute = Utility.getAttribute(fieldInfo, AttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ if (checkMode(mode, DETAILED)) {
+ // disassemble compact version of annotations
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ }
+ decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
+ if (fieldInfo.isSynthetic()) {
+ buffer.append("synthetic"); //$NON-NLS-1$
+ buffer.append(Messages.disassembler_space);
+ }
+ buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
+ buffer.append(' ');
+ buffer.append(new String(fieldInfo.getName()));
+ ConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
+ if (constantValueAttribute != null) {
+ buffer.append(Messages.disassembler_fieldhasconstant);
+ ConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue();
+ switch (constantPoolEntry.getKind()) {
+ case ConstantPoolConstant.CONSTANT_Long :
+ buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Float :
+ buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Double :
+ buffer.append(constantPoolEntry.getDoubleValue());
+ break;
+ case ConstantPoolConstant.CONSTANT_Integer :
+ switch (fieldDescriptor[0]) {
+ case 'C' :
+ buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case 'Z' :
+ buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case 'B' :
+ buffer.append(constantPoolEntry.getIntegerValue());
+ break;
+ case 'S' :
+ buffer.append(constantPoolEntry.getIntegerValue());
+ break;
+ case 'I' :
+ buffer.append(constantPoolEntry.getIntegerValue());
+ }
+ break;
+ case ConstantPoolConstant.CONSTANT_String :
+ buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"");//$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+ buffer.append(Messages.disassembler_endoffieldheader);
+ if (checkMode(mode, DETAILED)) {
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassemble((RuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ }
+ }
+
+ private void disassemble(InnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ buffer.append(Messages.disassembler_innerattributesheader);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ InnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries();
+ int length = innerClassesAttributeEntries.length;
+ int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
+ InnerClassesAttributeEntry innerClassesAttributeEntry;
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ }
+ innerClassesAttributeEntry = innerClassesAttributeEntries[i];
+ innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
+ outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
+ innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
+ accessFlags = innerClassesAttributeEntry.getAccessFlags();
+ buffer.append(Messages.disassembler_openinnerclassentry).append(Messages.disassembler_inner_class_info_name);
+ if (innerClassNameIndex != 0) {
+ buffer.append(Messages.disassembler_space).append(innerClassesAttributeEntry.getInnerClassName());
+ }
+ buffer.append(Messages.disassembler_comma).append(Messages.disassembler_space).append(Messages.disassembler_outer_class_info_name);
+ if (outerClassNameIndex != 0) {
+ buffer.append(Messages.disassembler_space).append(innerClassesAttributeEntry.getOuterClassName());
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ dumpTab(tabNumber, buffer);
+ buffer.append(Messages.disassembler_space);
+ buffer.append(Messages.disassembler_inner_name);
+ if (innerNameIndex != 0) {
+ buffer.append(Messages.disassembler_space).append(innerClassesAttributeEntry.getInnerName());
+ }
+ buffer.append(Messages.disassembler_comma).append(Messages.disassembler_space).append(Messages.disassembler_inner_accessflags).append(accessFlags).append(Messages.disassembler_space);
+ decodeModifiersForInnerClasses(buffer, accessFlags, true);
+ buffer.append(Messages.disassembler_closeinnerclassentry);
+ }
+ }
+
+ private void disassemble(int index, ParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ Annotation[] annotations = parameterAnnotation.getAnnotations();
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(NLS.bind(Messages.disassembler_parameterannotationentrystart, new String[] {Integer.toString(index), Integer.toString(annotations.length)}));
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassemble(RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_runtimeinvisibleannotationsattributeheader);
+ Annotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassemble(RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_runtimeinvisibleparameterannotationsattributeheader);
+ ParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations();
+ for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
+ disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassemble(RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader);
+ Annotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassemble(RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append(Messages.disassembler_runtimevisibleparameterannotationsattributeheader);
+ ParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations();
+ for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
+ disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleAsModifier(Annotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
+ buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode));
+ final AnnotationComponent[] components = annotation.getComponents();
+ final int length = components.length;
+ if (length != 0) {
+ buffer.append('(');
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ buffer.append(')');
+ }
+ }
+
+ private void disassembleAsModifier(AnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ buffer.append(annotationComponent.getComponentName()).append('=');
+ disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
+ }
+
+ private void disassembleAsModifier(AnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ switch (annotationComponentValue.getTag()) {
+ case AnnotationComponentValue.BYTE_TAG :
+ case AnnotationComponentValue.CHAR_TAG :
+ case AnnotationComponentValue.DOUBLE_TAG :
+ case AnnotationComponentValue.FLOAT_TAG :
+ case AnnotationComponentValue.INTEGER_TAG :
+ case AnnotationComponentValue.LONG_TAG :
+ case AnnotationComponentValue.SHORT_TAG :
+ case AnnotationComponentValue.BOOLEAN_TAG :
+ case AnnotationComponentValue.STRING_TAG :
+ ConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
+ String value = null;
+ switch (constantPoolEntry.getKind()) {
+ case ConstantPoolConstant.CONSTANT_Long :
+ value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Float :
+ value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
+ break;
+ case ConstantPoolConstant.CONSTANT_Double :
+ value = Double.toString(constantPoolEntry.getDoubleValue());
+ break;
+ case ConstantPoolConstant.CONSTANT_Integer :
+ switch (annotationComponentValue.getTag()) {
+ case AnnotationComponentValue.CHAR_TAG :
+ value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; //$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case AnnotationComponentValue.BOOLEAN_TAG :
+ value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false";//$NON-NLS-1$//$NON-NLS-2$
+ break;
+ case AnnotationComponentValue.BYTE_TAG :
+ value = "(byte) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ break;
+ case AnnotationComponentValue.SHORT_TAG :
+ value = "(short) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ break;
+ case AnnotationComponentValue.INTEGER_TAG :
+ value = "(int) " + constantPoolEntry.getIntegerValue(); //$NON-NLS-1$
+ }
+ break;
+ case ConstantPoolConstant.CONSTANT_Utf8 :
+ value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
+ }
+ buffer.append(value);
+ break;
+ case AnnotationComponentValue.ENUM_TAG :
+ final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
+ final char[] constantName = annotationComponentValue.getEnumConstantName();
+ buffer.append(returnClassName(Signature.toCharArray(typeName), '.', mode)).append('.').append(constantName);
+ break;
+ case AnnotationComponentValue.CLASS_TAG :
+ constantPoolEntry = annotationComponentValue.getClassInfo();
+ final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
+ buffer.append(returnClassName(Signature.toCharArray(className), '.', mode));
+ break;
+ case AnnotationComponentValue.ANNOTATION_TAG :
+ Annotation annotation = annotationComponentValue.getAnnotationValue();
+ disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode);
+ break;
+ case AnnotationComponentValue.ARRAY_TAG :
+ final AnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
+ buffer.append('{');
+ for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ }
+ disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ buffer.append('}');
+ }
+ }
+
+ private void disassembleAsModifier(AnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ AnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
+ disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
+ }
+
+ private void disassembleAsModifier(RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ Annotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleAsModifier(RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode) {
+ ParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations();
+ if (parameterAnnotations.length > index) {
+ disassembleAsModifier(parameterAnnotations[index], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleAsModifier(RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode) {
+ ParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations();
+ if (parameterAnnotations.length > index) {
+ disassembleAsModifier(parameterAnnotations[index], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleAsModifier(ParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ Annotation[] annotations = parameterAnnotation.getAnnotations();
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ if (i > 0) {
+ buffer.append(' ');
+ }
+ disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleAsModifier(RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ Annotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
+ for (int i = 0, max = annotations.length; i < max; i++) {
+ if (i > 0) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ }
+
+ private void disassembleTypeMembers(ClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) {
+ FieldInfo[] fields = classFileReader.getFieldInfos();
+ // sort fields
+ Arrays.sort(fields, new Comparator<FieldInfo>() {
+ public int compare(FieldInfo fieldInfo1, FieldInfo fieldInfo2) {
+ int compare = new String(fieldInfo1.getName()).compareTo(new String(fieldInfo2.getName()));
+ if (compare == 0) {
+ return new String(fieldInfo1.getDescriptor()).compareTo(new String(fieldInfo2.getDescriptor()));
+ }
+ return compare;
+ }
+ });
+ for (int i = 0, max = fields.length; i < max; i++) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
+ }
+ MethodInfo[] methods = classFileReader.getMethodInfos();
+ // sort methods
+ Arrays.sort(methods, new Comparator<MethodInfo>() {
+ public int compare(MethodInfo methodInfo1, MethodInfo methodInfo2) {
+ int compare = new String(methodInfo1.getName()).compareTo(new String(methodInfo2.getName()));
+ if (compare == 0) {
+ return new String(methodInfo1.getDescriptor()).compareTo(new String(methodInfo2.getDescriptor()));
+ }
+ return compare;
+ }
+ });
+ for (int i = 0, max = methods.length; i < max; i++) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode);
+ }
+ }
+
+ private final void dumpTab(int tabNumber, StringBuffer buffer) {
+ for (int i = 0; i < tabNumber; i++) {
+ buffer.append(Messages.disassembler_indentation);
+ }
+ }
+
+ private EnclosingMethodAttribute getEnclosingMethodAttribute(ClassFileReader classFileReader) {
+ ClassFileAttribute[] attributes = classFileReader.getAttributes();
+ for (int i = 0, max = attributes.length; i < max; i++) {
+ if (Arrays.equals(attributes[i].getAttributeName(), AttributeNamesConstants.ENCLOSING_METHOD)) {
+ return (EnclosingMethodAttribute) attributes[i];
+ }
+ }
+ return null;
+ }
+
+ private char[] getSignatureForField(char[] fieldDescriptor) {
+ char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.');
+ newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%');
+ char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
+ CharOperation.replace(fieldDescriptorSignature, '%', '$');
+ return fieldDescriptorSignature;
+ }
+
+ private boolean isDeprecated(ClassFileReader classFileReader) {
+ ClassFileAttribute[] attributes = classFileReader.getAttributes();
+ for (int i = 0, max = attributes.length; i < max; i++) {
+ if (Arrays.equals(attributes[i].getAttributeName(), AttributeNamesConstants.DEPRECATED)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isSynthetic(ClassFileReader classFileReader) {
+ int flags = classFileReader.getAccessFlags();
+ if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
+ return true;
+ }
+ ClassFileAttribute[] attributes = classFileReader.getAttributes();
+ for (int i = 0, max = attributes.length; i < max; i++) {
+ if (Arrays.equals(attributes[i].getAttributeName(), AttributeNamesConstants.SYNTHETIC)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkMode(int mode, int flag) {
+ return (mode & flag) != 0;
+ }
+
+ private boolean isCompact(int mode) {
+ return (mode & Disassembler.COMPACT) != 0;
+ }
+
+ private char[] returnClassName(char[] classInfoName, char separator, int mode) {
+ if (classInfoName.length == 0) {
+ return CharOperation.NO_CHAR;
+ } else if (isCompact(mode)) {
+ int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName);
+ if (lastIndexOfSlash != -1) {
+ return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length);
+ }
+ }
+ return classInfoName;
+ }
+
+ private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) {
+ buffer.append(lineSeparator);
+ dumpTab(tabNumber, buffer);
+ }
+}

Back to the top