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

org.aspectj.weaver.bcel.BcelPerClauseAspectAdder 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) 2005 Contributors.
 * 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:
 * initial implementation              Alexandre Vasseur
 *******************************************************************************/
package org.aspectj.weaver.bcel;

import java.util.List;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.InstructionBranch;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.ReferenceType;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.patterns.PerClause;

/**
 * Adds aspectOf(), hasAspect() etc to the annotation defined aspects
 *
 * @author Alexandre Vasseur
 * @author Andy Clement
 */
public class BcelPerClauseAspectAdder extends BcelTypeMunger {

	private final PerClause.Kind kind;

	private boolean hasGeneratedInner = false;

	public BcelPerClauseAspectAdder(ResolvedType aspect, PerClause.Kind kind) {
		super(null, aspect);
		this.kind = kind;
		if (kind == PerClause.SINGLETON || kind == PerClause.PERTYPEWITHIN || kind == PerClause.PERCFLOW) {
			// no inner needed
			hasGeneratedInner = true;
		}
	}

	public boolean munge(BcelClassWeaver weaver) {
		LazyClassGen gen = weaver.getLazyClassGen();

		doAggressiveInner(gen);

		// Only munge the aspect type
		if (!gen.getType().equals(aspectType)) {
			return false;
		}

		return doMunge(gen, true);
	}

	public boolean forceMunge(LazyClassGen gen, boolean checkAlreadyThere) {
		doAggressiveInner(gen);
		return doMunge(gen, checkAlreadyThere);
	}

	private void doAggressiveInner(LazyClassGen gen) {
		// agressively generate the inner interface if any
		// Note: we do so because of the bug #75442 that leads to have this interface implemented by all classes and not
		// only those matched by the per clause, which fails under LTW since the very first class
		// gets weaved and impl this interface that is still not defined.
		if (!hasGeneratedInner) {
			if (kind == PerClause.PEROBJECT) {// redundant test - see constructor, but safer
				// inner class
				UnresolvedType interfaceTypeX = AjcMemberMaker.perObjectInterfaceType(aspectType);
				LazyClassGen interfaceGen = new LazyClassGen(interfaceTypeX.getName(), "java.lang.Object", null,
						Constants.ACC_INTERFACE + Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT, new String[0], getWorld());
				interfaceGen.addMethodGen(makeMethodGen(interfaceGen, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
				interfaceGen.addMethodGen(makeMethodGen(interfaceGen, AjcMemberMaker.perObjectInterfaceSet(aspectType)));
				// not really an inner class of it but that does not matter, we pass back to the LTW
				gen.addGeneratedInner(interfaceGen);
			}
			hasGeneratedInner = true;
		}
	}

	private boolean doMunge(LazyClassGen gen, boolean checkAlreadyThere) {
		if (checkAlreadyThere && hasPerClauseMembersAlready(gen)) {
			return false;
		}

		generatePerClauseMembers(gen);

		if (kind == PerClause.SINGLETON) {
			generatePerSingletonAspectOfMethod(gen);
			generatePerSingletonHasAspectMethod(gen);
			generatePerSingletonAjcClinitMethod(gen);
		} else if (kind == PerClause.PEROBJECT) {
			generatePerObjectAspectOfMethod(gen);
			generatePerObjectHasAspectMethod(gen);
			generatePerObjectBindMethod(gen);
			// these will be added by the PerObjectInterface munger that affects the type - pr144602
			// generatePerObjectGetSetMethods(gen);
		} else if (kind == PerClause.PERCFLOW) {
			generatePerCflowAspectOfMethod(gen);
			generatePerCflowHasAspectMethod(gen);
			generatePerCflowPushMethod(gen);
			generatePerCflowAjcClinitMethod(gen);
		} else if (kind == PerClause.PERTYPEWITHIN) {
			generatePerTWAspectOfMethod(gen);
			generatePerTWHasAspectMethod(gen);
			generatePerTWGetInstanceMethod(gen);
			generatePerTWCreateAspectInstanceMethod(gen);
			generatePerTWGetWithinTypeNameMethod(gen);
		} else {
			throw new Error("should not happen - not such kind " + kind.getName());
		}
		return true;
	}

	public ResolvedMember getMatchingSyntheticMember(Member member) {
		return null;
	}

	public ResolvedMember getSignature() {
		return null;
	}

	public boolean matches(ResolvedType onType) {
		// cannot always do the right thing because may need to eagerly generate ajcMightHaveAspect interface for LTW (says Alex)
		if (hasGeneratedInner) { // pr237419 - not always going to generate the marker interface
			return aspectType.equals(onType);
		} else {
			return true;
		}
	}

	private boolean hasPerClauseMembersAlready(LazyClassGen classGen) {
		List methodGens = classGen.getMethodGens();
		for (LazyMethodGen method: methodGens) {
			if ("aspectOf".equals(method.getName())) {
				if ("()".equals(method.getParameterSignature()) && (kind == PerClause.SINGLETON || kind == PerClause.PERCFLOW)) {
					return true;
				} else if ("(Ljava/lang/Object;)".equals(method.getParameterSignature()) && kind == PerClause.PEROBJECT) {
					return true;
				} else if ("(Ljava/lang/Class;)".equals(method.getParameterSignature()) && kind == PerClause.PERTYPEWITHIN) {
					return true;
				}
			}
		}
		return false;
	}

	private void generatePerClauseMembers(LazyClassGen classGen) {
		// FIXME Alex handle when field already there - or handle it with / similar to isAnnotationDefinedAspect()
		// for that use aspectType and iterate on the fields.

		// FIXME Alex percflowX is not using this one but AJ code style does generate it so..
		ResolvedMember failureFieldInfo = AjcMemberMaker.initFailureCauseField(aspectType);
		if (kind == PerClause.SINGLETON) {
			classGen.addField(makeFieldGen(classGen, failureFieldInfo), null);
		}

		if (kind == PerClause.SINGLETON) {
			ResolvedMember perSingletonFieldInfo = AjcMemberMaker.perSingletonField(aspectType);
			classGen.addField(makeFieldGen(classGen, perSingletonFieldInfo), null);
			// pr144602 - don't need to do this, PerObjectInterface munger will do it
			// } else if (kind == PerClause.PEROBJECT) {
			// ResolvedMember perObjectFieldInfo = AjcMemberMaker.perObjectField(aspectType, aspectType);
			// classGen.addField(makeFieldGen(classGen, perObjectFieldInfo).(), null);
			// // if lazy generation of the inner interface MayHaveAspect works on LTW (see previous note)
			// // it should be done here.
		} else if (kind == PerClause.PERCFLOW) {
			ResolvedMember perCflowFieldInfo = AjcMemberMaker.perCflowField(aspectType);
			classGen.addField(makeFieldGen(classGen, perCflowFieldInfo), null);
		} else if (kind == PerClause.PERTYPEWITHIN) {
			ResolvedMember perTypeWithinForField = AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType);
			classGen.addField(makeFieldGen(classGen, perTypeWithinForField), null);
		}
	}

	private void generatePerSingletonAspectOfMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perSingletonAspectOfMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
		InstructionBranch ifNotNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
		il.append(ifNotNull);
		il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
		il.append(InstructionConstants.DUP);
		il.append(InstructionFactory.PUSH(classGen.getConstantPool(), aspectType.getName()));
		il.append(Utility.createGet(factory, AjcMemberMaker.initFailureCauseField(aspectType)));
		il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "", Type.VOID, new Type[] {
				Type.STRING, new ObjectType("java.lang.Throwable") }, Constants.INVOKESPECIAL));
		il.append(InstructionConstants.ATHROW);
		InstructionHandle ifElse = il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
		il.append(InstructionFactory.createReturn(Type.OBJECT));
		ifNotNull.setTarget(ifElse);
	}

	private void generatePerSingletonHasAspectMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perSingletonHasAspectMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(Utility.createGet(factory, AjcMemberMaker.perSingletonField(aspectType)));
		InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
		il.append(ifNull);
		il.append(InstructionFactory.PUSH(classGen.getConstantPool(), true));
		il.append(InstructionFactory.createReturn(Type.INT));
		InstructionHandle ifElse = il.append(InstructionFactory.PUSH(classGen.getConstantPool(), false));
		il.append(InstructionFactory.createReturn(Type.INT));
		ifNull.setTarget(ifElse);
	}

	private void generatePerSingletonAjcClinitMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.ajcPostClinitMethod(aspectType));
		flagAsSynthetic(method, true);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(factory.createNew(aspectType.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(aspectType.getName(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
		il.append(Utility.createSet(factory, AjcMemberMaker.perSingletonField(aspectType)));
		il.append(InstructionFactory.createReturn(Type.VOID));

		// patch  to delegate to ajc$postClinit at the end
		LazyMethodGen clinit = classGen.getStaticInitializer();
		il = new InstructionList();
		InstructionHandle tryStart = il.append(factory.createInvoke(aspectType.getName(), NameMangler.AJC_POST_CLINIT_NAME,
				Type.VOID, Type.NO_ARGS, Constants.INVOKESTATIC));
		InstructionBranch tryEnd = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
		il.append(tryEnd);
		InstructionHandle handler = il.append(InstructionConstants.ASTORE_0);
		il.append(InstructionConstants.ALOAD_0);
		il.append(Utility.createSet(factory, AjcMemberMaker.initFailureCauseField(aspectType)));
		il.append(InstructionFactory.createReturn(Type.VOID));
		tryEnd.setTarget(il.getEnd());

		// replace the original "return" with a "nop"
		// TODO AV - a bit odd, looks like Bcel alters bytecode and has a IMPDEP1 in its representation
		if (clinit.getBody().getEnd().getInstruction().opcode == Constants.IMPDEP1) {
			clinit.getBody().getEnd().getPrev().setInstruction(InstructionConstants.NOP);
		}
		clinit.getBody().getEnd().setInstruction(InstructionConstants.NOP);
		clinit.getBody().append(il);

		clinit.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Throwable"), false);
	}

	private void generatePerObjectAspectOfMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectAspectOfMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createInstanceOf(interfaceType));
		InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
		il.append(ifEq);
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createCheckCast(interfaceType));
		il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
		il.append(InstructionConstants.DUP);
		InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
		il.append(ifNull);
		il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(aspectType)));
		InstructionHandle ifNullElse = il.append(InstructionConstants.POP);
		ifNull.setTarget(ifNullElse);
		InstructionHandle ifEqElse = il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
		ifEq.setTarget(ifEqElse);
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "", Type.VOID, Type.NO_ARGS,
				Constants.INVOKESPECIAL));
		il.append(InstructionConstants.ATHROW);
	}

	private void generatePerObjectHasAspectMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectHasAspectMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createInstanceOf(interfaceType));
		InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
		il.append(ifEq);
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createCheckCast(interfaceType));
		il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
		InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
		il.append(ifNull);
		il.append(InstructionConstants.ICONST_1);
		il.append(InstructionFactory.createReturn(Type.INT));
		InstructionHandle ifEqElse = il.append(InstructionConstants.ICONST_0);
		ifEq.setTarget(ifEqElse);
		ifNull.setTarget(ifEqElse);
		il.append(InstructionFactory.createReturn(Type.INT));
	}

	private void generatePerObjectBindMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		ReferenceType interfaceType = (ReferenceType) BcelWorld.makeBcelType(AjcMemberMaker.perObjectInterfaceType(aspectType));
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perObjectBind(aspectType));
		flagAsSynthetic(method, true);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createInstanceOf(interfaceType));
		InstructionBranch ifEq = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
		il.append(ifEq);
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createCheckCast(interfaceType));
		il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceGet(aspectType)));
		InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
		il.append(ifNonNull);
		il.append(InstructionConstants.ALOAD_0);
		il.append(factory.createCheckCast(interfaceType));
		il.append(factory.createNew(aspectType.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(aspectType.getName(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
		il.append(Utility.createInvoke(factory, Constants.INVOKEINTERFACE, AjcMemberMaker.perObjectInterfaceSet(aspectType)));
		InstructionHandle end = il.append(InstructionFactory.createReturn(Type.VOID));
		ifEq.setTarget(end);
		ifNonNull.setTarget(end);
	}

	// private void generatePerObjectGetSetMethods(LazyClassGen classGen) {
	// InstructionFactory factory = classGen.getFactory();
	//
	// LazyMethodGen methodGet = makeMethodGen(classGen, AjcMemberMaker.perObjectInterfaceGet(aspectType));
	// flagAsSynthetic(methodGet, true);
	// classGen.addMethodGen(methodGet);
	// InstructionList ilGet = methodGet.getBody();
	// ilGet = new InstructionList();
	// ilGet.append(InstructionConstants.ALOAD_0);
	// ilGet.append(Utility.createGet(factory, AjcMemberMaker.perObjectField(aspectType, aspectType)));
	// ilGet.append(InstructionFactory.createReturn(Type.OBJECT));
	//
	// LazyMethodGen methodSet = makeMethodGen(classGen, AjcMemberMaker.perObjectInterfaceSet(aspectType));
	// flagAsSynthetic(methodSet, true);
	// classGen.addMethodGen(methodSet);
	// InstructionList ilSet = methodSet.getBody();
	// ilSet = new InstructionList();
	// ilSet.append(InstructionConstants.ALOAD_0);
	// ilSet.append(InstructionConstants.ALOAD_1);
	// ilSet.append(Utility.createSet(factory, AjcMemberMaker.perObjectField(aspectType, aspectType)));
	// ilSet.append(InstructionFactory.createReturn(Type.VOID));
	// }

	private void generatePerCflowAspectOfMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowAspectOfMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
		il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackPeekInstance()));
		il.append(factory.createCheckCast((ReferenceType) BcelWorld.makeBcelType(aspectType)));
		il.append(InstructionFactory.createReturn(Type.OBJECT));
	}

	private void generatePerCflowHasAspectMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowHasAspectMethod(aspectType));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
		il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackIsValid()));
		il.append(InstructionFactory.createReturn(Type.INT));
	}

	private void generatePerCflowPushMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perCflowPush(aspectType));
		flagAsSynthetic(method, true);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(Utility.createGet(factory, AjcMemberMaker.perCflowField(aspectType)));
		il.append(factory.createNew(aspectType.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(aspectType.getName(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
		il.append(Utility.createInvoke(factory, Constants.INVOKEVIRTUAL, AjcMemberMaker.cflowStackPushInstance()));
		il.append(InstructionFactory.createReturn(Type.VOID));
	}

	private void generatePerCflowAjcClinitMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();

		LazyMethodGen method = classGen.getAjcPreClinit(); // Creates a clinit if there isn't one

		InstructionList il = new InstructionList();
		il.append(factory.createNew(AjcMemberMaker.CFLOW_STACK_TYPE.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(AjcMemberMaker.CFLOW_STACK_TYPE.getName(), "", Type.VOID, Type.NO_ARGS,
				Constants.INVOKESPECIAL));
		il.append(Utility.createSet(factory, AjcMemberMaker.perCflowField(aspectType)));
		method.getBody().insert(il);
	}

	private void generatePerTWAspectOfMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinAspectOfMethod(aspectType, classGen.getWorld()
				.isInJava5Mode()));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);

		il.append(Utility.createInvoke(factory, Constants.INVOKESTATIC, AjcMemberMaker.perTypeWithinGetInstance(aspectType)));
		il.append(InstructionConstants.ASTORE_1);
		il.append(InstructionConstants.ALOAD_1);
		InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
		il.append(ifNonNull);
		il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
		il.append(InstructionConstants.DUP);
		il.append(InstructionFactory.PUSH(classGen.getConstantPool(), aspectType.getName()));
		il.append(InstructionConstants.ACONST_NULL);
		il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "", Type.VOID, new Type[] {
				Type.STRING, new ObjectType("java.lang.Throwable") }, Constants.INVOKESPECIAL));
		il.append(InstructionConstants.ATHROW);
		InstructionHandle ifElse = il.append(InstructionConstants.ALOAD_1);
		ifNonNull.setTarget(ifElse);
		il.append(InstructionFactory.createReturn(Type.OBJECT));

		InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
		il.append(factory.createNew(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION.getName(), "", Type.VOID, Type.NO_ARGS,
				Constants.INVOKESPECIAL));
		il.append(InstructionConstants.ATHROW);

		method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
	}

	// Create 'public String getWithinTypeName() { return ajc$withinType;}'
	private void generatePerTWGetWithinTypeNameMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(aspectType, classGen
				.getWorld().isInJava5Mode()));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);
		// 0: aload_0
		// 1: getfield #14; //Field ajc$withinType:Ljava/lang/String;
		// 4: areturn
		InstructionList il = method.getBody();
		il.append(InstructionConstants.ALOAD_0);
		il.append(Utility.createGet(factory, AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType)));
		il.append(InstructionConstants.ARETURN);
	}

	private void generatePerTWHasAspectMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinHasAspectMethod(aspectType, classGen.getWorld()
				.isInJava5Mode()));
		flagAsSynthetic(method, false);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);
		il.append(Utility.createInvoke(factory, Constants.INVOKESTATIC, AjcMemberMaker.perTypeWithinGetInstance(aspectType)));
		InstructionBranch ifNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
		il.append(ifNull);
		il.append(InstructionConstants.ICONST_1);
		il.append(InstructionConstants.IRETURN);
		InstructionHandle ifElse = il.append(InstructionConstants.ICONST_0);
		ifNull.setTarget(ifElse);
		il.append(InstructionConstants.IRETURN);

		InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
		il.append(InstructionConstants.ICONST_0);
		il.append(InstructionConstants.IRETURN);

		method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
	}

	private void generatePerTWGetInstanceMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinGetInstance(aspectType));
		flagAsSynthetic(method, true);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		InstructionHandle tryStart = il.append(InstructionConstants.ALOAD_0);
		il.append(InstructionFactory.PUSH(factory.getConstantPool(), NameMangler.perTypeWithinLocalAspectOf(aspectType)));
		il.append(InstructionConstants.ACONST_NULL);// Class[] for "getDeclaredMethod"
		il.append(factory.createInvoke("java/lang/Class", "getDeclaredMethod", Type.getType("Ljava/lang/reflect/Method;"),
				new Type[] { Type.getType("Ljava/lang/String;"), Type.getType("[Ljava/lang/Class;") }, Constants.INVOKEVIRTUAL));
		il.append(InstructionConstants.ACONST_NULL);// Object for "invoke", static method
		il.append(InstructionConstants.ACONST_NULL);// Object[] for "invoke", no arg
		il.append(factory.createInvoke("java/lang/reflect/Method", "invoke", Type.OBJECT, new Type[] {
				Type.getType("Ljava/lang/Object;"), Type.getType("[Ljava/lang/Object;") }, Constants.INVOKEVIRTUAL));
		il.append(factory.createCheckCast((ReferenceType) BcelWorld.makeBcelType(aspectType)));
		il.append(InstructionConstants.ARETURN);

		InstructionHandle handler = il.append(InstructionConstants.ASTORE_1);
		il.append(InstructionConstants.ACONST_NULL);
		il.append(InstructionConstants.ARETURN);

		method.addExceptionHandler(tryStart, handler.getPrev(), handler, new ObjectType("java.lang.Exception"), false);
	}

	private void generatePerTWCreateAspectInstanceMethod(LazyClassGen classGen) {
		InstructionFactory factory = classGen.getFactory();
		LazyMethodGen method = makeMethodGen(classGen, AjcMemberMaker.perTypeWithinCreateAspectInstance(aspectType));
		flagAsSynthetic(method, true);
		classGen.addMethodGen(method);

		InstructionList il = method.getBody();
		il.append(factory.createNew(aspectType.getName()));
		il.append(InstructionConstants.DUP);
		il.append(factory.createInvoke(aspectType.getName(), "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
		il.append(InstructionConstants.ASTORE_1);
		il.append(InstructionConstants.ALOAD_1);
		il.append(InstructionConstants.ALOAD_0);
		il.append(Utility.createSet(factory, AjcMemberMaker.perTypeWithinWithinTypeField(aspectType, aspectType)));
		il.append(InstructionConstants.ALOAD_1);
		il.append(InstructionConstants.ARETURN);
	}

	/**
	 * Add standard Synthetic (if wished) and AjSynthetic (always) attributes
	 *
	 * @param methodGen
	 * @param makeJavaSynthetic true if standard Synthetic attribute must be set as well (invisible to user)
	 */
	private static void flagAsSynthetic(LazyMethodGen methodGen, boolean makeJavaSynthetic) {
		if (makeJavaSynthetic) {
			methodGen.makeSynthetic();
		}
		methodGen.addAttribute(Utility
				.bcelAttribute(new AjAttribute.AjSynthetic(), methodGen.getEnclosingClass().getConstantPool()));
	}

	// public boolean isLateTypeMunger() {
	// return true;
	// }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy