123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * PARC initial implementation
- * ******************************************************************/
-
- package org.aspectj.weaver.bcel;
-
- import java.util.List;
-
- import org.aspectj.apache.bcel.classfile.Attribute;
- import org.aspectj.apache.bcel.classfile.ConstantPool;
- import org.aspectj.apache.bcel.classfile.Field;
- import org.aspectj.apache.bcel.classfile.Synthetic;
- import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
- import org.aspectj.apache.bcel.generic.FieldGen;
- import org.aspectj.util.GenericSignature;
- import org.aspectj.util.GenericSignatureParser;
- import org.aspectj.weaver.AjAttribute;
- import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
- import org.aspectj.weaver.AnnotationAJ;
- import org.aspectj.weaver.ISourceContext;
- import org.aspectj.weaver.ResolvedMemberImpl;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.UnresolvedType;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
-
- /**
- * An AspectJ Field object that is backed by a Bcel Field object.
- *
- * @author PARC
- * @author Andy Clement
- */
- final class BcelField extends ResolvedMemberImpl {
-
- public static int AccSynthetic = 0x1000;
-
- private Field field;
- private boolean isAjSynthetic;
- private boolean isSynthetic = false;
- private AnnotationAJ[] annotations;
- private final World world;
- private final BcelObjectType bcelObjectType;
- private UnresolvedType genericFieldType = null;
- private boolean unpackedGenericSignature = false;
- private boolean annotationsOnFieldObjectAreOutOfDate = false;
-
- BcelField(BcelObjectType declaringType, Field field) {
- super(FIELD, declaringType.getResolvedTypeX(), field.getModifiers(), field.getName(), field.getSignature());
- this.field = field;
- this.world = declaringType.getResolvedTypeX().getWorld();
- this.bcelObjectType = declaringType;
- unpackAttributes(world);
- checkedExceptions = UnresolvedType.NONE;
- }
-
- /**
- * Constructs an instance that wrappers a Field object, but where we do not (yet) have a BcelObjectType - usually because the
- * containing type (and this field) are being constructed at runtime (so there is no .class file to retrieve).
- */
- BcelField(String declaringTypeName, Field field, World world) {
- super(FIELD, UnresolvedType.forName(declaringTypeName), field.getModifiers(), field.getName(), field.getSignature());
- this.field = field;
- this.world = world;
- this.bcelObjectType = null;
- unpackAttributes(world);
- checkedExceptions = UnresolvedType.NONE;
- }
-
- private void unpackAttributes(World world) {
- Attribute[] attrs = field.getAttributes();
- if (attrs != null && attrs.length > 0) {
- ISourceContext sourceContext = getSourceContext(world);
- List<AjAttribute> as = Utility.readAjAttributes(getDeclaringType().getClassName(), attrs, sourceContext, world,
- (bcelObjectType != null ? bcelObjectType.getWeaverVersionAttribute() : WeaverVersionInfo.CURRENT),
- new BcelConstantPoolReader(field.getConstantPool()));
- as.addAll(AtAjAttributes.readAj5FieldAttributes(field, this, world.resolve(getDeclaringType()), sourceContext,
- world.getMessageHandler()));
-
- // FIXME this code has no effect!!!??? it is set to false immediately after the block
- // for (AjAttribute a : as) {
- // if (a instanceof AjAttribute.AjSynthetic) {
- // isAjSynthetic = true;
- // } else {
- // throw new BCException("weird field attribute " + a);
- // }
- // }
- }
- isAjSynthetic = false;
-
- for (int i = attrs.length - 1; i >= 0; i--) {
- if (attrs[i] instanceof Synthetic) {
- isSynthetic = true;
- }
- }
- // in 1.5, synthetic is a modifier, not an attribute
- if ((field.getModifiers() & AccSynthetic) != 0) {
- isSynthetic = true;
- }
-
- }
-
- @Override
- public boolean isAjSynthetic() {
- return isAjSynthetic;
- }
-
- @Override
- public boolean isSynthetic() {
- return isSynthetic;
- }
-
- @Override
- public boolean hasAnnotation(UnresolvedType ofType) {
- ensureAnnotationTypesRetrieved();
- for (ResolvedType aType : annotationTypes) {
- if (aType.equals(ofType)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public ResolvedType[] getAnnotationTypes() {
- ensureAnnotationTypesRetrieved();
- return annotationTypes;
- }
-
- @Override
- public AnnotationAJ[] getAnnotations() {
- ensureAnnotationTypesRetrieved();
- return annotations;
- }
-
- @Override
- public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
- ensureAnnotationTypesRetrieved();
- for (AnnotationAJ annotation : annotations) {
- if (annotation.getTypeName().equals(ofType.getName())) {
- return annotation;
- }
- }
- return null;
- }
-
- private void ensureAnnotationTypesRetrieved() {
- if (annotationTypes == null) {
- AnnotationGen annos[] = field.getAnnotations();
- if (annos.length == 0) {
- annotationTypes = ResolvedType.EMPTY_ARRAY;
- annotations = AnnotationAJ.EMPTY_ARRAY;
- } else {
- int annosCount = annos.length;
- annotationTypes = new ResolvedType[annosCount];
- annotations = new AnnotationAJ[annosCount];
- for (int i = 0; i < annosCount; i++) {
- AnnotationGen anno = annos[i];
- annotations[i] = new BcelAnnotation(anno, world);
- annotationTypes[i] = annotations[i].getType();
- }
- }
- }
- }
-
- @Override
- public void addAnnotation(AnnotationAJ annotation) {
- ensureAnnotationTypesRetrieved();
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len + 1];
- System.arraycopy(annotations, 0, ret, 0, len);
- ret[len] = annotation;
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
- System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
- newAnnotationTypes[len] = annotation.getType();
- annotationTypes = newAnnotationTypes;
-
- annotationsOnFieldObjectAreOutOfDate = true;
- }
-
- public void removeAnnotation(AnnotationAJ annotation) {
- ensureAnnotationTypesRetrieved();
-
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len - 1];
- int p = 0;
- for (AnnotationAJ anno : annotations) {
- if (!anno.getType().equals(annotation.getType())) {
- ret[p++] = anno;
- }
- }
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
- p = 0;
- for (ResolvedType anno : annotationTypes) {
- if (!anno.equals(annotation.getType())) {
- newAnnotationTypes[p++] = anno;
- }
- }
- annotationTypes = newAnnotationTypes;
-
- annotationsOnFieldObjectAreOutOfDate = true;
- }
-
- /**
- * Unpack the generic signature attribute if there is one and we haven't already done so, then find the true field type of this
- * field (eg. List<String>).
- */
- @Override
- public UnresolvedType getGenericReturnType() {
- unpackGenericSignature();
- return genericFieldType;
- }
-
- public Field getFieldAsIs() {
- return field;
- }
-
- public Field getField(ConstantPool cpool) {
- if (!annotationsOnFieldObjectAreOutOfDate) {
- return field;
- }
- FieldGen newFieldGen = new FieldGen(field, cpool);
- newFieldGen.removeAnnotations();
- // List<AnnotationGen> alreadyHas = fg.getAnnotations();
- // if (annotations != null) {
- // fg.removeAnnotations();
- for (AnnotationAJ annotation : annotations) {
- newFieldGen.addAnnotation(new AnnotationGen(((BcelAnnotation) annotation).getBcelAnnotation(), cpool, true));
- }
- // for (int i = 0; i < annotations.length; i++) {
- // AnnotationAJ array_element = annotations[i];
- // boolean alreadyHasIt = false;
- // for (AnnotationGen gen : alreadyHas) {
- // if (gen.getTypeName().equals(array_element.getTypeName())) {
- // alreadyHasIt = true;
- // break;
- // }
- // }
- // if (!alreadyHasIt) {
- // fg.addAnnotation(new AnnotationGen(((BcelAnnotation) array_element).getBcelAnnotation(), cpg, true));
- // // }
- // // }
- // }
- field = newFieldGen.getField();
- annotationsOnFieldObjectAreOutOfDate = false; // we are now correct again
- return field;
- }
-
- private void unpackGenericSignature() {
- if (unpackedGenericSignature) {
- return;
- }
- if (!world.isInJava5Mode()) {
- this.genericFieldType = getReturnType();
- return;
- }
- unpackedGenericSignature = true;
- String gSig = field.getGenericSignature();
- if (gSig != null) {
- // get from generic
- GenericSignature.FieldTypeSignature fts = new GenericSignatureParser().parseAsFieldSignature(gSig);
- GenericSignature.ClassSignature genericTypeSig = bcelObjectType.getGenericClassTypeSignature();
-
- GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
- GenericSignature.FormalTypeParameter[] typeVars = ((genericTypeSig == null) ? GenericSignature.FormalTypeParameter.NONE
- : genericTypeSig.formalTypeParameters);
- GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
- + typeVars.length];
- // put method formal in front of type formals for overriding in
- // lookup
- System.arraycopy(typeVars, 0, formals, 0, typeVars.length);
- System.arraycopy(parentFormals, 0, formals, typeVars.length, parentFormals.length);
-
- try {
- genericFieldType = BcelGenericSignatureToTypeXConverter.fieldTypeSignature2TypeX(fts, formals, world);
- } catch (GenericSignatureFormatException e) {
- // development bug, fail fast with good info
- throw new IllegalStateException("While determing the generic field type of " + this.toString()
- + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
- }
- } else {
- genericFieldType = getReturnType();
- }
- }
-
- @Override
- public void evictWeavingState() {
- if (field != null) {
- unpackGenericSignature();
- unpackAttributes(world);
- ensureAnnotationTypesRetrieved();
- // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
- field = null;
- }
- }
- }
|