Package org.aspectj.weaver.bcel

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

/* *******************************************************************
* Copyright (c) 2005 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* Contributors:
*     Andy Clement     initial implementation
* ******************************************************************/


package org.aspectj.weaver.bcel;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.Instruction;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.Shadow.Kind;


/**
* Represents access to an annotation on an element, relating to some 'kinded' pointcut. 
* Depending on the kind of pointcut the element might be a field or a method or a ...
*/
public class KindedAnnotationAccessVar extends BcelVar {

  private Kind   kind;           // What kind of shadow are we at?
  private UnresolvedType  containingType; // The type upon which we want to ask for 'member'
  private Member member;         // For method call/execution and field get/set contains the member that has the annotation
 
  public KindedAnnotationAccessVar(Kind kind, ResolvedType type,UnresolvedType theTargetIsStoredHere,Member sig) {
    super(type,0);
    this.kind = kind;
    this.containingType = theTargetIsStoredHere;
    this.member = sig;
  }

  public String toString() {
    return "KindedAnnotationAccessVar(" + getType() +")";
  }

    public Instruction createLoad(InstructionFactory fact) {
    throw new RuntimeException("unimplemented");
    }
    public Instruction createStore(InstructionFactory fact) {
      throw new RuntimeException("unimplemented");
    }

    public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
        throw new RuntimeException("unimplemented");
    }
   
  public void appendLoad(InstructionList il, InstructionFactory fact) {
    il.append(createLoadInstructions(getType(), fact));
  }

  // FIXME asc Refactor all this stuff - there is a lot of commonality 
  public InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
   
    // FIXME asc Decide on whether we ought to build an exception handler for the NoSuchMethodException that can be thrown
    // by getDeclaredMethod()... right now we don't but no-one seems to care...
//    LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
//    int var_ex_slot = var_ex.getIndex();
//   
//    InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
//    var_ex.setStart(handler);
//    var_ex.setEnd(il.append(InstructionConstants.RETURN));
//   
//    mg.addExceptionHandler(try_start, try_end, handler,
//        new ObjectType("java.io.IOException"));
   
   
    InstructionList il = new InstructionList();
    Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS);

    Type jlString = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.String;"));
    Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.forSignature("[Ljava.lang.Class;"));
   
    Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;"));
   
    if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution ||
      kind==Shadow.PreInitialization || kind==Shadow.Initialization ||
      kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution ||
      kind==Shadow.AdviceExecution ||
      // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
      ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD)) {
     
      Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Method;"));
   
    // Calls getClass
     
    // Variant (1) Use the target directly
        il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
       
    // Variant (2) Ask the target for its class (could give a different answer at runtime)
        // il.append(target.createLoad(fact));
        // il.append(fact.createInvoke("java/lang/Object","getClass",jlClass,new Type[]{},Constants.INVOKEVIRTUAL));
   
      // il.append(fact.createConstant(new ObjectType(toType.getClassName())));
      
     
      if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || kind==Shadow.AdviceExecution ||
        // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
        ((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD) ||
        ((kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution) && member.getKind()==Member.METHOD)) {
      il.append(fact.createConstant(member.getName()));
        Type[] paramTypes = null;
      paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
      buildArray(il,fact,jlClass,paramTypes,1);
      // Calls getDeclaredMethod
      il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL));
      // FIXME asc perf Cache the result of getDeclaredMethod() and use it
          // again for other annotations on the same signature at this join point
          // Calls getAnnotation
          String ss = toType.getName();
          il.append(fact.createConstant(new ObjectType(toType.getName())));   
      il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
      il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
      } else { // init/preinit/ctor-call/ctor-exec
      Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
      buildArray(il,fact,jlClass,paramTypes,1);
      Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Constructor;"));
      il.append(fact.createInvoke("java/lang/Class","getDeclaredConstructor",jlrCtor,new Type[]{jlClassArray},Constants.INVOKEVIRTUAL));
   
      // !!! OPTIMIZATION: Cache the result of getDeclaredMethod() and use it
      // again for other annotations on the same signature at this join point
      // Calls getAnnotation
      String ss = toType.getName();
      il.append(fact.createConstant(new ObjectType(toType.getName())));   
      il.append(fact.createInvoke("java/lang/reflect/Constructor","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
      il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
      }
    } else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) {
      Type jlrField = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Field;"));
      il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); // Stick the target on the stack
      il.append(fact.createConstant(member.getName())); // Stick what we are after on the stack
      il.append(fact.createInvoke("java/lang/Class","getDeclaredField",jlrField,new Type[]{jlString},Constants.INVOKEVIRTUAL));
      String ss = toType.getName();
          il.append(fact.createConstant(new ObjectType(toType.getName())));   
      il.append(fact.createInvoke("java/lang/reflect/Field","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
      il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
    } else if (kind == Shadow.StaticInitialization || kind==Shadow.ExceptionHandler) {
      il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
      String ss = toType.getName();
          il.append(fact.createConstant(new ObjectType(toType.getName())));   
      il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL));
      il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType)));
    } else {
      throw new RuntimeException("Don't understand this kind "+kind);
    }
    return il;
   
  }
 

  private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries,int dim) {
        il.append(fact.createConstant(new Integer(arrayEntries==null?0:arrayEntries.length)));
        il.append(fact.createNewArray(arrayElementType,(short)dim));
        if (arrayEntries == null) return;
        for (int i = 0; i < arrayEntries.length; i++) {
      il.append(InstructionFactory.createDup(1));
      il.append(fact.createConstant(new Integer(i)));
          switch (arrayEntries[i].getType()) {
            case Constants.T_ARRAY:
              il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature())));
              break;
            case Constants.T_BOOLEAN: il.append(fact.createGetStatic("java/lang/Boolean","TYPE",arrayElementType)); break;
            case Constants.T_BYTE:il.append(fact.createGetStatic("java/lang/Byte","TYPE",arrayElementType)); break;
            case Constants.T_CHAR:il.append(fact.createGetStatic("java/lang/Character","TYPE",arrayElementType)); break;
            case Constants.T_INT:il.append(fact.createGetStatic("java/lang/Integer","TYPE",arrayElementType)); break;
            case Constants.T_LONG:il.append(fact.createGetStatic("java/lang/Long","TYPE",arrayElementType)); break;
            case Constants.T_DOUBLE:il.append(fact.createGetStatic("java/lang/Double","TYPE",arrayElementType)); break;
            case Constants.T_FLOAT:il.append(fact.createGetStatic("java/lang/Float","TYPE",arrayElementType)); break;
            case Constants.T_SHORT:il.append(fact.createGetStatic("java/lang/Short","TYPE",arrayElementType)); break;
            default:
              il.append(fact.createConstant(arrayEntries[i]));
          }
      il.append(InstructionConstants.AASTORE);
    }
  }

  public void appendLoadAndConvert(
    InstructionList il,
    InstructionFactory fact,
    ResolvedType toType) {
    il.append(createLoadInstructions(toType, fact));       

  }

  public void insertLoad(InstructionList il, InstructionFactory fact) {
    il.insert(createLoadInstructions(getType(), fact));
  }

}
TOP

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

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.