/******************************************************************************* * 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'); } } }