Package org.aspectj.weaver

Source Code of org.aspectj.weaver.AsmRelationshipProvider

/* *******************************************************************
* 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 Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* Contributors:
*     PARC     initial implementation
* ******************************************************************/


package org.aspectj.weaver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.Utility;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IHierarchy;
import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.IRelationship;
import org.aspectj.asm.IRelationshipMap;
import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.weaver.bcel.BcelAdvice;


public class AsmRelationshipProvider {
 
    protected static AsmRelationshipProvider INSTANCE = new AsmRelationshipProvider();
   
  public static final String ADVISES = "advises";
  public static final String ADVISED_BY = "advised by";
  public static final String DECLARES_ON = "declares on";
  public static final String DECLAREDY_BY = "declared by";
    public static final String SOFTENS = "softens";
    public static final String SOFTENED_BY = "softened by";
    public static final String MATCHED_BY = "matched by";
  public static final String MATCHES_DECLARE = "matches declare";
  public static final String INTER_TYPE_DECLARES = "declared on";
  public static final String INTER_TYPE_DECLARED_BY = "aspect declarations";
 
  public static final String ANNOTATES = "annotates";
  public static final String ANNOTATED_BY = "annotated by";
 
  public void checkerMunger(IHierarchy model, Shadow shadow, Checker checker) {
    if (!AsmManager.isCreatingModel()) return;
    if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) return;
   
    // Ensure a node for the target exists
    IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow);

    String sourceHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
      checker.getSourceLocation().getSourceFile(),
      checker.getSourceLocation().getLine(),
      checker.getSourceLocation().getColumn(),
      checker.getSourceLocation().getOffset());
     
    String targetHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
      shadow.getSourceLocation().getSourceFile(),
      shadow.getSourceLocation().getLine(),
      shadow.getSourceLocation().getColumn(),
      shadow.getSourceLocation().getOffset());

    IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
    if (sourceHandle != null && targetHandle != null) {
      IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY,false,true);
      foreward.addTarget(targetHandle);
//      foreward.getTargets().add(targetHandle);
       
      IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE,false,true);
      if (back != null && back.getTargets() != null) {
        back.addTarget(sourceHandle);
        //back.getTargets().add(sourceHandle);  
      }
    }
  }

    // For ITDs
  public void addRelationship(
    ResolvedType onType,
    ResolvedTypeMunger munger,
    ResolvedType originatingAspect) {

    if (!AsmManager.isCreatingModel()) return;
    String sourceHandle = "";
    if (munger.getSourceLocation()!=null) {
      sourceHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
                    munger.getSourceLocation().getSourceFile(),
                    munger.getSourceLocation().getLine(),
                    munger.getSourceLocation().getColumn(),
                    munger.getSourceLocation().getOffset());
    } else {
      sourceHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
              originatingAspect.getSourceLocation().getSourceFile(),
              originatingAspect.getSourceLocation().getLine(),
              originatingAspect.getSourceLocation().getColumn(),
              originatingAspect.getSourceLocation().getOffset());
    }
    if (originatingAspect.getSourceLocation() != null) {
       
      String targetHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
        onType.getSourceLocation().getSourceFile(),
        onType.getSourceLocation().getLine(),
        onType.getSourceLocation().getColumn(),
        onType.getSourceLocation().getOffset());
       
      IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
      if (sourceHandle != null && targetHandle != null) {
        IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true);
        foreward.addTarget(targetHandle);
//        foreward.getTargets().add(targetHandle);
       
        IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true);
        back.addTarget(sourceHandle);
//        back.getTargets().add(sourceHandle); 
      }
    }
  }
 
  public void addDeclareParentsRelationship(ISourceLocation decp,ResolvedType targetType, List newParents) {
      if (!AsmManager.isCreatingModel()) return;

    String sourceHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(decp.getSourceFile(),decp.getLine(),decp.getColumn(),decp.getOffset());
   
    IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForHandle(sourceHandle);
   
 
    String targetHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
        targetType.getSourceLocation().getSourceFile(),
        targetType.getSourceLocation().getLine(),
        targetType.getSourceLocation().getColumn(),
        targetType.getSourceLocation().getOffset());
       
    IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
    if (sourceHandle != null && targetHandle != null) {
      IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true);
      foreward.addTarget(targetHandle);
       
      IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true);
      back.addTarget(sourceHandle);
    }
   
  }
 
  /**
   * Adds a declare annotation relationship, sometimes entities don't have source locs (methods/fields) so use other
   * variants of this method if that is the case as they will look the entities up in the structure model.
   */
  public void addDeclareAnnotationRelationship(ISourceLocation declareAnnotationLocation,ISourceLocation annotatedLocation) {
      if (!AsmManager.isCreatingModel()) return;
    String sourceHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(declareAnnotationLocation.getSourceFile(),declareAnnotationLocation.getLine(),
                                  declareAnnotationLocation.getColumn(),declareAnnotationLocation.getOffset());
    IProgramElement declareAnnotationPE = AsmManager.getDefault().getHierarchy().findElementForHandle(sourceHandle);
   
    String targetHandle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(
        annotatedLocation.getSourceFile(),
        annotatedLocation.getLine(),
        annotatedLocation.getColumn(),
        annotatedLocation.getOffset());
       
    IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
    if (sourceHandle != null && targetHandle != null) {
      IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES,false,true);
      foreward.addTarget(targetHandle);
       
      IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY,false,true);
      back.addTarget(sourceHandle);
    }
  }
 
  public void adviceMunger(IHierarchy model, Shadow shadow, ShadowMunger munger) {
    if (!AsmManager.isCreatingModel()) return;
    if (munger instanceof Advice) {
      Advice advice = (Advice)munger;
     
      if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) {
        // TODO: might want to show these in the future
        return;
      }
     

      IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
      IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow);
      boolean runtimeTest = ((BcelAdvice)munger).hasDynamicTests();
     
      // Work out extra info to inform interested UIs !
      IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation();

      String adviceHandle = advice.getHandle();
     
      // What kind of advice is it?
      // TODO: Prob a better way to do this but I just want to
      // get it into CVS !!!
      AdviceKind ak = ((Advice)munger).getKind();
      ai.setExtraAdviceInformation(ak.getName());
      IProgramElement adviceElement = AsmManager.getDefault().getHierarchy().findElementForHandle(adviceHandle);
      adviceElement.setExtraInfo(ai);   
     
      if (adviceHandle != null && targetNode != null) {
   
        if (targetNode != null) {
                    String targetHandle = targetNode.getHandleIdentifier();
                    if (advice.getKind().equals(AdviceKind.Softener)) {
                        IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.DECLARE_SOFT, SOFTENS,runtimeTest,true);
                        if (foreward != null) foreward.addTarget(targetHandle);//foreward.getTargets().add(targetHandle);
                       
                        IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, SOFTENED_BY,runtimeTest,true);
                        if (back != null)     back.addTarget(adviceHandle);//back.getTargets().add(adviceHandle);
                    } else {
              IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES,runtimeTest,true);
              if (foreward != null) foreward.addTarget(targetHandle);//foreward.getTargets().add(targetHandle);
             
              IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY,runtimeTest,true);
              if (back != null)     back.addTarget(adviceHandle);//back.getTargets().add(adviceHandle);
                    }
                }
      }

    }
  }

  protected IProgramElement getNode(IHierarchy model, Shadow shadow) {
    Member enclosingMember = shadow.getEnclosingCodeSignature();
   
    IProgramElement enclosingNode = lookupMember(model, enclosingMember);
    if (enclosingNode == null) {
      Lint.Kind err = shadow.getIWorld().getLint().shadowNotInStructure;
      if (err.isEnabled()) {
        err.signal(shadow.toString(), shadow.getSourceLocation());
      }
      return null;
    }
   
    Member shadowSig = shadow.getSignature();
    if (!shadowSig.equals(enclosingMember)) {
      IProgramElement bodyNode = findOrCreateCodeNode(enclosingNode, shadowSig, shadow);
      return bodyNode;
    } else {
      return enclosingNode;
    }
  }
 
  private boolean sourceLinesMatch(ISourceLocation loc1,ISourceLocation loc2) {
    if (loc1.getLine()!=loc2.getLine()) return false;
    return true;
  }
 
 
  private IProgramElement findOrCreateCodeNode(IProgramElement enclosingNode, Member shadowSig, Shadow shadow)
  {
    for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext(); ) {
      IProgramElement node = (IProgramElement)it.next();
      if (shadowSig.getName().equals(node.getBytecodeName()) &&
        shadowSig.getSignature().equals(node.getBytecodeSignature()) &&
        sourceLinesMatch(node.getSourceLocation(),shadow.getSourceLocation()))
      {
        return node;
      }
    }
   
    ISourceLocation sl = shadow.getSourceLocation();
   
//    XXX why not use shadow file? new SourceLocation(sl.getSourceFile(), sl.getLine()),
    SourceLocation peLoc = new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(),sl.getLine());
    peLoc.setOffset(sl.getOffset());
    IProgramElement peNode = new ProgramElement(
      shadow.toString(),
      IProgramElement.Kind.CODE,
      peLoc,
      0,
      "",
      new ArrayList());
       
    peNode.setBytecodeName(shadowSig.getName());
    peNode.setBytecodeSignature(shadowSig.getSignature());
    enclosingNode.addChild(peNode);
    return peNode;
  }
 
  protected IProgramElement lookupMember(IHierarchy model, Member member) {
    UnresolvedType declaringType = member.getDeclaringType();
    IProgramElement classNode =
      model.findElementForType(declaringType.getPackageName(), declaringType.getClassName());
    return findMemberInClass(classNode, member);
  }
  protected IProgramElement findMemberInClass(
    IProgramElement classNode,
    Member member)
  {
    if (classNode == null) return null; // XXX remove this check
    for (Iterator it = classNode.getChildren().iterator(); it.hasNext(); ) {
      IProgramElement node = (IProgramElement)it.next();
      if (member.getName().equals(node.getBytecodeName()) &&
        member.getSignature().equals(node.getBytecodeSignature()))
      {
        return node;
      }
    }
     // if we can't find the member, we'll just put it in the class
    return classNode;
  }
 
//  private static IProgramElement.Kind genShadowKind(Shadow shadow) {
//    IProgramElement.Kind shadowKind;
//    if (shadow.getKind() == Shadow.MethodCall
//      || shadow.getKind() == Shadow.ConstructorCall
//      || shadow.getKind() == Shadow.FieldGet
//      || shadow.getKind() == Shadow.FieldSet
//      || shadow.getKind() == Shadow.ExceptionHandler) {
//      return IProgramElement.Kind.CODE;
//     
//    } else if (shadow.getKind() == Shadow.MethodExecution) {
//      return IProgramElement.Kind.METHOD;
//     
//    } else if (shadow.getKind() == Shadow.ConstructorExecution) {
//      return IProgramElement.Kind.CONSTRUCTOR;
//     
//    } else if (shadow.getKind() == Shadow.PreInitialization
//      || shadow.getKind() == Shadow.Initialization) {
//      return IProgramElement.Kind.CLASS;
//     
//    } else if (shadow.getKind() == Shadow.AdviceExecution) {
//      return IProgramElement.Kind.ADVICE;
//     
//    } else {
//      return IProgramElement.Kind.ERROR;
//    }
//  }

    public static AsmRelationshipProvider getDefault() {
        return INSTANCE;
    }
   
    /**
     * Reset the instance of this class, intended for extensibility.
     * This enables a subclass to become used as the default instance.
     */
    public static void setDefault(AsmRelationshipProvider instance) {
        INSTANCE = instance;
    }

    /**
     * Add a relationship to the known set for a declare @method/@constructor construct. 
     * Locating the method is a messy (for messy read 'fragile') bit of code that could break at any moment
     * but it's working for my simple testcase.  Currently just fails silently if any of the lookup code
     * doesn't find anything...
     */
  public void addDeclareAnnotationRelationship(ISourceLocation sourceLocation, String typename,Method method) {
    if (!AsmManager.isCreatingModel()) return;
     
    String pkg  = null;
    String type = typename;
    int packageSeparator = typename.lastIndexOf(".");
    if (packageSeparator!=-1) {
     pkg = typename.substring(0,packageSeparator);
      type = typename.substring(packageSeparator+1);
    }
   
    IProgramElement typeElem = AsmManager.getDefault().getHierarchy().findElementForType(pkg,type);
    if (typeElem == null) return;


    StringBuffer parmString = new StringBuffer("(");
    Type[] args = method.getArgumentTypes();
    for (int i = 0; i < args.length; i++) {
      Type type2 = args[i];
      String s = Utility.signatureToString(type2.getSignature());
      if (s.lastIndexOf(".")!=-1) s =s.substring(s.lastIndexOf(".")+1);
      parmString.append(s);
      if ((i+1)<args.length) parmString.append(",");
    }
    parmString.append(")");
    IProgramElement methodElem = null;
   
    if (method.getName().startsWith("<init>")) {
      // its a ctor
      methodElem = AsmManager.getDefault().getHierarchy().findElementForSignature(typeElem,IProgramElement.Kind.CONSTRUCTOR,type+parmString);
    if (methodElem == null && args.length==0) methodElem = typeElem; // assume default ctor
    } else {
      // its a method
      methodElem = AsmManager.getDefault().getHierarchy().findElementForSignature(typeElem,IProgramElement.Kind.METHOD,method.getName()+parmString);
    }
   
    if (methodElem == null) return;
   
    try {
      String sourceHandle =
            AsmManager.getDefault().getHandleProvider().createHandleIdentifier(sourceLocation.getSourceFile(),sourceLocation.getLine(),
       sourceLocation.getColumn(),sourceLocation.getOffset());
         
      String targetHandle = methodElem.getHandleIdentifier();
      IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
    if (sourceHandle != null && targetHandle != null) {
        IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES,false,true);
        foreward.addTarget(targetHandle);
         
        IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY,false,true);
        back.addTarget(sourceHandle);
    }
        } catch (Throwable t) { // I'm worried about that code above, this will make sure we don't explode if it plays up
          t.printStackTrace(); // I know I know .. but I don't want to lose it!
        }
  }
 
    /**
     * Add a relationship to the known set for a declare @field construct.  Locating the field is trickier than
     * it might seem since we have no line number info for it, we have to dig through the structure model under
     * the fields' type in order to locate it.  Currently just fails silently if any of the lookup code
     * doesn't find anything...
     */
  public void addDeclareAnnotationRelationship(ISourceLocation sourceLocation, String typename,Field field) {
      if (!AsmManager.isCreatingModel()) return;
     
        String pkg  = null;
      String type = typename;
      int packageSeparator = typename.lastIndexOf(".");
      if (packageSeparator!=-1) {
        pkg  = typename.substring(0,packageSeparator);
        type = typename.substring(packageSeparator+1);
      }
     
        IProgramElement typeElem = AsmManager.getDefault().getHierarchy().findElementForType(pkg,type);
        if (typeElem == null) return;
       
        IProgramElement fieldElem = AsmManager.getDefault().getHierarchy().findElementForSignature(typeElem,IProgramElement.Kind.FIELD,field.getName());
        if (fieldElem== null) return;

    String sourceHandle =
            AsmManager.getDefault().getHandleProvider().createHandleIdentifier(sourceLocation.getSourceFile(),sourceLocation.getLine(),
        sourceLocation.getColumn(),sourceLocation.getOffset());
       
    String targetHandle = fieldElem.getHandleIdentifier();
   
        IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
    if (sourceHandle != null && targetHandle != null) {
      IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES,false,true);
      foreward.addTarget(targetHandle);
       
      IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY,false,true);
      back.addTarget(sourceHandle);
    }
  }
 
}
TOP

Related Classes of org.aspectj.weaver.AsmRelationshipProvider

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.