ca.mcgill.sable.soot.callgraph.CallGraphGenerator.java Source code

Java tutorial

Introduction

Here is the source code for ca.mcgill.sable.soot.callgraph.CallGraphGenerator.java

Source

/* Soot - a J*va Optimization Framework
 * Copyright (C) 2004 Jennifer Lhotak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package ca.mcgill.sable.soot.callgraph;

import org.eclipse.ui.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.*;
import ca.mcgill.sable.graph.*;
import ca.mcgill.sable.graph.model.*;
import org.eclipse.core.runtime.*;
import java.util.*;
import java.lang.reflect.*;
import soot.jimple.toolkits.annotation.callgraph.*;
import soot.*;
import soot.tagkit.*;
import ca.mcgill.sable.soot.interaction.*;
import ca.mcgill.sable.soot.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.plugin.*;
import soot.toolkits.graph.interaction.*;
import org.eclipse.core.resources.*;
import org.eclipse.jdt.core.*;
import org.eclipse.ui.texteditor.*;
import org.eclipse.ui.part.*;

public class CallGraphGenerator {

    private CallGraphInfo info;
    private Graph graph;
    private InteractionController controller;
    private ArrayList centerList;

    public CallGraphGenerator() {
    }

    public void run() {

        IWorkbench workbench = SootPlugin.getDefault().getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        IWorkbenchPage page = window.getActivePage();
        ;

        try {
            if (graph == null) {
                setGraph(new Graph());
                graph.setName("CallGraph");
            } else {
                graph.removeAllChildren();
            }
            IEditorPart part = page.openEditor(graph, "ca.mcgill.sable.graph.GraphEditor", true);
            ((GraphEditor) part).setPartFactory(new CallGraphPartFactory());
            addActions((GraphEditor) part);
            ((GraphEditor) part)
                    .setMenuProvider(new CGMenuProvider(((GraphEditor) part).getGraphEditorGraphicalViewer(),
                            ((GraphEditor) part).getGraphEditorActionRegistry(), part));

            buildModel();
        } catch (PartInitException e3) {
            e3.printStackTrace();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }

    public void addActions(GraphEditor part) {
        ShowCodeAction showCode = new ShowCodeAction((IWorkbenchPart) part);
        part.getGraphEditorActionRegistry().registerAction(showCode);
        part.getGraphEditorSelectionActions().add(showCode.getId());

        ExpandAction expand = new ExpandAction((IWorkbenchPart) part);
        part.getGraphEditorActionRegistry().registerAction(expand);
        part.getGraphEditorSelectionActions().add(expand.getId());

        CollapseAction collapse = new CollapseAction((IWorkbenchPart) part);
        part.getGraphEditorActionRegistry().registerAction(collapse);
        part.getGraphEditorSelectionActions().add(collapse.getId());

    }

    public void buildModel() {
        CallGraphNode cgn = new CallGraphNode();
        getGraph().addChild(cgn);
        cgn.setGenerator(this);
        cgn.setData(getInfo().getCenter());

        cgn.setExpand(false);
        makeCons(getInfo(), cgn);

    }

    private CallGraphNode getNodeForMethod(SootMethod meth) {
        CallGraphNode node = null;
        Iterator it = getGraph().getChildren().iterator();
        while (it.hasNext()) {
            CallGraphNode next = (CallGraphNode) it.next();
            if (next.getData().equals(meth)) {
                node = next;
            }
        }
        if (node == null) {
            node = new CallGraphNode();
            getGraph().addChild(node);
            node.setData(meth);
        }
        return node;
    }

    private void makeCons(CallGraphInfo info, CallGraphNode center) {
        Iterator it1 = info.getInputs().iterator();
        while (it1.hasNext()) {
            MethInfo mInfo = (MethInfo) it1.next();
            SootMethod sm = mInfo.method();
            CallGraphNode inNode = getNodeForMethod(sm);
            inNode.setGenerator(this);
            Edge inEdge = new Edge(inNode, center);
            inEdge.setLabel(mInfo.edgeKind().name());
        }

        Iterator it2 = info.getOutputs().iterator();
        while (it2.hasNext()) {
            MethInfo mInfo = (MethInfo) it2.next();
            SootMethod sm = mInfo.method();
            CallGraphNode outNode = getNodeForMethod(sm);
            outNode.setGenerator(this);
            Edge inEdge = new Edge(center, outNode);
            inEdge.setLabel(mInfo.edgeKind().name());
        }
    }

    public void collapseGraph(CallGraphNode node) {
        // need to undo (remove in and out nodes
        // who are not in center list)
        ArrayList inputsToRemove = new ArrayList();
        ArrayList outputsToRemove = new ArrayList();
        ArrayList nodesToRemove = new ArrayList();

        if (node.getInputs() != null) {
            Iterator inIt = node.getInputs().iterator();
            while (inIt.hasNext()) {
                Edge next = (Edge) inIt.next();
                CallGraphNode src = (CallGraphNode) next.getSrc();
                if (src.isLeaf()) {
                    inputsToRemove.add(next);
                    nodesToRemove.add(src);
                }
            }
        }

        if (node.getOutputs() != null) {
            Iterator outIt = node.getOutputs().iterator();
            while (outIt.hasNext()) {
                Edge next = (Edge) outIt.next();
                CallGraphNode tgt = (CallGraphNode) next.getTgt();
                if (tgt.isLeaf()) {
                    outputsToRemove.add(next);
                    nodesToRemove.add(tgt);
                }
            }
        }

        Iterator inRIt = inputsToRemove.iterator();
        while (inRIt.hasNext()) {
            Edge temp = (Edge) inRIt.next();
            node.removeInput(temp);
        }

        Iterator outRIt = outputsToRemove.iterator();
        while (outRIt.hasNext()) {
            Edge temp = (Edge) outRIt.next();
            node.removeInput(temp);
        }

        Iterator nodeRIt = nodesToRemove.iterator();
        while (nodeRIt.hasNext()) {
            CallGraphNode temp = (CallGraphNode) nodeRIt.next();
            temp.removeAllInputs();
            temp.removeAllOutputs();
            getGraph().removeChild(temp);
        }

        node.setExpand(true);
    }

    public void expandGraph(CallGraphNode node) {
        getController()
                .setEvent(new InteractionEvent(IInteractionConstants.CALL_GRAPH_NEXT_METHOD, node.getData()));
        getController().handleEvent();

    }

    public void showInCode(CallGraphNode node) {
        SootMethod meth = (SootMethod) node.getData();
        String sootClassName = meth.getDeclaringClass().getName();
        sootClassName = sootClassName.replaceAll("\\.", System.getProperty("file.separator"));
        sootClassName = sootClassName + ".java";
        String sootMethName = meth.getName();

        IProject[] progs = SootPlugin.getWorkspace().getRoot().getProjects();
        IResource fileToOpen = null;
        for (int i = 0; i < progs.length; i++) {
            IProject project = progs[i];

            IJavaProject jProj = JavaCore.create(project);
            try {

                IPackageFragmentRoot[] roots = jProj.getAllPackageFragmentRoots();
                for (int j = 0; j < roots.length; j++) {
                    if (!(roots[j].getResource() instanceof IContainer))
                        continue;
                    fileToOpen = ((IContainer) roots[j].getResource()).findMember(sootClassName);
                    if (fileToOpen == null)
                        continue;
                    else
                        break;
                }
            } catch (Exception e) {
            }

            if (fileToOpen != null)
                break;
        }

        IWorkbench workbench = SootPlugin.getDefault().getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        IWorkbenchPage page = window.getActivePage();
        ;

        try {
            IEditorPart part = page.openEditor(new FileEditorInput((IFile) fileToOpen),
                    org.eclipse.jdt.ui.JavaUI.ID_CU_EDITOR);
            SourceLnPosTag methTag = (SourceLnPosTag) meth.getTag("SourceLnPosTag");
            if (methTag != null) {

                int selOffset = ((AbstractTextEditor) part).getDocumentProvider().getDocument(part.getEditorInput())
                        .getLineOffset(methTag.startLn() - 1);

                ((AbstractTextEditor) SootPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow()
                        .getActivePage().getActiveEditor()).selectAndReveal(selOffset, 0);
            }

        } catch (PartInitException e3) {
            e3.printStackTrace();
        }

        catch (Exception e2) {
            e2.printStackTrace();
        }
    }

    public void addToGraph(Object info) {
        CallGraphInfo cgInfo = (CallGraphInfo) info;

        SootMethod center = cgInfo.getCenter();

        // find the center who is already in the graph
        CallGraphNode centerNode = getNodeForMethod(cgInfo.getCenter());
        //addToCenterList(cgInfo.getCenter());
        centerNode.setExpand(false);
        // make connections to all the children
        makeCons(cgInfo, centerNode);
    }

    /**
     * @return
     */
    public Graph getGraph() {
        return graph;
    }

    /**
     * @param graph
     */
    public void setGraph(Graph graph) {
        this.graph = graph;
    }

    /**
     * @return
     */
    public CallGraphInfo getInfo() {
        return info;
    }

    /**
     * @param info
     */
    public void setInfo(CallGraphInfo info) {
        this.info = info;
    }

    /**
     * @return
     */
    public InteractionController getController() {
        return controller;
    }

    /**
     * @param controller
     */
    public void setController(InteractionController controller) {
        this.controller = controller;
    }

    public void addToCenterList(Object obj) {
        if (getCenterList() == null) {
            setCenterList(new ArrayList());
        }
        getCenterList().add(obj);
    }

    /**
     * @return
     */
    public ArrayList getCenterList() {
        return centerList;
    }

    /**
     * @param list
     */
    public void setCenterList(ArrayList list) {
        centerList = list;
    }

}