Added viewer for CHA/CG/PA for Java/JavaScript.
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3954 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
1d4d158de3
commit
9cae049830
|
@ -0,0 +1,34 @@
|
|||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||
import com.ibm.wala.cast.js.test.Util;
|
||||
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
public class JsViewerDriver {
|
||||
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
|
||||
|
||||
if (args.length != 1){
|
||||
System.out.println("Usage: <URL of html page to analyze>");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
URL url = new URL(args[0]);
|
||||
|
||||
// computing CG + PA
|
||||
Util.setTranslatorFactory(new CAstRhinoTranslatorFactory());
|
||||
JSCFABuilder builder = Util.makeHTMLCGBuilder(url);
|
||||
CallGraph cg = builder.makeCallGraph(builder.getOptions());
|
||||
|
||||
PointerAnalysis pa = builder.getPointerAnalysis();
|
||||
|
||||
new JsViewer(cg, pa);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,8 @@ Export-Package: com.ibm.wala.cast.js,
|
|||
com.ibm.wala.cast.js.ssa,
|
||||
com.ibm.wala.cast.js.translator,
|
||||
com.ibm.wala.cast.js.types,
|
||||
com.ibm.wala.cast.js.util
|
||||
com.ibm.wala.cast.js.util,
|
||||
com.ibm.wala.cast.js.vis
|
||||
Require-Bundle: com.ibm.wala.cast,
|
||||
com.ibm.wala.core,
|
||||
com.ibm.wala.cast,
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.cast.ipa.callgraph.AstGlobalPointerKey;
|
||||
import com.ibm.wala.cast.ipa.callgraph.ObjectPropertyCatalogKey;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
|
||||
/**
|
||||
* Augments the PaPanel with: 1) global pointer keys at the root level. 2) property catalog key for instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class JsPaPanel extends PaPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MutableMapping<List<ObjectPropertyCatalogKey>> instanceKeyIdToObjectPropertyCatalogKey = MutableMapping.<List<ObjectPropertyCatalogKey>> make();
|
||||
private List<AstGlobalPointerKey> globalsPointerKeys = new ArrayList<AstGlobalPointerKey>();
|
||||
|
||||
public JsPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof ObjectPropertyCatalogKey){
|
||||
ObjectPropertyCatalogKey opck = (ObjectPropertyCatalogKey) n;
|
||||
InstanceKey instanceKey = opck.getObject();
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(instanceKey);
|
||||
mapUsingMutableMapping(instanceKeyIdToObjectPropertyCatalogKey, instanceKeyId, opck);
|
||||
} else if (n instanceof AstGlobalPointerKey){
|
||||
globalsPointerKeys.add((AstGlobalPointerKey) n);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
List<PointerKey> ret = new ArrayList<PointerKey>();
|
||||
ret.addAll(super.getPointerKeysUnderInstanceKey(ik));
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
ret.addAll(nonNullList(instanceKeyIdToObjectPropertyCatalogKey.getMappedObject(ikIndex)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String cgNodesRoot = "CGNodes";
|
||||
private String globalsRoot = "Globals";
|
||||
|
||||
@Override
|
||||
protected List<Object> getRootNodes() {
|
||||
List<Object> ret = new ArrayList<Object>(2);
|
||||
ret.add(cgNodesRoot);
|
||||
ret.add(globalsRoot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node == cgNodesRoot){
|
||||
for (int nodeId = 0 ; nodeId < cg.getNumberOfNodes(); nodeId++){
|
||||
CGNode cgNode = cg.getNode(nodeId);
|
||||
ret.add(cgNode);
|
||||
}
|
||||
} else if (node == globalsRoot){
|
||||
ret.addAll(globalsPointerKeys);
|
||||
} else {
|
||||
ret.addAll(super.getChildrenFor(node));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
import com.ibm.wala.viz.viewer.WalaViewer;
|
||||
|
||||
public class JsViewer extends WalaViewer{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public JsViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new JsPaPanel(cg, pa);
|
||||
}
|
||||
}
|
|
@ -36,4 +36,8 @@ public class ObjectPropertyCatalogKey extends AbstractPointerKey {
|
|||
public String toString() {
|
||||
return "[" + getName() + "]";
|
||||
}
|
||||
|
||||
public InstanceKey getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.ibm.wala.core.tests/src/com/ibm/wala/examples/drivers/JavaViewerDriver.java"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="1"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.examples.drivers.JavaViewerDriver"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-appClassPath ${workspace_loc}/com.ibm.wala.core.testdata/bin/JLex.jar"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.core.tests"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Xmx800M"/>
|
||||
</launchConfiguration>
|
|
@ -0,0 +1,62 @@
|
|||
package com.ibm.wala.examples.drivers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
import com.ibm.wala.util.io.CommandLine;
|
||||
import com.ibm.wala.util.io.FileProvider;
|
||||
import com.ibm.wala.viz.viewer.WalaViewer;
|
||||
|
||||
/**
|
||||
* Allows viewing the ClassHeirarcy, CallGraph and Pointer Analysis built from a given classpath.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class JavaViewerDriver {
|
||||
public static void main(String[] args) throws ClassHierarchyException, IOException, CallGraphBuilderCancelException {
|
||||
Properties p = CommandLine.parse(args);
|
||||
validateCommandLine(p);
|
||||
run(p.getProperty("appClassPath"), p.getProperty("exclusionFile", CallGraphTestUtil.REGRESSION_EXCLUSIONS));
|
||||
}
|
||||
|
||||
public static void validateCommandLine(Properties p) {
|
||||
if (p.get("appClassPath") == null) {
|
||||
throw new UnsupportedOperationException("expected command-line to include -appClassPath");
|
||||
}
|
||||
}
|
||||
|
||||
private static void run(String classPath, String exclusionFilePath) throws IOException, ClassHierarchyException, CallGraphBuilderCancelException{
|
||||
|
||||
File exclusionFile = FileProvider.getFile(exclusionFilePath);
|
||||
AnalysisScope scope = AnalysisScopeReader.makeJavaBinaryAnalysisScope(classPath, exclusionFile != null ? exclusionFile
|
||||
: new File(CallGraphTestUtil.REGRESSION_EXCLUSIONS));
|
||||
|
||||
ClassHierarchy cha = ClassHierarchy.make(scope);
|
||||
|
||||
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha);
|
||||
AnalysisOptions options = new AnalysisOptions(scope, entrypoints);
|
||||
|
||||
// //
|
||||
// build the call graph
|
||||
// //
|
||||
com.ibm.wala.ipa.callgraph.CallGraphBuilder builder = Util.makeZeroCFABuilder(options, new AnalysisCache(), cha, scope);
|
||||
CallGraph cg = builder.makeCallGraph(options, null);
|
||||
|
||||
PointerAnalysis pa = builder.getPointerAnalysis();
|
||||
new WalaViewer(cg, pa);
|
||||
|
||||
}
|
||||
}
|
|
@ -76,5 +76,6 @@ Export-Package: .,
|
|||
com.ibm.wala.util.strings,
|
||||
com.ibm.wala.util.tables,
|
||||
com.ibm.wala.util.warnings,
|
||||
com.ibm.wala.viz
|
||||
com.ibm.wala.viz,
|
||||
com.ibm.wala.viz.viewer
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
|
||||
public class CgPanel extends JSplitPane{
|
||||
|
||||
private final CallGraph cg;
|
||||
|
||||
public CgPanel(CallGraph cg) {
|
||||
this.cg = cg;
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
|
||||
final IrAndSourceViewer irViewer = new IrAndSourceViewer(cg);
|
||||
this.setRightComponent(irViewer.getComponent());
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode node = (CGNode) userObject;
|
||||
IR ir = node.getIR();
|
||||
irViewer.setIR(ir);
|
||||
} else if (userObject instanceof CallSiteReference){
|
||||
CGNode parentNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
IR ir = parentNode.getIR();
|
||||
irViewer.setIRAndPc(ir, ((CallSiteReference) userObject).getProgramCounter());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
|
||||
CGNode cgRoot = cg.getFakeRootNode();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
List<DefaultMutableTreeNode> newChilds = new ArrayList<DefaultMutableTreeNode>();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode cgNode = (CGNode) userObject;
|
||||
for (Iterator<CallSiteReference> iter = cgNode.iterateCallSites(); iter.hasNext();) {
|
||||
CallSiteReference csr = iter.next();
|
||||
newChilds.add(new DefaultMutableTreeNode(csr));
|
||||
}
|
||||
} else {
|
||||
assert userObject instanceof CallSiteReference;
|
||||
CallSiteReference csr = (CallSiteReference) userObject;
|
||||
CGNode cgNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
Set<CGNode> successors = cg.getPossibleTargets(cgNode, csr);
|
||||
for (CGNode successor : successors) {
|
||||
newChilds.add(new DefaultMutableTreeNode(successor));
|
||||
}
|
||||
}
|
||||
|
||||
for (DefaultMutableTreeNode newChild : newChilds) {
|
||||
treeNode.add(newChild);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
||||
public class ChaPanel extends JSplitPane {
|
||||
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
public ChaPanel(IClassHierarchy cha) {
|
||||
this.cha = cha;
|
||||
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
final DefaultListModel methodListModel = new DefaultListModel();
|
||||
JList methodList = new JList(methodListModel);
|
||||
this.setRightComponent(methodList);
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener(){
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
methodListModel.clear();
|
||||
for (IMethod m : klass.getDeclaredMethods()){
|
||||
methodListModel.addElement(m.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
IClass rootClass = cha.getRootClass();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootClass);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
Collection<IClass> immediateSubclasses = cha.getImmediateSubclasses(klass);
|
||||
for (IClass immediateSubclass : immediateSubclasses){
|
||||
treeNode.add(new DefaultMutableTreeNode(immediateSubclass));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
|
||||
/**
|
||||
* Renderer for the heap tree. Gives non default icons for pointer keys and instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
class DualTreeCellRenderer implements TreeCellRenderer {
|
||||
|
||||
private final DefaultTreeCellRenderer defaultTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer ikTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer pkTreeCellRenderer;
|
||||
|
||||
public DualTreeCellRenderer() {
|
||||
defaultTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
|
||||
|
||||
ikTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
ikTreeCellRenderer.setOpenIcon(createImageIcon("images/ik_open.png"));
|
||||
ikTreeCellRenderer.setClosedIcon(createImageIcon("images/ik_closed.png"));
|
||||
ikTreeCellRenderer.setLeafIcon(createImageIcon("images/ik_leaf.png"));
|
||||
|
||||
pkTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
pkTreeCellRenderer.setOpenIcon(createImageIcon("images/pk_open.png"));
|
||||
pkTreeCellRenderer.setClosedIcon(createImageIcon("images/pk_closed.png"));
|
||||
pkTreeCellRenderer.setLeafIcon(createImageIcon("images/pk_leaf.png"));
|
||||
}
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf,
|
||||
int row, boolean hasFocus) {
|
||||
TreeCellRenderer delegate = getTreeCellRenderer(value);
|
||||
return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
}
|
||||
|
||||
private TreeCellRenderer getTreeCellRenderer(Object value) {
|
||||
if (value instanceof DefaultMutableTreeNode){
|
||||
value = ((DefaultMutableTreeNode) value).getUserObject();
|
||||
}
|
||||
if (value instanceof PointerKey){
|
||||
return pkTreeCellRenderer;
|
||||
} else if (value instanceof InstanceKey){
|
||||
return ikTreeCellRenderer;
|
||||
} else {
|
||||
return defaultTreeCellRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns an ImageIcon, or null if the path was invalid. */
|
||||
protected ImageIcon createImageIcon(String path) {
|
||||
java.net.URL imgURL = DualTreeCellRenderer.class.getResource(path);
|
||||
if (imgURL != null) {
|
||||
return new ImageIcon(imgURL);
|
||||
} else {
|
||||
System.err.println("Couldn't find file: " + path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.JSplitPane;
|
||||
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.viz.viewer.IrViewer.SelectedPcListner;
|
||||
|
||||
public class IrAndSourceViewer {
|
||||
|
||||
private IrViewer irViewer;
|
||||
private SourceViewer sourceViewer;
|
||||
|
||||
private IR ir;
|
||||
|
||||
public IrAndSourceViewer(CallGraph cg) {
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
|
||||
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
irViewer = new IrViewer();
|
||||
splitPane.setLeftComponent(irViewer);
|
||||
|
||||
sourceViewer = new SourceViewer();
|
||||
splitPane.setRightComponent(sourceViewer);
|
||||
|
||||
irViewer.addSelectedPcListner(new SelectedPcListner(){
|
||||
|
||||
public void valueChanged(int pc) {
|
||||
IMethod method = ir.getMethod();
|
||||
int sourceLineNumber = IrViewer.NA;
|
||||
String sourceFileName = null;
|
||||
if (pc != IrViewer.NA){
|
||||
try{
|
||||
sourceLineNumber = method.getLineNumber(pc);
|
||||
IClassLoader loader = method.getDeclaringClass().getClassLoader();
|
||||
sourceFileName = loader.getSourceFileName(method, pc);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (sourceFileName != null){
|
||||
URL url;
|
||||
try {
|
||||
url = (new File(sourceFileName)).toURI().toURL();
|
||||
sourceViewer.setSource(url, sourceLineNumber);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
sourceViewer.removeSource();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return splitPane;
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
this.ir = ir;
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.ir = ir;
|
||||
irViewer.setIR(ir);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
public class IrViewer extends JPanel{
|
||||
private JTextField methodName;
|
||||
private DefaultListModel irLineList = new DefaultListModel();
|
||||
private JList irLines;
|
||||
|
||||
// mapping from ir viewer list line to source code line number.
|
||||
private Map<Integer, Integer> lineToPosition = null;
|
||||
|
||||
// Mapping for pc to line in the ir viewer list.
|
||||
private Map<Integer, Integer> pcToLine = null;
|
||||
private Map<Integer, Integer> lineToPc = null;
|
||||
|
||||
public interface SelectedPcListner{
|
||||
void valueChanged(int pc);
|
||||
}
|
||||
Set<SelectedPcListner> selectedPcListners = new HashSet<SelectedPcListner>();
|
||||
|
||||
public IrViewer() {
|
||||
super(new BorderLayout());
|
||||
irLines = new JList(irLineList);
|
||||
methodName = new JTextField("IR");
|
||||
this.add(methodName, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
|
||||
|
||||
|
||||
irLines.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
int index = irLines.getSelectedIndex();
|
||||
Integer pc = lineToPc.get(index);
|
||||
if (pc == null) {
|
||||
pc = NA;
|
||||
}
|
||||
for (SelectedPcListner selectedPcListner : selectedPcListners) {
|
||||
selectedPcListner.valueChanged(pc);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.lineToPosition = HashMapFactory.make();
|
||||
this.pcToLine = HashMapFactory.make();
|
||||
this.lineToPc = HashMapFactory.make();
|
||||
|
||||
int firstLineWithPosition = NA;
|
||||
|
||||
try {
|
||||
methodName.setText("IR: " + ir.getMethod());
|
||||
irLineList.clear();
|
||||
BufferedReader br = new BufferedReader(new StringReader(ir.toString()));
|
||||
int lineNum = 0;
|
||||
int position = NA;
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
irLineList.addElement(line);
|
||||
int pc = parseIrLine(line);
|
||||
if (pc != NA) {
|
||||
IMethod m = ir.getMethod();
|
||||
int newPosition = m.getLineNumber(pc);
|
||||
if (newPosition != -1) {
|
||||
position = newPosition;
|
||||
}
|
||||
lineToPc.put(lineNum, pc);
|
||||
pcToLine.put(pc, lineNum);
|
||||
|
||||
if (position != NA) {
|
||||
lineToPosition.put(lineNum, position);
|
||||
if (firstLineWithPosition == NA){
|
||||
firstLineWithPosition = lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineNum++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ???
|
||||
assert false;
|
||||
}
|
||||
|
||||
// focusing on the first line with position
|
||||
if (firstLineWithPosition != NA){
|
||||
irLines.setSelectedIndex(firstLineWithPosition);
|
||||
irLines.ensureIndexIsVisible(firstLineWithPosition);
|
||||
}
|
||||
}
|
||||
|
||||
static final int NA = -1;
|
||||
|
||||
private int parseIrLine(String line) {
|
||||
int firstSpace = line.indexOf(' ');
|
||||
if (firstSpace > 0) {
|
||||
String pcString = line.substring(0, firstSpace);
|
||||
try {
|
||||
return Integer.parseInt(pcString);
|
||||
} catch (NumberFormatException e) {
|
||||
return NA;
|
||||
}
|
||||
} else {
|
||||
return NA;
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedPcListner(SelectedPcListner selectedPcListner) {
|
||||
this.selectedPcListners.add(selectedPcListner);
|
||||
}
|
||||
|
||||
public void setPc(int pc){
|
||||
Integer lineNum = pcToLine.get(pc);
|
||||
if (lineNum != null){
|
||||
irLines.ensureIndexIsVisible(lineNum);
|
||||
irLines.setSelectedIndex(lineNum);
|
||||
}
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
setIR(ir);
|
||||
if (pc != NA){
|
||||
setPc(pc);
|
||||
} else {
|
||||
int curSelectedIndex = irLines.getSelectedIndex();
|
||||
irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
|
||||
/**
|
||||
* Panel for showing the Pointer Analysis results. Shows the heap graph on the left, and the ir viewer on the right. Sets the IR of
|
||||
* and pc according to the chosen pointer/instance key when possible (e.g., allocation side for NormalAllocationInNode instance
|
||||
* keys. Can be customized for clients that use different their own pointer / instance keys (see JsPaPanel)
|
||||
*
|
||||
* Note the two steps initialization require (calling init())
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class PaPanel extends JSplitPane {
|
||||
|
||||
protected final PointerAnalysis pa;
|
||||
protected final CallGraph cg;
|
||||
|
||||
private JTextField fullName;
|
||||
|
||||
private IrAndSourceViewer irViewer;
|
||||
|
||||
private MutableMapping<List<LocalPointerKey>> cgNodeIdToLocalPointers = MutableMapping.<List<LocalPointerKey>> make();
|
||||
private MutableMapping<List<ReturnValueKey>> cgNodeIdToReturnValue = MutableMapping.<List<ReturnValueKey>> make();
|
||||
private MutableMapping<List<InstanceFieldPointerKey>> instanceKeyIdToInstanceFieldPointers = MutableMapping.<List<InstanceFieldPointerKey>> make();
|
||||
|
||||
|
||||
public PaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(JSplitPane.HORIZONTAL_SPLIT);
|
||||
|
||||
this.pa = pa;
|
||||
this.cg = cg;
|
||||
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Two steps initialization is required here is our deriver can choose the roots for the heap tree.
|
||||
*/
|
||||
public void init() {
|
||||
this.setDividerLocation(250);
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
for (Object rootChildNode : getRootNodes()){
|
||||
DefaultMutableTreeNode n = new DefaultMutableTreeNode(rootChildNode);
|
||||
root.add(n);
|
||||
expandNodeRec(n, 1);
|
||||
}
|
||||
|
||||
JTree heapTree = new JTree(root);
|
||||
|
||||
heapTree.setCellRenderer(new DualTreeCellRenderer());
|
||||
|
||||
this.setLeftComponent(new JScrollPane(heapTree));
|
||||
JPanel rightPanel = new JPanel(new BorderLayout());
|
||||
this.setRightComponent(rightPanel);
|
||||
fullName = new JTextField("");
|
||||
rightPanel.add(fullName, BorderLayout.PAGE_START);
|
||||
irViewer = new IrAndSourceViewer(cg);
|
||||
rightPanel.add(irViewer.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
heapTree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNodeRec(lastNode, 2);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
}
|
||||
});
|
||||
|
||||
heapTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
fullName.setText(userObject.toString());
|
||||
if (userObject instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) userObject;
|
||||
IR ir = lpk.getNode().getIR();
|
||||
SSAInstruction def = lpk.getNode().getDU().getDef(lpk.getValueNumber());
|
||||
int pc = IrViewer.NA;
|
||||
if (def != null){
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
SSAInstruction instruction = instructions[i];
|
||||
if (def == instruction){
|
||||
pc = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof InstanceFieldPointerKey){
|
||||
InstanceKey ik = ((InstanceFieldPointerKey) userObject).getInstanceKey();
|
||||
if (ik instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) ik;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
} else if (userObject instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) userObject;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof CGNode){
|
||||
irViewer.setIR(((CGNode)userObject).getIR());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){ // considering only roots of the heap graph.
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) n;
|
||||
int nodeId = lpk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToLocalPointers, nodeId, lpk);
|
||||
} else if (n instanceof ReturnValueKey){
|
||||
ReturnValueKey rvk = (ReturnValueKey) n;
|
||||
int nodeId = rvk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToReturnValue, nodeId, rvk);
|
||||
} else if (n instanceof InstanceFieldPointerKey){
|
||||
InstanceFieldPointerKey ifpk = (InstanceFieldPointerKey) n;
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(ifpk.getInstanceKey());
|
||||
mapUsingMutableMapping(instanceKeyIdToInstanceFieldPointers, instanceKeyId, ifpk);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override if you want different roots for your heap tree.
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getRootNodes(){
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
for (CGNode n : cg){
|
||||
ret.add(n);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* expands the given "treeNode" "rec" levels.
|
||||
* @param treeNode
|
||||
* @param rec
|
||||
*/
|
||||
private void expandNodeRec(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0){ // may be expandable.
|
||||
List<Object> children = getChildrenFor(treeNode.getUserObject());
|
||||
for (Object child : children){
|
||||
treeNode.add(new DefaultMutableTreeNode(child));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < treeNode.getChildCount(); i++){
|
||||
TreeNode child = treeNode.getChildAt(i);
|
||||
expandNodeRec((DefaultMutableTreeNode)child, rec-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for filling the tree dynamically. Override and handle your own nodes / different links.
|
||||
* @param node
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node instanceof InstanceKey){
|
||||
ret.addAll(getPointerKeysUnderInstanceKey((InstanceKey) node));
|
||||
} else if (node instanceof PointerKey){
|
||||
for (InstanceKey ik : pa.getPointsToSet((PointerKey) node)){
|
||||
ret.add(ik);
|
||||
}
|
||||
} else if (node instanceof CGNode){
|
||||
int nodeId = ((CGNode) node).getGraphNodeId();
|
||||
ret.addAll(nonNullList(cgNodeIdToLocalPointers.getMappedObject(nodeId)));
|
||||
ret.addAll(nonNullList(cgNodeIdToReturnValue.getMappedObject(nodeId)));
|
||||
} else {
|
||||
assert false : "Unhandled Node : " + node;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of pointer keys that should be presented below an instance key in the heap tree. Override if you have special
|
||||
* pointer keys (not just for fields)
|
||||
*
|
||||
* @param ik
|
||||
* @return
|
||||
*/
|
||||
protected List<? extends PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
List<? extends PointerKey> ret;
|
||||
if (ikIndex <= instanceKeyIdToInstanceFieldPointers.getMaximumIndex()){
|
||||
ret = nonNullList(instanceKeyIdToInstanceFieldPointers.getMappedObject(ikIndex));
|
||||
} else {
|
||||
ret = Collections.emptyList();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method for mutable mapping. map[index] U= o
|
||||
* @param <T>
|
||||
* @param map
|
||||
* @param index
|
||||
* @param o
|
||||
*/
|
||||
protected static <T> void mapUsingMutableMapping(MutableMapping<List<T>> map, int index, T o){
|
||||
List<T> set;
|
||||
if (index <= map.getMaximumIndex()){
|
||||
set = map.getMappedObject(index);
|
||||
} else {
|
||||
set = null;
|
||||
}
|
||||
if (null == set){
|
||||
set = new ArrayList<T>();
|
||||
map.put(index, set);
|
||||
}
|
||||
set.add(o);
|
||||
}
|
||||
|
||||
protected <T> List<T> nonNullList(List<T> l){
|
||||
if (null == l){
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class SourceViewer extends JPanel{
|
||||
private URL sourceURL;
|
||||
private JTextField sourceCodeLocation;
|
||||
private DefaultListModel sourceCodeLinesList = new DefaultListModel();
|
||||
private JList sourceCodeLines;
|
||||
|
||||
public SourceViewer() {
|
||||
super(new BorderLayout());
|
||||
sourceURL = null;
|
||||
sourceCodeLines = new JList(sourceCodeLinesList);
|
||||
sourceCodeLocation = new JTextField("Source code");
|
||||
this.add(sourceCodeLocation, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(sourceCodeLines), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setSource(URL url) {
|
||||
setSource(url, IrViewer.NA);
|
||||
}
|
||||
|
||||
public void setSource(URL url, int sourceLine) {
|
||||
sourceCodeLocation.setText("Source code: " + url);
|
||||
loadSource(url);
|
||||
if (sourceLine != IrViewer.NA){
|
||||
sourceCodeLines.ensureIndexIsVisible(sourceLine-1);
|
||||
sourceCodeLines.setSelectedIndex(sourceLine-1);
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadSource(URL url) {
|
||||
if (url == null) {
|
||||
if (sourceURL != null) {
|
||||
// easing the current code.
|
||||
sourceCodeLinesList.clear();
|
||||
}
|
||||
return false; // nothing to load
|
||||
} else {
|
||||
if (url.equals(sourceURL)) {
|
||||
return true; // already loaded
|
||||
} else {
|
||||
sourceCodeLinesList.clear();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sourceCodeLinesList.addElement(line.replaceAll("\t", " "));
|
||||
}
|
||||
br.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not load source at " + url);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSelection() {
|
||||
int curSelectedIndex = sourceCodeLines.getSelectedIndex();
|
||||
sourceCodeLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
|
||||
public void removeSource() {
|
||||
sourceURL = null;
|
||||
sourceCodeLocation = new JTextField("Source code");
|
||||
sourceCodeLinesList.clear();
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
|
||||
/**
|
||||
* Viewer for ClassHeirarcy, CallGraph and Pointer Analysis results.
|
||||
* A driver for example can be found in com.ibm.wala.js.rhino.vis.JsViewer.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class WalaViewer extends JFrame {
|
||||
|
||||
protected static final String DefaultMutableTreeNode = null;
|
||||
|
||||
|
||||
public WalaViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
setNativeLookAndFeel();
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
tabbedPane.add("Call Graph", new CgPanel(cg));
|
||||
tabbedPane.add("Class Hierarchy", new ChaPanel(cg.getClassHierarchy()));
|
||||
PaPanel paPanel = createPaPanel(cg, pa);
|
||||
paPanel.init();
|
||||
tabbedPane.add("Pointer Analysis", paPanel);
|
||||
|
||||
setSize(600, 800);
|
||||
setExtendedState(MAXIMIZED_BOTH);
|
||||
addWindowListener(new ExitListener());
|
||||
|
||||
this.setTitle("Wala viewer");
|
||||
|
||||
add(tabbedPane);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new PaPanel(cg, pa);
|
||||
}
|
||||
|
||||
public static void setNativeLookAndFeel() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExitListener extends WindowAdapter {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 529 B |
Binary file not shown.
After Width: | Height: | Size: 445 B |
Binary file not shown.
After Width: | Height: | Size: 621 B |
Binary file not shown.
After Width: | Height: | Size: 581 B |
Binary file not shown.
After Width: | Height: | Size: 607 B |
Binary file not shown.
After Width: | Height: | Size: 581 B |
Loading…
Reference in New Issue