Package kilim.analysis

Source Code of kilim.analysis.ClassFlow

/* 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 kilim.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;

/**
* This class reads a .class file (or stream), wraps each method with a MethodFlow
* object and optionally analyzes it.
*
*/
public class ClassFlow extends ClassNode {
    ArrayList<MethodFlow> methodFlows;
    ClassReader cr;
    String classDesc;
    /**
     * true if any of the methods contained in the class file is pausable.
     * ClassWeaver uses it later to avoid weaving if isPausable isn't true.
     */
    private boolean isPausable;

    /**
     * true if the .class being read is already woven.
     */
    public boolean isWoven = false;
  private Detector detector;
   
    public ClassFlow(InputStream is, Detector detector) throws IOException {
        cr = new ClassReader(is);
      this.detector = detector;
    }
   
    public ClassFlow(String aClassName, Detector detector) throws IOException {
        cr = new ClassReader(aClassName);
      this.detector = detector;
    }
   
    public ClassFlow(byte[] data, Detector detector) {
      cr = new ClassReader(data);
      this.detector = detector;
  }

  @Override
  @SuppressWarnings({"unchecked"})
    public MethodVisitor visitMethod(
            final int access,
            final String name,
            final String desc,
            final String signature,
            final String[] exceptions)
    {
        MethodFlow mn = new MethodFlow( this, access, name,  desc, signature,
                exceptions, detector);
        super.methods.add(mn);
        return mn;
    }
   
    public ArrayList<MethodFlow> getMethodFlows(){
        assert (methodFlows != null): "ClassFlow.analyze not called";
        return methodFlows;
    }
   
  public ArrayList<MethodFlow> analyze(boolean forceAnalysis) throws KilimException {
//        cr.accept(this, ClassReader.SKIP_DEBUG);
   
    Detector save = Detector.setDetector(detector);
    try {
   
        cr.accept(this, false);
        for (Object o: this.fields) {
            FieldNode fn = (FieldNode)o;
            if (fn.name.equals(Constants.WOVEN_FIELD)) {
                isWoven = true; break;
            }
        }
       
        cr = null; // We don't need this any more.
        classDesc = TypeDesc.getInterned("L" + name + ';');
        ArrayList<MethodFlow> flows = new ArrayList<MethodFlow>(methods.size());
        String msg = "";
        for (Object o: methods) {
            try {
                MethodFlow mf = (MethodFlow)o;
                if (mf.isBridge()) {
                    MethodFlow mmf = getOrigWithSameSig(mf);
                    if (mmf != null)
                        mf.setPausable(mmf.isPausable());
                }
                mf.verifyPausables();
                if (mf.isPausable()) isPausable = true;
                if ((mf.isPausable() || forceAnalysis) && (!mf.isAbstract())) {
                    mf.analyze();
                }
                flows.add(mf);
            } catch (KilimException ke) {
                msg = msg + ke.getMessage() + "\n-------------------------------------------------\n";
            }
        }
        if (msg.length() > 0) {
            throw new KilimException(msg);
        }
        methodFlows = flows;
        return flows;
       
    } finally {
      Detector.setDetector(save);
    }
    }
   
    private MethodFlow getOrigWithSameSig(MethodFlow bridgeMethod) {
        for (Object o:methods) {
            MethodFlow mf = (MethodFlow)o;
            if (mf == bridgeMethod) continue;
            if (mf.name.equals(bridgeMethod.name)) {
                String mfArgs = mf.desc.substring(0,mf.desc.indexOf(')'));
                String bmArgs = bridgeMethod.desc.substring(0,bridgeMethod.desc.indexOf(')'));
                if (mfArgs.equals(bmArgs)) return mf;
            }
        }
        return null;
//        throw new AssertionError("Bridge method found, but original method does not exist\nBridge method:" +
//                this.name + "::" + bridgeMethod.name + bridgeMethod.desc);
    }
   
    public String getClassDescriptor() { return classDesc; }
   
    public String getClassName() { return super.name.replace('/', '.');}

    public boolean isPausable() {
        getMethodFlows(); // check analyze has been run.
        return isPausable;
    }
   
     boolean isInterface() {
        return (this.access & Opcodes.ACC_INTERFACE) != 0;
    }

  public Detector detector() {
    return detector;
  }
}
TOP

Related Classes of kilim.analysis.ClassFlow

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.