001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2004 Jennifer Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package ca.mcgill.sable.soot.interaction;
021:
022: import soot.AbstractTrap;
023: import soot.toolkits.graph.interaction.*;
024: import java.util.*;
025:
026: import org.eclipse.ui.*;
027:
028: import ca.mcgill.sable.soot.launching.*;
029: import org.eclipse.swt.widgets.*;
030: import org.eclipse.jface.dialogs.*;
031: import org.eclipse.swt.*;
032: import ca.mcgill.sable.soot.*;
033: import ca.mcgill.sable.soot.callgraph.*;
034: import ca.mcgill.sable.soot.cfg.*;
035: import soot.jimple.toolkits.annotation.callgraph.*;
036: import soot.*;
037:
038: public class InteractionController implements IInteractionController,
039: IInteractionListener {
040:
041: private ArrayList listeners;
042: private Thread sootThread;
043: private boolean available;
044: private InteractionEvent event;
045: private Display display;
046: private SootRunner parent;
047: private soot.toolkits.graph.DirectedGraph currentGraph;
048: private ModelCreator mc;
049: private CallGraphGenerator generator;
050:
051: public InteractionController() {
052: }
053:
054: public void addListener(IInteractionListener listener) {
055: if (listeners == null) {
056: listeners = new ArrayList();
057: }
058: listeners.add(listener);
059: }
060:
061: public void removeListener(IInteractionListener listener) {
062: if (listeners == null)
063: return;
064: if (listeners.contains(listener)) {
065: listeners.remove(listener);
066: }
067: }
068:
069: public void handleEvent() {
070: if (getEvent().type() == IInteractionConstants.NEW_ANALYSIS) {
071: handleNewAnalysisEvent(event.info());
072:
073: } else if (getEvent().type() == IInteractionConstants.NEW_CFG) {
074: handleCfgEvent(getEvent().info());
075: // process and update graph
076: } else if (getEvent().type() == IInteractionConstants.NEW_BEFORE_ANALYSIS_INFO) {
077:
078: handleBeforeFlowEvent(getEvent().info());
079: // process and update graph ui
080: } else if (getEvent().type() == IInteractionConstants.NEW_AFTER_ANALYSIS_INFO) {
081: handleAfterFlowEvent(getEvent().info());
082: // process and update graph ui
083: } else if (getEvent().type() == IInteractionConstants.NEW_BEFORE_ANALYSIS_INFO_AUTO) {
084:
085: handleBeforeFlowEventAuto(getEvent().info());
086: // process and update graph ui
087: } else if (getEvent().type() == IInteractionConstants.NEW_AFTER_ANALYSIS_INFO_AUTO) {
088: handleAfterFlowEventAuto(getEvent().info());
089: // process and update graph ui
090: } else if (getEvent().type() == IInteractionConstants.DONE) {
091: // remove controller and listener from soot
092: waitForContinue();
093: } else if (getEvent().type() == IInteractionConstants.STOP_AT_NODE) {
094: handleStopAtNodeEvent(getEvent().info());
095: } else if (getEvent().type() == IInteractionConstants.CLEARTO) {
096: handleClearEvent(getEvent().info());
097: } else if (getEvent().type() == IInteractionConstants.REPLACE) {
098: handleReplaceEvent(getEvent().info());
099: }
100:
101: else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_START) {
102: handleCallGraphStartEvent(getEvent().info());
103: } else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_NEXT_METHOD) {
104: handleCallGraphNextMethodEvent(getEvent().info());
105: }
106:
107: else if (getEvent().type() == IInteractionConstants.CALL_GRAPH_PART) {
108: handleCallGraphPartEvent(getEvent().info());
109: }
110: }
111:
112: private Shell getShell() {
113: IWorkbenchWindow window = SootPlugin.getDefault()
114: .getWorkbench().getActiveWorkbenchWindow();
115: final Shell[] shell = new Shell[1];
116: getDisplay().syncExec(new Runnable() {
117: public void run() {
118: shell[0] = getDisplay().getDefault().getActiveShell();
119: }
120: });
121: return shell[0];
122: }
123:
124: private void handleNewAnalysisEvent(Object info) {
125:
126: SootPlugin.getDefault().setDataKeeper(new DataKeeper(this ));
127: InteractionHandler.v().setInteractThisAnalysis(true);
128:
129: }
130:
131: private void handleCfgEvent(Object info) {
132:
133: soot.toolkits.graph.DirectedGraph cfg = (soot.toolkits.graph.DirectedGraph) info;
134: setCurrentGraph(cfg);
135: setMc(new ModelCreator());
136: getMc().setSootGraph(getCurrentGraph());
137: String editorName = "CFG Editor";
138:
139: if (cfg instanceof soot.toolkits.graph.UnitGraph) {
140: soot.Body body = ((soot.toolkits.graph.UnitGraph) cfg)
141: .getBody();
142: editorName = body.getMethod().getDeclaringClass().getName()
143: + "." + body.getMethod().getName();
144: }
145: mc.setEditorName(editorName);
146:
147: final ModelCreator mc = getMc();
148:
149: getDisplay().syncExec(new Runnable() {
150: public void run() {
151: mc.displayModel();
152: }
153: });
154: InteractionHandler.v().autoCon(false);
155:
156: waitForContinue();
157:
158: }
159:
160: private void waitForContinue() {
161: soot.toolkits.graph.interaction.InteractionHandler.v()
162: .waitForContinue();
163: }
164:
165: private void handleBeforeFlowEvent(Object info) {
166: handleBeforeEvent(info);
167: waitForContinue();
168:
169: }
170:
171: private void handleBeforeEvent(Object info) {
172: FlowInfo fi = (FlowInfo) info;
173: SootPlugin.getDefault().getDataKeeper().addFlowInfo(info);
174:
175: Iterator it = getCurrentGraph().iterator();
176:
177: final Shell myShell = getShell();
178: final FlowInfo flowBefore = fi;
179: final ModelCreator mc = getMc();
180: getDisplay().syncExec(new Runnable() {
181: public void run() {
182: mc.updateNode(flowBefore);
183: };
184: });
185: }
186:
187: private void handleBeforeFlowEventAuto(Object info) {
188: handleBeforeEvent(info);
189:
190: }
191:
192: private void handleAfterFlowEvent(Object fi) {
193: handleAfterEvent(fi);
194: waitForContinue();
195:
196: }
197:
198: private void handleAfterEvent(Object fi) {
199: final Shell myShell = getShell();
200: SootPlugin.getDefault().getDataKeeper().addFlowInfo(fi);
201:
202: final FlowInfo flowAfter = (FlowInfo) fi;
203: final ModelCreator mc = getMc();
204:
205: getDisplay().syncExec(new Runnable() {
206: public void run() {
207: mc.updateNode(flowAfter);
208: };
209: });
210:
211: }
212:
213: private void handleAfterFlowEventAuto(Object fi) {
214: handleAfterEvent(fi);
215: }
216:
217: private void handleStopAtNodeEvent(Object info) {
218: // highlight box being waited on
219: InteractionHandler.v().autoCon(false);
220:
221: final soot.Unit stopUnit = (soot.Unit) info;
222: final ModelCreator mc = getMc();
223: getDisplay().syncExec(new Runnable() {
224: public void run() {
225: mc.highlightNode(stopUnit);
226: };
227: });
228: // then wait
229: waitForContinue();
230: }
231:
232: private void handleClearEvent(Object info) {
233: final FlowInfo fi = (FlowInfo) info;
234: final ModelCreator mc = getMc();
235:
236: getDisplay().syncExec(new Runnable() {
237: public void run() {
238: mc.updateNode(fi);
239: };
240: });
241: }
242:
243: private void handleReplaceEvent(Object info) {
244: final FlowInfo fi = (FlowInfo) info;
245: final ModelCreator mc = getMc();
246:
247: getDisplay().syncExec(new Runnable() {
248: public void run() {
249: mc.updateNode(fi);
250: };
251: });
252: }
253:
254: private void handleCallGraphStartEvent(Object info) {
255: if (getGenerator() == null) {
256: setGenerator(new CallGraphGenerator());
257: }
258: getGenerator().setInfo((CallGraphInfo) info);
259: getGenerator().setController(this );
260: final CallGraphGenerator cgg = getGenerator();
261: getDisplay().syncExec(new Runnable() {
262: public void run() {
263: cgg.run();
264: }
265: });
266: waitForContinue();
267: }
268:
269: private void handleCallGraphNextMethodEvent(Object info) {
270: SootMethod meth = (SootMethod) info;
271: InteractionHandler.v().setNextMethod(meth);
272: InteractionHandler.v().setInteractionCon();
273: }
274:
275: private void handleCallGraphPartEvent(Object info) {
276: final CallGraphGenerator cgg = getGenerator();
277: final Object cgInfo = info;
278: getDisplay().asyncExec(new Runnable() {
279: public void run() {
280: cgg.addToGraph(cgInfo);
281: }
282: });
283: waitForContinue();
284: }
285:
286: /**
287: * @return
288: */
289: public Thread getSootThread() {
290: return sootThread;
291: }
292:
293: /**
294: * @param thread
295: */
296: public void setSootThread(Thread thread) {
297: sootThread = thread;
298: }
299:
300: /**
301: * @return
302: */
303: public boolean isAvailable() {
304: return available;
305: }
306:
307: /**
308: * @return
309: */
310: public InteractionEvent getEvent() {
311: return event;
312: }
313:
314: /**
315: * @param event
316: */
317: public void setEvent(InteractionEvent event) {
318: this .event = event;
319: }
320:
321: /**
322: * @return
323: */
324: public Display getDisplay() {
325: return display;
326: }
327:
328: /**
329: * @param display
330: */
331: public void setDisplay(Display display) {
332: this .display = display;
333: }
334:
335: /**
336: * @return
337: */
338: public SootRunner getParent() {
339: return parent;
340: }
341:
342: /**
343: * @param runner
344: */
345: public void setParent(SootRunner runner) {
346: parent = runner;
347: }
348:
349: /**
350: * @return
351: */
352: public soot.toolkits.graph.DirectedGraph getCurrentGraph() {
353: return currentGraph;
354: }
355:
356: /**
357: * @return
358: */
359: public ArrayList getListeners() {
360: return listeners;
361: }
362:
363: /**
364: * @param graph
365: */
366: public void setCurrentGraph(soot.toolkits.graph.DirectedGraph graph) {
367: currentGraph = graph;
368: }
369:
370: /**
371: * @param list
372: */
373: public void setListeners(ArrayList list) {
374: listeners = list;
375: }
376:
377: /**
378: * @return
379: */
380: public ModelCreator getMc() {
381: return mc;
382: }
383:
384: /**
385: * @param creator
386: */
387: public void setMc(ModelCreator creator) {
388: mc = creator;
389: }
390:
391: /**
392: * @return
393: */
394: public CallGraphGenerator getGenerator() {
395: return generator;
396: }
397:
398: /**
399: * @param generator
400: */
401: public void setGenerator(CallGraphGenerator generator) {
402: this.generator = generator;
403: }
404:
405: }
|