Package org.aspectj.weaver.bcel

Source Code of org.aspectj.weaver.bcel.BcelPerClauseAspectAdder

/*******************************************************************************
* Copyright (c) 2005 Contributors.
* 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://eclipse.org/legal/epl-v10.html
*
* Contributors:
* initial implementation              Alexandre Vasseur
*******************************************************************************/
package org.aspectj.weaver.bcel;

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) {
    ResolvedMember[] methods = classGen.getBcelObjectType().getDeclaredMethods();
    for (int i = 0; i < methods.length; i++) {
      ResolvedMember method = methods[i];
      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(), "<init>", 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(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
    il.append(Utility.createSet(factory, AjcMemberMaker.perSingletonField(aspectType)));
    il.append(InstructionFactory.createReturn(Type.VOID));

    // patch <clinit> 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(), "<init>", 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(), "<init>", 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(), "<init>", 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(), "<init>", 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(), "<init>", 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(), "<init>", 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(), "<init>", 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;
  // }
}
TOP

Related Classes of org.aspectj.weaver.bcel.BcelPerClauseAspectAdder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.