| /******************************************************************************* |
| * Copyright (c) 2016 Google, Inc 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: |
| * Stefan Xenos (Google) - Initial implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.nd.java.model; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.zip.ZipFile; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.classfmt.BinaryTypeFormatter; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; |
| import org.eclipse.jdt.internal.compiler.classfmt.ElementValuePairInfo; |
| import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; |
| import org.eclipse.jdt.internal.compiler.env.ClassSignature; |
| import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryField; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryType; |
| import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; |
| import org.eclipse.jdt.internal.compiler.env.IDependent; |
| import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker; |
| import org.eclipse.jdt.internal.compiler.impl.Constant; |
| import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus; |
| import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; |
| import org.eclipse.jdt.internal.core.JarPackageFragmentRoot; |
| import org.eclipse.jdt.internal.core.JavaModelManager; |
| import org.eclipse.jdt.internal.core.nd.IReader; |
| import org.eclipse.jdt.internal.core.nd.db.IString; |
| import org.eclipse.jdt.internal.core.nd.java.JavaNames; |
| import org.eclipse.jdt.internal.core.nd.java.NdAnnotation; |
| import org.eclipse.jdt.internal.core.nd.java.NdAnnotationValuePair; |
| import org.eclipse.jdt.internal.core.nd.java.NdConstant; |
| import org.eclipse.jdt.internal.core.nd.java.NdConstantAnnotation; |
| import org.eclipse.jdt.internal.core.nd.java.NdConstantArray; |
| import org.eclipse.jdt.internal.core.nd.java.NdConstantClass; |
| import org.eclipse.jdt.internal.core.nd.java.NdConstantEnum; |
| import org.eclipse.jdt.internal.core.nd.java.NdMethod; |
| import org.eclipse.jdt.internal.core.nd.java.NdMethodException; |
| import org.eclipse.jdt.internal.core.nd.java.NdMethodId; |
| import org.eclipse.jdt.internal.core.nd.java.NdMethodParameter; |
| import org.eclipse.jdt.internal.core.nd.java.NdResourceFile; |
| import org.eclipse.jdt.internal.core.nd.java.NdType; |
| import org.eclipse.jdt.internal.core.nd.java.NdTypeAnnotation; |
| import org.eclipse.jdt.internal.core.nd.java.NdTypeId; |
| import org.eclipse.jdt.internal.core.nd.java.NdTypeInterface; |
| import org.eclipse.jdt.internal.core.nd.java.NdTypeParameter; |
| import org.eclipse.jdt.internal.core.nd.java.NdTypeSignature; |
| import org.eclipse.jdt.internal.core.nd.java.NdVariable; |
| import org.eclipse.jdt.internal.core.nd.java.TypeRef; |
| import org.eclipse.jdt.internal.core.nd.util.CharArrayUtils; |
| import org.eclipse.jdt.internal.core.util.CharArrayBuffer; |
| |
| /** |
| * Implementation of {@link IBinaryType} that reads all its content from the index |
| */ |
| public class IndexBinaryType implements IBinaryType { |
| private final TypeRef typeRef; |
| |
| private boolean simpleAttributesInitialized; |
| private char[] enclosingMethod; |
| private char[] enclosingType; |
| private char[] fileName; |
| private char[] superclassName; |
| private int modifiers; |
| private boolean isAnonymous; |
| private boolean isLocal; |
| private boolean isMember; |
| |
| private long tagBits; |
| |
| private char[] binaryTypeName; |
| |
| private static final IBinaryAnnotation[] NO_ANNOTATIONS = new IBinaryAnnotation[0]; |
| private static final int[] NO_PATH = new int[0]; |
| |
| public IndexBinaryType(TypeRef type, char[] indexPath) { |
| this.typeRef = type; |
| this.fileName = indexPath; |
| } |
| |
| public boolean exists() { |
| return this.typeRef.get() != null; |
| } |
| |
| @Override |
| public int getModifiers() { |
| initSimpleAttributes(); |
| |
| return this.modifiers; |
| } |
| |
| @Override |
| public boolean isBinaryType() { |
| return true; |
| } |
| |
| @Override |
| public char[] getFileName() { |
| return this.fileName; |
| } |
| |
| @Override |
| public IBinaryAnnotation[] getAnnotations() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| return toAnnotationArray(this.typeRef.get().getAnnotations()); |
| } else { |
| return NO_ANNOTATIONS; |
| } |
| } |
| } |
| |
| private static IBinaryAnnotation[] toAnnotationArray(List<? extends NdAnnotation> annotations) { |
| if (annotations.isEmpty()) { |
| return NO_ANNOTATIONS; |
| } |
| IBinaryAnnotation[] result = new IBinaryAnnotation[annotations.size()]; |
| |
| for (int idx = 0; idx < result.length; idx++) { |
| result[idx] = createBinaryAnnotation(annotations.get(idx)); |
| } |
| return result; |
| } |
| |
| @Override |
| public IBinaryTypeAnnotation[] getTypeAnnotations() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| return createBinaryTypeAnnotations(type.getTypeAnnotations()); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public char[] getEnclosingMethod() { |
| initSimpleAttributes(); |
| |
| return this.enclosingMethod; |
| } |
| |
| @Override |
| public char[] getEnclosingTypeName() { |
| initSimpleAttributes(); |
| |
| return this.enclosingType; |
| } |
| |
| @Override |
| public IBinaryField[] getFields() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| List<NdVariable> variables = type.getVariables(); |
| |
| if (variables.isEmpty()) { |
| return null; |
| } |
| |
| IBinaryField[] result = new IBinaryField[variables.size()]; |
| for (int fieldIdx = 0; fieldIdx < variables.size(); fieldIdx++) { |
| result[fieldIdx] = createBinaryField(variables.get(fieldIdx)); |
| } |
| return result; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public char[] getGenericSignature() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| if (!type.getFlag(NdType.FLG_GENERIC_SIGNATURE_PRESENT)) { |
| return null; |
| } |
| CharArrayBuffer buffer = new CharArrayBuffer(); |
| NdTypeParameter.getSignature(buffer, type.getTypeParameters()); |
| NdTypeSignature superclass = type.getSuperclass(); |
| if (superclass != null) { |
| superclass.getSignature(buffer); |
| } |
| for (NdTypeInterface nextInterface : type.getInterfaces()) { |
| nextInterface.getInterface().getSignature(buffer); |
| } |
| return buffer.getContents(); |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public char[][] getInterfaceNames() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| List<NdTypeInterface> interfaces = type.getInterfaces(); |
| |
| if (interfaces.isEmpty()) { |
| return null; |
| } |
| |
| char[][] result = new char[interfaces.size()][]; |
| for (int idx = 0; idx < interfaces.size(); idx++) { |
| NdTypeSignature nextInterface = interfaces.get(idx).getInterface(); |
| |
| result[idx] = nextInterface.getRawType().getBinaryName(); |
| } |
| return result; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public IBinaryNestedType[] getMemberTypes() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| List<NdType> declaredTypes = type.getTypeId().getDeclaredTypes(); |
| if (declaredTypes.isEmpty()) { |
| return null; |
| } |
| |
| NdResourceFile resFile = type.getResourceFile(); |
| IString javaRoot = resFile.getPackageFragmentRoot(); |
| |
| // Filter out all the declared types which are at different java roots (only keep the ones belonging |
| // to the same .jar file or to another .class file in the same folder). |
| List<IBinaryNestedType> result = new ArrayList<>(); |
| for (NdType next : declaredTypes) { |
| NdResourceFile nextResFile = next.getResourceFile(); |
| |
| if (nextResFile.getPackageFragmentRoot().compare(javaRoot, true) == 0) { |
| result.add(createBinaryNestedType(next)); |
| } |
| } |
| return result.isEmpty() ? null : result.toArray(new IBinaryNestedType[result.size()]); |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| private IBinaryNestedType createBinaryNestedType(NdType next) { |
| return new IndexBinaryNestedType(next.getTypeId().getBinaryName(), next.getDeclaringType().getBinaryName(), |
| next.getModifiers()); |
| } |
| |
| @Override |
| public IBinaryMethod[] getMethods() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| List<NdMethod> methods = type.getMethods(); |
| |
| if (methods.isEmpty()) { |
| return null; |
| } |
| |
| IBinaryMethod[] result = new IBinaryMethod[methods.size()]; |
| for (int idx = 0; idx < result.length; idx++) { |
| result[idx] = createBinaryMethod(methods.get(idx)); |
| } |
| |
| return result; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public char[][][] getMissingTypeNames() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| IString string = type.getMissingTypeNames(); |
| if (string.length() == 0) { |
| return null; |
| } |
| char[] missingTypeNames = string.getChars(); |
| char[][] paths = CharOperation.splitOn(',', missingTypeNames); |
| char[][][] result = new char[paths.length][][]; |
| for (int idx = 0; idx < paths.length; idx++) { |
| result[idx] = CharOperation.splitOn('/', paths[idx]); |
| } |
| return result; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public char[] getName() { |
| initSimpleAttributes(); |
| |
| return this.binaryTypeName; |
| } |
| |
| @Override |
| public char[] getSourceName() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| return type.getSourceName(); |
| } else { |
| return new char[0]; |
| } |
| } |
| } |
| |
| @Override |
| public char[] getSuperclassName() { |
| initSimpleAttributes(); |
| |
| return this.superclassName; |
| } |
| |
| @Override |
| public long getTagBits() { |
| initSimpleAttributes(); |
| |
| return this.tagBits; |
| } |
| |
| @Override |
| public boolean isAnonymous() { |
| initSimpleAttributes(); |
| |
| return this.isAnonymous; |
| } |
| |
| @Override |
| public boolean isLocal() { |
| initSimpleAttributes(); |
| |
| return this.isLocal; |
| } |
| |
| @Override |
| public boolean isMember() { |
| initSimpleAttributes(); |
| |
| return this.isMember; |
| } |
| |
| @Override |
| public char[] sourceFileName() { |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| char[] result = type.getSourceFileName().getChars(); |
| if (result.length == 0) { |
| return null; |
| } |
| return result; |
| } else { |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member, |
| LookupEnvironment environment) { |
| return walker; |
| } |
| |
| private IBinaryMethod createBinaryMethod(NdMethod ndMethod) { |
| NdMethodId methodId = ndMethod.getMethodId(); |
| |
| return IndexBinaryMethod.create().setAnnotations(toAnnotationArray(ndMethod.getAnnotations())) |
| .setModifiers(ndMethod.getModifiers()).setIsConstructor(methodId.isConstructor()) |
| .setArgumentNames(getArgumentNames(ndMethod)).setDefaultValue(unpackValue(ndMethod.getDefaultValue())) |
| .setExceptionTypeNames(getExceptionTypeNames(ndMethod)) |
| .setGenericSignature(getGenericSignatureFor(ndMethod)) |
| .setMethodDescriptor(methodId.getMethodDescriptor()) |
| .setParameterAnnotations(getParameterAnnotations(ndMethod)) |
| .setSelector(ndMethod.getMethodId().getSelector()).setTagBits(ndMethod.getTagBits()) |
| .setIsClInit(methodId.isClInit()).setTypeAnnotations(createBinaryTypeAnnotations(ndMethod.getTypeAnnotations())); |
| } |
| |
| private static IBinaryTypeAnnotation[] createBinaryTypeAnnotations(List<? extends NdTypeAnnotation> typeAnnotations) { |
| if (typeAnnotations.isEmpty()) { |
| return null; |
| } |
| IBinaryTypeAnnotation[] result = new IBinaryTypeAnnotation[typeAnnotations.size()]; |
| int idx = 0; |
| for (NdTypeAnnotation next : typeAnnotations) { |
| IBinaryAnnotation annotation = createBinaryAnnotation(next); |
| int[] typePath = getTypePath(next.getTypePath()); |
| int info = 0; |
| int info2 = 0; |
| switch (next.getTargetType()) { |
| case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER: |
| case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER: |
| info = next.getTargetInfoArg0(); |
| break; |
| case AnnotationTargetTypeConstants.CLASS_EXTENDS: |
| info = next.getTarget(); |
| break; |
| case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND: |
| case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND: |
| info = next.getTargetInfoArg0(); |
| info2 = next.getTargetInfoArg1(); |
| break; |
| case AnnotationTargetTypeConstants.FIELD: |
| case AnnotationTargetTypeConstants.METHOD_RETURN: |
| case AnnotationTargetTypeConstants.METHOD_RECEIVER: |
| break; |
| case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER : |
| info = next.getTarget(); |
| break; |
| case AnnotationTargetTypeConstants.THROWS : |
| info = next.getTarget(); |
| break; |
| |
| default: |
| throw new IllegalStateException("Target type not handled " + next.getTargetType()); //$NON-NLS-1$ |
| } |
| result[idx++] = new IndexBinaryTypeAnnotation(next.getTargetType(), info, info2, typePath, annotation); |
| } |
| return result; |
| } |
| |
| private static int[] getTypePath(byte[] typePath) { |
| if (typePath.length == 0) { |
| return NO_PATH; |
| } |
| int[] result = new int[typePath.length]; |
| for (int idx = 0; idx < typePath.length; idx++) { |
| result[idx] = typePath[idx]; |
| } |
| return result; |
| } |
| |
| private static char[] getGenericSignatureFor(NdMethod method) { |
| if (!method.hasAllFlags(NdMethod.FLG_GENERIC_SIGNATURE_PRESENT)) { |
| return null; |
| } |
| CharArrayBuffer result = new CharArrayBuffer(); |
| method.getGenericSignature(result, method.hasAllFlags(NdMethod.FLG_THROWS_SIGNATURE_PRESENT)); |
| return result.getContents(); |
| } |
| |
| private char[][] getArgumentNames(NdMethod ndMethod) { |
| // Unlike what its JavaDoc says, IBinaryType returns an empty array if no argument names are available, so |
| // we replicate this weird undocumented corner case here. |
| char[][] result = ndMethod.getParameterNames(); |
| int lastNonEmpty = -1; |
| for (int idx = 0; idx < result.length; idx++) { |
| if (result[idx] != null && result[idx].length != 0) { |
| lastNonEmpty = idx; |
| } |
| } |
| |
| if (lastNonEmpty != result.length - 1) { |
| char[][] newResult = new char[lastNonEmpty + 1][]; |
| System.arraycopy(result, 0, newResult, 0, lastNonEmpty + 1); |
| return newResult; |
| } |
| return result; |
| } |
| |
| private IBinaryAnnotation[][] getParameterAnnotations(NdMethod ndMethod) { |
| List<NdMethodParameter> parameters = ndMethod.getMethodParameters(); |
| if (parameters.isEmpty()) { |
| return null; |
| } |
| |
| IBinaryAnnotation[][] result = new IBinaryAnnotation[parameters.size()][]; |
| for (int idx = 0; idx < parameters.size(); idx++) { |
| NdMethodParameter next = parameters.get(idx); |
| |
| result[idx] = toAnnotationArray(next.getAnnotations()); |
| } |
| |
| // int newLength = result.length; |
| // while (newLength > 0 && result[newLength - 1] == null) { |
| // --newLength; |
| // } |
| // |
| // if (newLength < result.length) { |
| // if (newLength == 0) { |
| // return null; |
| // } |
| // IBinaryAnnotation[][] newResult = new IBinaryAnnotation[newLength][]; |
| // System.arraycopy(result, 0, newResult, 0, newLength); |
| // result = newResult; |
| // } |
| |
| return result; |
| } |
| |
| private char[][] getExceptionTypeNames(NdMethod ndMethod) { |
| List<NdMethodException> exceptions = ndMethod.getExceptions(); |
| |
| // Although the JavaDoc for IBinaryMethod says that the exception list will be null if empty, |
| // the implementation in MethodInfo returns an empty array rather than null. We copy the |
| // same behavior here in case something is relying on it. Uncomment the following if the "null" |
| // version is deemed correct. |
| |
| // if (exceptions.isEmpty()) { |
| // return null; |
| // } |
| |
| char[][] result = new char[exceptions.size()][]; |
| for (int idx = 0; idx < exceptions.size(); idx++) { |
| NdMethodException next = exceptions.get(idx); |
| |
| result[idx] = next.getExceptionType().getRawType().getBinaryName(); |
| } |
| return result; |
| } |
| |
| public static IBinaryField createBinaryField(NdVariable ndVariable) { |
| char[] name = ndVariable.getName().getChars(); |
| Constant constant = null; |
| NdConstant ndConstant = ndVariable.getConstant(); |
| if (ndConstant != null) { |
| constant = ndConstant.getConstant(); |
| } |
| if (constant == null) { |
| constant = Constant.NotAConstant; |
| } |
| |
| NdTypeSignature type = ndVariable.getType(); |
| |
| IBinaryTypeAnnotation[] typeAnnotationArray = createBinaryTypeAnnotations(ndVariable.getTypeAnnotations()); |
| |
| IBinaryAnnotation[] annotations = toAnnotationArray(ndVariable.getAnnotations()); |
| |
| CharArrayBuffer signature = new CharArrayBuffer(); |
| if (ndVariable.hasVariableFlag(NdVariable.FLG_GENERIC_SIGNATURE_PRESENT)) { |
| type.getSignature(signature); |
| } |
| |
| long tagBits = ndVariable.getTagBits(); |
| return new IndexBinaryField(annotations, constant, signature.getContents(), ndVariable.getModifiers(), name, |
| tagBits, typeAnnotationArray, type.getRawType().getFieldDescriptor().getChars()); |
| } |
| |
| public static IBinaryAnnotation createBinaryAnnotation(NdAnnotation ndAnnotation) { |
| List<NdAnnotationValuePair> elementValuePairs = ndAnnotation.getElementValuePairs(); |
| |
| final IBinaryElementValuePair[] resultingPair = new IBinaryElementValuePair[elementValuePairs.size()]; |
| |
| for (int idx = 0; idx < elementValuePairs.size(); idx++) { |
| NdAnnotationValuePair next = elementValuePairs.get(idx); |
| |
| resultingPair[idx] = new ElementValuePairInfo(next.getName().getChars(), unpackValue(next.getValue())); |
| } |
| |
| final char[] binaryName = JavaNames.fieldDescriptorToBinaryName( |
| ndAnnotation.getType().getRawType().getFieldDescriptor().getChars()); |
| |
| return new IBinaryAnnotation() { |
| @Override |
| public char[] getTypeName() { |
| return binaryName; |
| } |
| |
| @Override |
| public IBinaryElementValuePair[] getElementValuePairs() { |
| return resultingPair; |
| } |
| |
| @Override |
| public String toString() { |
| return BinaryTypeFormatter.annotationToString(this); |
| } |
| }; |
| } |
| |
| public void initSimpleAttributes() { |
| if (!this.simpleAttributesInitialized) { |
| this.simpleAttributesInitialized = true; |
| |
| try (IReader rl = this.typeRef.lock()) { |
| NdType type = this.typeRef.get(); |
| if (type != null) { |
| NdMethodId methodId = type.getDeclaringMethod(); |
| |
| if (methodId != null) { |
| char[] methodName = methodId.getMethodName().getChars(); |
| int startIdx = CharArrayUtils.lastIndexOf('#', methodName); |
| this.enclosingMethod = CharArrayUtils.subarray(methodName, startIdx + 1); |
| this.enclosingType = CharArrayUtils.subarray(methodName, 1, startIdx); |
| } else { |
| NdTypeId typeId = type.getDeclaringType(); |
| |
| if (typeId != null) { |
| this.enclosingType = typeId.getBinaryName(); |
| } |
| } |
| |
| this.modifiers = type.getModifiers(); |
| this.isAnonymous = type.isAnonymous(); |
| this.isLocal = type.isLocal(); |
| this.isMember = type.isMember(); |
| this.tagBits = type.getTagBits(); |
| |
| NdTypeSignature superclass = type.getSuperclass(); |
| if (superclass != null) { |
| this.superclassName = superclass.getRawType().getBinaryName(); |
| } else { |
| this.superclassName = null; |
| } |
| |
| this.binaryTypeName = JavaNames.fieldDescriptorToBinaryName(type.getFieldDescriptor().getChars()); |
| } else { |
| this.binaryTypeName = JavaNames.fieldDescriptorToBinaryName(this.typeRef.getFieldDescriptor()); |
| } |
| } |
| } |
| } |
| |
| private static Object unpackValue(NdConstant value) { |
| if (value == null) { |
| return null; |
| } |
| if (value instanceof NdConstantAnnotation) { |
| NdConstantAnnotation annotation = (NdConstantAnnotation) value; |
| |
| return createBinaryAnnotation(annotation.getValue()); |
| } |
| if (value instanceof NdConstantArray) { |
| NdConstantArray array = (NdConstantArray) value; |
| |
| List<NdConstant> arrayContents = array.getValue(); |
| |
| Object[] result = new Object[arrayContents.size()]; |
| for (int idx = 0; idx < arrayContents.size(); idx++) { |
| result[idx] = unpackValue(arrayContents.get(idx)); |
| } |
| return result; |
| } |
| if (value instanceof NdConstantEnum) { |
| NdConstantEnum ndConstantEnum = (NdConstantEnum) value; |
| |
| NdTypeSignature signature = ndConstantEnum.getType(); |
| |
| return new EnumConstantSignature(signature.getRawType().getBinaryName(), ndConstantEnum.getValue()); |
| } |
| if (value instanceof NdConstantClass) { |
| NdConstantClass constant = (NdConstantClass) value; |
| |
| return new ClassSignature(constant.getValue().getRawType().getBinaryName()); |
| } |
| |
| return value.getConstant(); |
| } |
| |
| @Override |
| public ExternalAnnotationStatus getExternalAnnotationStatus() { |
| return ExternalAnnotationStatus.NOT_EEA_CONFIGURED; |
| } |
| //{ObjectTeams: retrieve class file in workspace: |
| @Override |
| public IBinaryType withClassBytes() throws ClassFormatException, IOException, CoreException { |
| File file = new File(String.valueOf(this.fileName)); |
| if (file.exists()) |
| return ClassFileReader.read(file); |
| int pos = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, this.fileName); |
| if (pos != -1) { |
| String jarIdentifier = String.valueOf(CharOperation.subarray(this.fileName, 0, pos)); |
| String fileInJarName = String.valueOf(CharOperation.subarray(this.fileName, pos+1, -1)); |
| IJavaElement jJar = JavaCore.create(jarIdentifier); |
| if (jJar.exists()) { |
| ZipFile jarZip = ((JarPackageFragmentRoot) jJar).getJar(); |
| try { |
| return ClassFileReader.read(jarZip, fileInJarName); |
| } finally { |
| JavaModelManager.getJavaModelManager().closeZipFile(jarZip); |
| } |
| } |
| } |
| return this; // could not improve |
| } |
| // SH} |
| } |