All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.weaver.bcel.BcelField Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * 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 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).
	 */
	@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 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;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy