| /******************************************************************************* |
| * Copyright (c) 2005, 2009 BEA Systems, Inc. |
| * 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: |
| * tyeung@bea.com - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.compiler.classfmt; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; |
| |
| public class AnnotationMethodInfo extends MethodInfo { |
| protected Object defaultValue = null; |
| |
| public static MethodInfo createAnnotationMethod(byte classFileBytes[], int offsets[], int offset) { |
| MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); |
| int attributesCount = methodInfo.u2At(6); |
| int readOffset = 8; |
| AnnotationInfo[] annotations = null; |
| Object defaultValue = null; |
| for (int i = 0; i < attributesCount; i++) { |
| // check the name of each attribute |
| int utf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset)] - methodInfo.structOffset; |
| char[] attributeName = methodInfo.utf8At(utf8Offset + 3, methodInfo.u2At(utf8Offset + 1)); |
| if (attributeName.length > 0) { |
| switch(attributeName[0]) { |
| case 'A': |
| if (CharOperation.equals(attributeName, AttributeNamesConstants.AnnotationDefaultName)) { |
| // readOffset + 6 so the offset is at the start of the 'member_value' entry |
| // u2 attribute_name_index + u4 attribute_length = + 6 |
| AnnotationInfo info = |
| new AnnotationInfo(methodInfo.reference, methodInfo.constantPoolOffsets, readOffset + 6 + methodInfo.structOffset); |
| defaultValue = info.decodeDefaultValue(); |
| } |
| break; |
| case 'S' : |
| if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) |
| methodInfo.signatureUtf8Offset = methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset + 6)] - methodInfo.structOffset; |
| break; |
| case 'R' : |
| AnnotationInfo[] methodAnnotations = null; |
| if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) { |
| methodAnnotations = decodeMethodAnnotations(readOffset, true, methodInfo); |
| } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) { |
| methodAnnotations = decodeMethodAnnotations(readOffset, false, methodInfo); |
| } |
| if (methodAnnotations != null) { |
| if (annotations == null) { |
| annotations = methodAnnotations; |
| } else { |
| int length = annotations.length; |
| AnnotationInfo[] newAnnotations = new AnnotationInfo[length + methodAnnotations.length]; |
| System.arraycopy(annotations, 0, newAnnotations, 0, length); |
| System.arraycopy(methodAnnotations, 0, newAnnotations, length, methodAnnotations.length); |
| annotations = newAnnotations; |
| } |
| } |
| break; |
| } |
| } |
| readOffset += (6 + methodInfo.u4At(readOffset + 2)); |
| } |
| methodInfo.attributeBytes = readOffset; |
| |
| if (defaultValue != null) { |
| if (annotations != null) { |
| return new AnnotationMethodInfoWithAnnotations(methodInfo, defaultValue, annotations); |
| } |
| return new AnnotationMethodInfo(methodInfo, defaultValue); |
| } |
| if (annotations != null) |
| return new MethodInfoWithAnnotations(methodInfo, annotations); |
| return methodInfo; |
| } |
| |
| AnnotationMethodInfo(MethodInfo methodInfo, Object defaultValue) { |
| super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset); |
| this.defaultValue = defaultValue; |
| |
| this.accessFlags = methodInfo.accessFlags; |
| this.attributeBytes = methodInfo.attributeBytes; |
| this.descriptor = methodInfo.descriptor; |
| this.exceptionNames = methodInfo.exceptionNames; |
| this.name = methodInfo.name; |
| this.signature = methodInfo.signature; |
| this.signatureUtf8Offset = methodInfo.signatureUtf8Offset; |
| this.tagBits = methodInfo.tagBits; |
| } |
| public Object getDefaultValue() { |
| return this.defaultValue; |
| } |
| protected void toStringContent(StringBuffer buffer) { |
| super.toStringContent(buffer); |
| if (this.defaultValue != null) { |
| buffer.append(" default "); //$NON-NLS-1$ |
| if (this.defaultValue instanceof Object[]) { |
| buffer.append('{'); |
| Object[] elements = (Object[]) this.defaultValue; |
| for (int i = 0, len = elements.length; i < len; i++) { |
| if (i > 0) |
| buffer.append(", "); //$NON-NLS-1$ |
| buffer.append(elements[i]); |
| } |
| buffer.append('}'); |
| } else { |
| buffer.append(this.defaultValue); |
| } |
| buffer.append('\n'); |
| } |
| } |
| } |