Package org.aspectj.weaver.bcel

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

/* *******************************************************************
* 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
*     Alexandre Vasseur    perClause support for @AJ aspects
* ******************************************************************/


package org.aspectj.weaver.bcel;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ClassParser;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.FieldInstruction;
import org.aspectj.apache.bcel.generic.GETSTATIC;
import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
import org.aspectj.apache.bcel.generic.INVOKESTATIC;
import org.aspectj.apache.bcel.generic.InvokeInstruction;
import org.aspectj.apache.bcel.generic.PUTSTATIC;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.util.ClassLoaderRepository;
import org.aspectj.apache.bcel.util.ClassPath;
import org.aspectj.apache.bcel.util.Repository;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.ICrossReferenceHandler;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberImpl;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.AjAttribute.Aspect;
import org.aspectj.weaver.patterns.FormalBinding;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.SimpleScope;

public class BcelWorld extends World implements Repository {
  private ClassPathManager classPath;

    private Repository delegate;

  //private ClassPathManager aspectPath = null;
  // private List aspectPathEntries;
 
    // ---- constructors

  public BcelWorld() {
    this("");   
  }
 
  public BcelWorld(String cp) {
    this(makeDefaultClasspath(cp), IMessageHandler.THROW, null);
  }
 
  private static List makeDefaultClasspath(String cp) {
    List classPath = new ArrayList();
    classPath.addAll(getPathEntries(cp));
    classPath.addAll(getPathEntries(ClassPath.getClassPath()));
    //System.err.println("classpath: " + classPath);
    return classPath;
   
  }
   
  private static List getPathEntries(String s) {
    List ret = new ArrayList();
    StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);

        while(tok.hasMoreTokens()) ret.add(tok.nextToken());
       
        return ret;
  }
 
  public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
    //this.aspectPath = new ClassPathManager(aspectPath, handler);
    this.classPath = new ClassPathManager(classPath, handler);
    setMessageHandler(handler)
    setCrossReferenceHandler(xrefHandler);
    // Tell BCEL to use us for resolving any classes
        delegate = this;
    // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
        // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
  }
 
  public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
    this.classPath = cpm;
    setMessageHandler(handler);
    setCrossReferenceHandler(xrefHandler);
    // Tell BCEL to use us for resolving any classes
        delegate = this;
        // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
        // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
  }

    /**
     * Build a World from a ClassLoader, for LTW support
     *
     * @param loader
     * @param handler
     * @param xrefHandler
     */
    public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
        this.classPath = null;
        setMessageHandler(handler);
        setCrossReferenceHandler(xrefHandler);
        // Tell BCEL to use us for resolving any classes
        delegate = new ClassLoaderRepository(loader);
        // TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
        // if so, how can that be safe in J2EE ?? (static stuff in Bcel)
    }

  public void addPath (String name) {
    classPath.addPath(name, this.getMessageHandler());
  }

    /**
     * Parse a string into advice.
     *
     * <blockquote><pre>
     * Kind ( Id , ... ) : Pointcut -> MethodSignature
     * </pre></blockquote>
     */
    public Advice shadowMunger(String str, int extraFlag) {
        str = str.trim();
        int start = 0;
        int i = str.indexOf('(');
        AdviceKind kind =
            AdviceKind.stringToKind(str.substring(start, i));
        start = ++i;
        i = str.indexOf(')', i);
        String[] ids = parseIds(str.substring(start, i).trim());
        //start = ++i;
       
       
       
        i = str.indexOf(':', i);       
        start = ++i;       
        i = str.indexOf("->", i);
        Pointcut pointcut = Pointcut.fromString(str.substring(start, i).trim());
        Member m = MemberImpl.methodFromString(str.substring(i+2, str.length()).trim());

        // now, we resolve
        UnresolvedType[] types = m.getParameterTypes();
        FormalBinding[] bindings = new FormalBinding[ids.length];
        for (int j = 0, len = ids.length; j < len; j++) {
            bindings[j] = new FormalBinding(types[j], ids[j], j, 0, 0, "fromString");
        }

        Pointcut p =
          pointcut.resolve(new SimpleScope(this, bindings));

        return new BcelAdvice(kind, p, m, extraFlag, 0, 0, null, null);
    }
   
    private String[] parseIds(String str) {
        if (str.length() == 0) return ZERO_STRINGS;
        List l = new ArrayList();
        int start = 0;
        while (true) {
            int i = str.indexOf(',', start);
            if (i == -1) {
                l.add(str.substring(start).trim());
                break;
            }
            l.add(str.substring(start, i).trim());
            start = i+1;
        }
        return (String[]) l.toArray(new String[l.size()]);
    }
   
    // ---- various interactions with bcel

    public static Type makeBcelType(UnresolvedType type) {
        return Type.getType(type.getErasureSignature());
    }

    static Type[] makeBcelTypes(UnresolvedType[] types) {
        Type[] ret = new Type[types.length];
        for (int i = 0, len = types.length; i < len; i++) {
            ret[i] = makeBcelType(types[i]);
        }
        return ret;
    }

    static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
        String[] ret = new String[types.length];
        for (int i = 0, len = types.length; i < len; i++) {
            ret[i] = types[i].getClassName();//makeBcelType(types[i]);
        }
        return ret;
    }

    public static UnresolvedType fromBcel(Type t) {
        return UnresolvedType.forSignature(t.getSignature());
    }

    static UnresolvedType[] fromBcel(Type[] ts) {
        UnresolvedType[] ret = new UnresolvedType[ts.length];
        for (int i = 0, len = ts.length; i < len; i++) {
            ret[i] = fromBcel(ts[i]);
        }
        return ret;
    }
   
    public ResolvedType resolve(Type t) {
        return resolve(fromBcel(t));
    }      


  protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
        String name = ty.getName();
        JavaClass jc = null;
        //UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
        //if (classFile != null) jc = classFile.getJavaClass();
//    if (jc == null) {
//        jc = lookupJavaClass(aspectPath, name);
//    }
        if (jc == null) {
          jc = lookupJavaClass(classPath, name);
        }      
        if (jc == null) {
          return null;
        } else {
          return makeBcelObjectType(ty, jc, false);
        }
  }
 
  protected BcelObjectType makeBcelObjectType(ReferenceType resolvedTypeX, JavaClass jc, boolean exposedToWeaver) {
    BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, exposedToWeaver);
    return ret;
  }
 
 
  private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
        if (classPath == null) {
            try {
                return delegate.loadClass(name);
            } catch (ClassNotFoundException e) {
                return null;
            }
        }

    try {
          ClassPathManager.ClassFile file = classPath.find(UnresolvedType.forName(name));
          if (file == null) return null;
         
          ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
         
          JavaClass jc = parser.parse();
      file.close();
      return jc;
    } catch (IOException ioe) {
      return null;
    }
  }
 
 
  public BcelObjectType addSourceObjectType(JavaClass jc) {
    BcelObjectType ret = null;
    String signature = UnresolvedType.forName(jc.getClassName()).getSignature();
   
    Object fromTheMap = typeMap.get(signature);
   
    if (fromTheMap!=null && !(fromTheMap instanceof ReferenceType)) {
      // what on earth is it then? See pr 112243
      StringBuffer exceptionText = new StringBuffer();
      exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
      exceptionText.append("Signature=["+signature+"] Found=["+fromTheMap+"] Class=["+fromTheMap.getClass()+"]");
      throw new BCException(exceptionText.toString());
    }
   
    ReferenceType nameTypeX = (ReferenceType)fromTheMap;
       
        if (nameTypeX == null) {         
        if (jc.isGeneric()) {
          nameTypeX =  ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()),this);
            ret = makeBcelObjectType(nameTypeX, jc, true);
          ReferenceType genericRefType = new ReferenceType(
              UnresolvedType.forGenericTypeSignature(signature,ret.getDeclaredGenericSignature()),this);
        nameTypeX.setDelegate(ret);
          genericRefType.setDelegate(ret);
          nameTypeX.setGenericType(genericRefType);
             typeMap.put(signature, nameTypeX);
        } else {
            nameTypeX = new ReferenceType(signature, this);
              ret = makeBcelObjectType(nameTypeX, jc, true);
               typeMap.put(signature, nameTypeX);
        }
        } else {
            ret = makeBcelObjectType(nameTypeX, jc, true);
        }
    return ret;
  }
 
  void deleteSourceObjectType(UnresolvedType ty) {
    typeMap.remove(ty.getSignature());
  }

    public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) {
      ConstantPoolGen cpg = cg.getConstantPoolGen();
        return           
                MemberImpl.field(
                  fi.getClassName(cpg),
                  (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
                  ? Modifier.STATIC: 0,
                  fi.getName(cpg),
                  fi.getSignature(cpg));
    }
 
//    public static Member makeFieldSetSignature(LazyClassGen cg, FieldInstruction fi) {
//      ConstantPoolGen cpg = cg.getConstantPoolGen();
//        return
//            MemberImpl.field(
//                fi.getClassName(cpg),
//                (fi instanceof GETSTATIC || fi instanceof PUTSTATIC)
//                ? Modifier.STATIC
//                : 0,
//                fi.getName(cpg),
//                "(" + fi.getSignature(cpg) + ")" +fi.getSignature(cpg));
//    }

  public Member makeJoinPointSignature(LazyMethodGen mg) {
    return makeJoinPointSignatureFromMethod(mg, null);
  }

 
  public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberImpl.Kind kind) {
    Member ret = mg.getMemberView();
    if (ret == null) {
          int mods = mg.getAccessFlags();
          if (mg.getEnclosingClass().isInterface()) {
              mods |= Modifier.INTERFACE;
          }
          if (kind == null) {
            if (mg.getName().equals("<init>")) {
              kind = Member.CONSTRUCTOR;
            } else if (mg.getName().equals("<clinit>")) {
              kind = Member.STATIC_INITIALIZATION;
            } else {
              kind = Member.METHOD;
            }
          }
          return new ResolvedMemberImpl(kind,
                  UnresolvedType.forName(mg.getClassName()),
                  mods,
                  fromBcel(mg.getReturnType()),
                  mg.getName(),
                  fromBcel(mg.getArgumentTypes())
                  );
    } else {
      return ret;
    }
       
    }

    public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) {
      ConstantPoolGen cpg = cg.getConstantPoolGen();
      String name = ii.getName(cpg);
        String declaring = ii.getClassName(cpg);
        UnresolvedType declaringType = null;
       
        String signature = ii.getSignature(cpg);
      
        int modifier =
            (ii instanceof INVOKEINTERFACE)
            ? Modifier.INTERFACE
            : (ii instanceof INVOKESTATIC)
              ? Modifier.STATIC
              : (ii instanceof INVOKESPECIAL && ! name.equals("<init>"))
                ? Modifier.PRIVATE
                : 0;

        // in Java 1.4 and after, static method call of super class within subclass method appears
        // as declared by the subclass in the bytecode - but they are not
        // see #104212
        if (ii instanceof INVOKESTATIC) {
            ResolvedType appearsDeclaredBy = resolve(declaring);
            // look for the method there
            for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator.hasNext();) {
                ResolvedMember method = (ResolvedMember) iterator.next();
                if (method.isStatic()) {
                    if (name.equals(method.getName()) && signature.equals(method.getSignature())) {
                        // we found it
                        declaringType = method.getDeclaringType();
                        break;
                    }
                }

            }
        }
       
        if (declaringType == null) {
          if (declaring.charAt(0)=='[') declaringType = UnresolvedType.forSignature(declaring);
          else               declaringType = UnresolvedType.forName(declaring);
        }
        return MemberImpl.method(declaringType, modifier, name, signature);
   

    public static Member makeMungerMethodSignature(JavaClass javaClass, Method method) {
        int mods = 0;
        if (method.isStatic()) mods = Modifier.STATIC;
        else if (javaClass.isInterface()) mods = Modifier.INTERFACE;
        else if (method.isPrivate()) mods = Modifier.PRIVATE;
        return MemberImpl.method(
            UnresolvedType.forName(javaClass.getClassName()), mods, method.getName(), method.getSignature());
    }
   
    private static final String[] ZERO_STRINGS = new String[0];
   
  public String toString() {
    StringBuffer buf = new StringBuffer();
    buf.append("BcelWorld(");
    //buf.append(shadowMungerMap);
    buf.append(")");
    return buf.toString();
  }

    public Advice createAdviceMunger(
         AjAttribute.AdviceAttribute attribute,
      Pointcut pointcut,
        Member signature)
    {
      //System.err.println("concrete advice: " + signature + " context " + sourceContext);
        return new BcelAdvice(attribute, pointcut, signature, null);
    }
   
    public ConcreteTypeMunger concreteTypeMunger(
        ResolvedTypeMunger munger, ResolvedType aspectType)
    {
        return new BcelTypeMunger(munger, aspectType);
    }
   
  public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
    return new BcelCflowStackFieldAdder(cflowField);
  }
 
  public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) {
    return new BcelCflowCounterFieldAdder(cflowField);
  }

    /**
     * Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
     *
     * @param aspect
     * @param kind
     * @return munger
     */
    public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) {
        return new BcelPerClauseAspectAdder(aspect, kind);
    }

    /**
     * Retrieve a bcel delegate for an aspect - this will return NULL if the
     * delegate is an EclipseSourceType and not a BcelObjectType - this happens
     * quite often when incrementally compiling.
     */
  public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) {
    ReferenceTypeDelegate rtDelegate = ((ReferenceType)concreteAspect).getDelegate();
    if (rtDelegate instanceof BcelObjectType) {
      return (BcelObjectType)rtDelegate;
    } else {
      return null;
    }
  }

  public void tidyUp() {
      // At end of compile, close any open files so deletion of those archives is possible
    classPath.closeArchives();
  }

 
  /// The repository interface methods

  public JavaClass findClass(String className) {
    return lookupJavaClass(classPath,className);
  }

  public JavaClass loadClass(String className) throws ClassNotFoundException {
    return lookupJavaClass(classPath,className);
  }

  public void storeClass(JavaClass clazz) {
    throw new RuntimeException("Not implemented");
  }

  public void removeClass(JavaClass clazz) {
    throw new RuntimeException("Not implemented");
  }

  public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
    throw new RuntimeException("Not implemented");
  }

  public void clear() {
    throw new RuntimeException("Not implemented");
  }

    // @Override
    /**
     * The aim of this method is to make sure a particular type is 'ok'.  Some
     * operations on the delegate for a type modify it and this method is
     * intended to undo that...  see pr85132
     */
  public void validateType(UnresolvedType type) {
    ResolvedType result = typeMap.get(type.getSignature());
    if (result==null) return; // We haven't heard of it yet
    if (!result.isExposedToWeaver()) return; // cant need resetting
    ReferenceType rt = (ReferenceType)result;
    rt.getDelegate().ensureDelegateConsistent();
    // If we want to rebuild it 'from scratch' then:
//    ClassParser cp = new ClassParser(new ByteArrayInputStream(newbytes),new String(cs));
//    try {
//      rt.setDelegate(makeBcelObjectType(rt,cp.parse(),true));
//    } catch (ClassFormatException e) {
//      e.printStackTrace();
//    } catch (IOException e) {
//      e.printStackTrace();
//    }
  }

    /**
     * Checks if given bytecode is an @AspectJ aspect
     *
     * @param name
     * @param bytes
     * @return true if so
     */
    public boolean isAnnotationStyleAspect(String name, byte[] bytes) {
        try {
            ClassParser cp = new ClassParser(new ByteArrayInputStream(bytes), null);
            JavaClass jc = cp.parse();
            if (!jc.isClass()) {
                return false;
            }
            Annotation anns[] = jc.getAnnotations();
            if (anns.length == 0) {
                return false;
            }
            boolean couldBeAtAspectJStyle = false;
            for (int i = 0; i < anns.length; i++) {
                Annotation ann = anns[i];
                if ("Lorg/aspectj/lang/annotation/Aspect;".equals(ann.getTypeSignature())) {
                    couldBeAtAspectJStyle = true;
                }
            }
           
            if (!couldBeAtAspectJStyle) return false;
           
            // ok, so it has the annotation, but it could have been put
            // on a code style aspect by the annotation visitor
            Attribute[] attributes = jc.getAttributes();
            for (int i = 0; i < attributes.length; i++) {
              if (attributes[i].getName().equals(Aspect.AttributeName)) {
                return false;
              }
            }
            return true;
        } catch (IOException e) {
            // assume it is one as a best effort
            return true;
        }
    }
}
TOP

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

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.