/* 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.interaction;
import soot.AbstractTrap;
import soot.toolkits.graph.interaction.*;
import java.util.*;
import org.eclipse.ui.*;
import ca.mcgill.sable.soot.launching.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.jface.dialogs.*;
import org.eclipse.swt.*;
import ca.mcgill.sable.soot.*;
import ca.mcgill.sable.soot.callgraph.*;
import ca.mcgill.sable.soot.cfg.*;
import soot.jimple.toolkits.annotation.callgraph.*;
import soot.*;
public class InteractionController implements IInteractionController, IInteractionListener {
private ArrayList listeners;
private Thread sootThread;
private boolean available;
private InteractionEvent event;
private Display display;
private SootRunner parent;
private soot.toolkits.graph.DirectedGraph currentGraph;
private ModelCreator mc;
private CallGraphGenerator generator;
public InteractionController() {
}
public void addListener(IInteractionListener listener){
if (listeners == null){
listeners = new ArrayList();
}
listeners.add(listener);
}
public void removeListener(IInteractionListener listener){
if (listeners == null) return;
if (listeners.contains(listener)) {
listeners.remove(listener);
}
}
public void handleEvent(){
if (getEvent().type() == IInteractionConstants.NEW_ANALYSIS){
handleNewAnalysisEvent(event.info());
}
else if (getEvent().type() == IInteractionConstants.NEW_CFG){
handleCfgEvent(getEvent().info());
// process and update graph
}
else if (getEvent().type() == IInteractionConstants.NEW_BEFORE_ANALYSIS_INFO){
handleBeforeFlowEvent(getEvent().info());
// process and update graph ui
}
else if (getEvent().type() == IInteractionConstants.NEW_AFTER_ANALYSIS_INFO){
handleAfterFlowEvent(getEvent().info());
// process and update graph ui
}
else if (getEvent().type() == IInteractionConstants.NEW_BEFORE_ANALYSIS_INFO_AUTO){
handleBeforeFlowEventAuto(getEvent().info());
// process and update graph ui
}
else if (getEvent().type() == IInteractionConstants.NEW_AFTER_ANALYSIS_INFO_AUTO){
handleAfterFlowEventAuto(getEvent().info());
// process and update graph ui
}
else if (getEvent().type() == IInteractionConstants.DONE){
// remove controller and listener from soot
waitForContinue();
}
else if (getEvent().type() == IInteractionConstants.STOP_AT_NODE){
handleStopAtNodeEvent(getEvent().info());
}
else if (getEvent().type() == IInteractionConstants.CLEARTO){
handleClearEvent(getEvent().info());
}
else if (getEvent().type() == IInteractionConstants.REPLACE){
handleReplaceEvent(getEvent().info());
}
else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_START){
handleCallGraphStartEvent(getEvent().info());
}
else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_NEXT_METHOD){
handleCallGraphNextMethodEvent(getEvent().info());
}
else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_PART){
handleCallGraphPartEvent(getEvent().info());
}
}
private Shell getShell(){
IWorkbenchWindow window = SootPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
final Shell [] shell = new Shell [1];
getDisplay().syncExec(new Runnable(){
public void run(){
shell[0] = getDisplay().getDefault().getActiveShell();
}
});
return shell[0];
}
private void handleNewAnalysisEvent(Object info){
SootPlugin.getDefault().setDataKeeper(new DataKeeper(this));
InteractionHandler.v().setInteractThisAnalysis(true);
}
private void handleCfgEvent(Object info){
soot.toolkits.graph.DirectedGraph cfg = (soot.toolkits.graph.DirectedGraph)info;
setCurrentGraph(cfg);
setMc(new ModelCreator());
getMc().setSootGraph(getCurrentGraph());
String editorName = "CFG Editor";
if (cfg instanceof soot.toolkits.graph.UnitGraph){
soot.Body body = ((soot.toolkits.graph.UnitGraph)cfg).getBody();
editorName = body.getMethod().getDeclaringClass().getName()+"."+body.getMethod().getName();
}
mc.setEditorName(editorName);
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable(){
public void run(){
mc.displayModel();
}
});
InteractionHandler.v().autoCon(false);
waitForContinue();
}
private void waitForContinue(){
soot.toolkits.graph.interaction.InteractionHandler.v().waitForContinue();
}
private void handleBeforeFlowEvent(Object info){
handleBeforeEvent(info);
waitForContinue();
}
private void handleBeforeEvent(Object info){
FlowInfo fi = (FlowInfo)info;
SootPlugin.getDefault().getDataKeeper().addFlowInfo(info);
Iterator it = getCurrentGraph().iterator();
final Shell myShell = getShell();
final FlowInfo flowBefore = fi;
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable() {
public void run(){
mc.updateNode(flowBefore);
};
});
}
private void handleBeforeFlowEventAuto(Object info){
handleBeforeEvent(info);
}
private void handleAfterFlowEvent(Object fi){
handleAfterEvent(fi);
waitForContinue();
}
private void handleAfterEvent(Object fi){
final Shell myShell = getShell();
SootPlugin.getDefault().getDataKeeper().addFlowInfo(fi);
final FlowInfo flowAfter = (FlowInfo)fi;
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable() {
public void run(){
mc.updateNode(flowAfter);
};
});
}
private void handleAfterFlowEventAuto(Object fi){
handleAfterEvent(fi);
}
private void handleStopAtNodeEvent(Object info){
// highlight box being waited on
InteractionHandler.v().autoCon(false);
final soot.Unit stopUnit = (soot.Unit)info;
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable() {
public void run(){
mc.highlightNode(stopUnit);
};
});
// then wait
waitForContinue();
}
private void handleClearEvent(Object info){
final FlowInfo fi = (FlowInfo)info;
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable() {
public void run(){
mc.updateNode(fi);
};
});
}
private void handleReplaceEvent(Object info){
final FlowInfo fi = (FlowInfo)info;
final ModelCreator mc = getMc();
getDisplay().syncExec(new Runnable() {
public void run(){
mc.updateNode(fi);
};
});
}
private void handleCallGraphStartEvent(Object info){
if (getGenerator() == null){
setGenerator(new CallGraphGenerator());
}
getGenerator().setInfo((CallGraphInfo)info);
getGenerator().setController(this);
final CallGraphGenerator cgg = getGenerator();
getDisplay().syncExec(new Runnable(){
public void run(){
cgg.run();
}
});
waitForContinue();
}
private void handleCallGraphNextMethodEvent(Object info){
SootMethod meth = (SootMethod)info;
InteractionHandler.v().setNextMethod(meth);
InteractionHandler.v().setInteractionCon();
}
private void handleCallGraphPartEvent(Object info){
final CallGraphGenerator cgg = getGenerator();
final Object cgInfo = info;
getDisplay().asyncExec(new Runnable(){
public void run(){
cgg.addToGraph(cgInfo);
}
});
waitForContinue();
}
/**
* @return
*/
public Thread getSootThread() {
return sootThread;
}
/**
* @param thread
*/
public void setSootThread(Thread thread) {
sootThread = thread;
}
/**
* @return
*/
public boolean isAvailable() {
return available;
}
/**
* @return
*/
public InteractionEvent getEvent() {
return event;
}
/**
* @param event
*/
public void setEvent(InteractionEvent event) {
this.event = event;
}
/**
* @return
*/
public Display getDisplay() {
return display;
}
/**
* @param display
*/
public void setDisplay(Display display) {
this.display = display;
}
/**
* @return
*/
public SootRunner getParent() {
return parent;
}
/**
* @param runner
*/
public void setParent(SootRunner runner) {
parent = runner;
}
/**
* @return
*/
public soot.toolkits.graph.DirectedGraph getCurrentGraph() {
return currentGraph;
}
/**
* @return
*/
public ArrayList getListeners() {
return listeners;
}
/**
* @param graph
*/
public void setCurrentGraph(soot.toolkits.graph.DirectedGraph graph) {
currentGraph = graph;
}
/**
* @param list
*/
public void setListeners(ArrayList list) {
listeners = list;
}
/**
* @return
*/
public ModelCreator getMc() {
return mc;
}
/**
* @param creator
*/
public void setMc(ModelCreator creator) {
mc = creator;
}
/**
* @return
*/
public CallGraphGenerator getGenerator() {
return generator;
}
/**
* @param generator
*/
public void setGenerator(CallGraphGenerator generator) {
this.generator = generator;
}
}