Package kilim.analysis

Source Code of kilim.analysis.Detector

/* Copyright (c) 2006, Sriram Srinivasan
*
* You may distribute this software under the terms of the license
* specified in the file "License"
*/
package kilim.analysis;
import static kilim.Constants.D_OBJECT;

import java.util.ArrayList;

import kilim.Constants;
import kilim.NotPausable;
import kilim.Pausable;
import kilim.mirrors.ClassMirror;
import kilim.mirrors.ClassMirrorNotFoundException;
import kilim.mirrors.MethodMirror;
import kilim.mirrors.Mirrors;
/**
* Utility class to check if a method has been marked pausable
*
*/
public class Detector {
    public static final int                   METHOD_NOT_FOUND         = 0;
    public static final int                   PAUSABLE_METHOD_FOUND    = 1;
    public static final int                   METHOD_NOT_PAUSABLE      = 2;

    // Note that we don't have the kilim package itself in the following list.
    static final String[]                     STANDARD_DONT_CHECK_LIST = {
            "java.", "javax."                                         };

    public static final Detector DEFAULT = new Detector(Mirrors.getRuntimeMirrors());

    private final Mirrors mirrors;
   
    public Detector(Mirrors mirrors) {
      this.mirrors = mirrors;
     
         NOT_PAUSABLE = mirrors.mirror(NotPausable.class);
         PAUSABLE = mirrors.mirror(Pausable.class);
         OBJECT = mirrors.mirror(Object.class);

  }

    ClassMirror NOT_PAUSABLE, PAUSABLE, OBJECT;
   
  public boolean isPausable(String className, String methodName,
            String desc) {
        return getPausableStatus(className, methodName, desc) == PAUSABLE_METHOD_FOUND;
    }

    /**
     * @return one of METHOD_NOT_FOUND, PAUSABLE_METHOD_FOUND, METHOD_NOT_PAUSABLE
     */
   
    public int getPausableStatus(String className, String methodName,
            String desc)
    {
        int ret = METHOD_NOT_FOUND;
        if (methodName.endsWith("init>")) {
            return METHOD_NOT_PAUSABLE; // constructors are not pausable.
        }
        className = className.replace('/', '.');
        try {
            ClassMirror cl = mirrors.classForName(className);
            MethodMirror m = findMethod(cl, methodName, desc);
            if (m != null) {
                for (ClassMirror c: m.getExceptionTypes()) {
                    if (NOT_PAUSABLE.isAssignableFrom(c)) {
                        return METHOD_NOT_PAUSABLE;
                    }
                    if (PAUSABLE.isAssignableFrom(c)) {
                        return PAUSABLE_METHOD_FOUND;
                    }
                }
                return METHOD_NOT_PAUSABLE;
            }
         } catch (ClassMirrorNotFoundException ignore) {
            
         } catch (VerifyError ve) {
             return AsmDetector.getPausableStatus(className, methodName, desc, this);
         }
         return ret;
    }
   
    private MethodMirror findMethod(ClassMirror cl, String methodName, String desc) {
        if (cl == null) return null;
        MethodMirror m = findMethodInHierarchy(cl, methodName, desc);
        if (m == null) {
            cl = mirrors.mirror(Object.class);
            for (MethodMirror om : cl.getDeclaredMethods()) {
                if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
                    return om;
                }
            }
        }
        return m;
    }
   
    private MethodMirror findMethodInHierarchy(ClassMirror cl, String methodName,
            String desc) {
        if (cl == nullreturn null;
       
        for (MethodMirror om : cl.getDeclaredMethods()) {
            if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
                if (om.isBridge()) continue;
                return om;
            }
        }

        if (OBJECT.equals(cl))
            return null;

        MethodMirror m = findMethodInHierarchy(cl.getSuperclass(), methodName, desc);
        if (m != null)
            return m;
        for (ClassMirror ifcl : cl.getInterfaces()) {
            m = findMethodInHierarchy(ifcl, methodName, desc);
            if (m != null)
                return m;
        }
        return null;
    }

    public static String D_FIBER_ = Constants.D_FIBER + ")";

    @SuppressWarnings("unused")
  private static String statusToStr(int st) {
        switch (st) {
        case METHOD_NOT_FOUND : return "not found";
        case PAUSABLE_METHOD_FOUND : return "pausable";
        case METHOD_NOT_PAUSABLE : return "not pausable";
        default: throw new AssertionError("Unknown status");
        }
    }
   

    static private final ThreadLocal<Detector> DETECTOR = new ThreadLocal<Detector>();
   
    static Detector getDetector() {
      Detector d = DETECTOR.get();
      if (d == null) return Detector.DEFAULT;
      return d;
    }

    static Detector setDetector(Detector d) {
      Detector res = DETECTOR.get();
      DETECTOR.set(d);
      return res;
    }

  public String commonSuperType(String oa, String ob) throws ClassMirrorNotFoundException {
        String a = toClassName(oa);
        String b = toClassName(ob);
       
        try {
          ClassMirror ca = mirrors.classForName(a);
          ClassMirror cb = mirrors.classForName(b);
          if (ca.isAssignableFrom(cb)) return oa;
          if (cb.isAssignableFrom(ca)) return ob;
          if (ca.isInterface() && cb.isInterface()) {
              return D_OBJECT; // This is what the java bytecode verifier does
          }
        } catch (ClassMirrorNotFoundException e) {
          // try to see if the below works...
        }
       
        ArrayList<String> sca = getSuperClasses(a);
        ArrayList<String> scb = getSuperClasses(b);
        int lasta = sca.size()-1;
        int lastb = scb.size()-1;
        do {
            if (sca.get(lasta).equals(scb.get(lastb))) {
                lasta--;
                lastb--;
            } else {
                break;
            }
        } while (lasta >= 0 && lastb >= 0);
        return toDesc(sca.get(lasta+1));   
  }
 

    public ArrayList<String> getSuperClasses(String cc) throws ClassMirrorNotFoundException {
      ClassMirror c = mirrors.classForName(cc);
        ArrayList<String> ret = new ArrayList<String>(3);
        while (c != null) {
            ret.add(c.getName());
            c = c.getSuperclass();
        }
        return ret;
       
    }
   
    private static String toDesc(String name) {
        return (name.equals(JAVA_LANG_OBJECT)) ?
                D_OBJECT : "L" + name.replace('.', '/') + ';';
    }

    private static String toClassName(String s) {
        return s.replace('/','.').substring(1,s.length()-1);
    }
   
    static String JAVA_LANG_OBJECT = "java.lang.Object";

}
TOP

Related Classes of kilim.analysis.Detector

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.