/** * */ package soottocfg.cfg; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.jgrapht.DirectedGraph; import org.jgrapht.graph.DefaultDirectedGraph; import org.jgrapht.graph.DefaultEdge; import soottocfg.cfg.method.CfgBlock; import soottocfg.cfg.method.Method; import soottocfg.cfg.statement.CallStatement; import soottocfg.cfg.statement.Statement; import soottocfg.cfg.type.Type; import soottocfg.cfg.variable.ClassVariable; import soottocfg.cfg.variable.Variable; /** * @author schaef * */ public class Program { private final Map<String, Variable> globalVariables = new LinkedHashMap<String, Variable>(); private final Map<String, Method> methods = new LinkedHashMap<String, Method>(); private Method entryPoint; private DirectedGraph<Method, DefaultEdge> callGraph; private final DirectedGraph<ClassVariable, DefaultEdge> typeGraph = new DefaultDirectedGraph<ClassVariable, DefaultEdge>( DefaultEdge.class);; public void addClassVariable(ClassVariable cv) { if (!this.typeGraph.containsVertex(cv)) { this.typeGraph.addVertex(cv); for (ClassVariable parent : cv.getParents()) { addClassVariable(parent); this.typeGraph.addEdge(parent, cv); } } } public Set<ClassVariable> getClassVariables() { return this.typeGraph.vertexSet(); } public ClassVariable findClassVariableByName(final String name) { for (ClassVariable cv : this.typeGraph.vertexSet()) { if (name.equals(cv.getName())) { return cv; } } return null; } public DirectedGraph<ClassVariable, DefaultEdge> getTypeGraph() { return this.typeGraph; } public Variable lookupGlobalVariable(String varName, Type t) { if (!this.globalVariables.containsKey(varName)) { this.globalVariables.put(varName, new Variable(varName, t, true, true)); } return this.globalVariables.get(varName); } public List<Variable> getGlobalVariables() { return new LinkedList<Variable>(this.globalVariables.values()); } public Map<String, Variable> getGlobalsMap() { return this.globalVariables; } public Method lookupMethod(String methodSignature) { return methods.get(methodSignature); } public void addMethod(Method m) { // set the callGraph to null because it has to be recomputed. callGraph = null; this.methods.put(m.getMethodName(), m); } public void removeMethods(Collection<Method> methods) { callGraph = null; for (Method m : methods) { this.methods.remove(m.getMethodName()); } } public void setEntryPoint(Method entry) { entryPoint = entry; } public Method getEntryPoint() { return entryPoint; } public Method[] getMethods() { return methods.values().toArray(new Method[methods.size()]); } public DirectedGraph<Method, DefaultEdge> getCallGraph() { if (callGraph == null) { computeCallGraph(); } return callGraph; } private void computeCallGraph() { callGraph = new DefaultDirectedGraph<Method, DefaultEdge>(DefaultEdge.class); for (Method m : methods.values()) { callGraph.addVertex(m); } for (Method m : methods.values()) { for (CfgBlock b : m.vertexSet()) { for (Statement s : b.getStatements()) { if (s instanceof CallStatement) { Method callee = ((CallStatement) s).getCallTarget(); if (!callGraph.containsEdge(m, callee)) { callGraph.addEdge(m, callee); } } } } } } public String toString() { StringBuilder prog = new StringBuilder(); // global variables for (Variable g : globalVariables.values()) { prog.append(g + ";\n"); } prog.append("\n"); List<Method> sortedMethods = new LinkedList<Method>(methods.values()); Collections.sort(sortedMethods, new Comparator<Method>() { @Override public int compare(Method o1, Method o2) { return o1.getMethodName().compareTo(o2.getMethodName()); } }); // methods for (Method m : sortedMethods) { prog.append(m + "\n"); } return prog.toString(); } }