package tools.icfg; import java.util.LinkedList; import java.util.List; import neo4j.batchInserter.ImportedNodeListener; import neo4j.batchInserter.Neo4JBatchInserter; import org.neo4j.graphdb.DynamicRelationshipType; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.index.IndexHits; import org.neo4j.unsafe.batchinsert.BatchRelationship; import databaseNodes.EdgeTypes; public class ICFGListener extends ImportedNodeListener { CallResolver resolver = new CallResolver(); @Override public void visitNode(Long callNodeId) { List<Long> arguments = getArgumentsByCallId(callNodeId); if (arguments == null) return; IndexHits<Long> dstIds = resolver.resolveByCallId(callNodeId); if (dstIds == null) return; connectArgumentsToDestinations(callNodeId, arguments, dstIds); } private List<Long> getArgumentsByCallId(Long callNodeId) { long argumentListId = getArgumentListByCallId(callNodeId); if (argumentListId == -1) return null; return getArgsFromArgList(argumentListId); } private void connectArgumentsToDestinations(Long callNodeId, List<Long> arguments, IndexHits<Long> dstIds) { for (Long dst : dstIds) { List<Long> parameters = getParametersByFunctionId(dst); if (parameters == null) continue; addArgParamEdges(callNodeId, arguments, parameters); } } private List<Long> getParametersByFunctionId(Long dst) { String query = "type:\"ParameterList\" AND functionId:\"" + dst + "\""; IndexHits<Long> hits = Neo4JBatchInserter.queryIndex(query); if (hits == null) return null; if (hits.size() != 1) throw (new RuntimeException( "Warning: Parameterlist not found or more than one.")); Long parameterListId = hits.next(); List<Long> params = getParametersFromList(parameterListId); return getIdentifiersFromParams(params); } private void addArgParamEdges(Long callNodeId, List<Long> arguments, List<Long> parameters) { if (parameters.size() != arguments.size()) return; RelationshipType rel = DynamicRelationshipType .withName(EdgeTypes.IS_ARG); for (int i = 0; i < arguments.size(); i++) Neo4JBatchInserter.addRelationship(arguments.get(i), parameters.get(i), rel, null); } private List<Long> getArgsFromArgList(long argumentListId) { return getChildrenByNodeId(argumentListId); } private long getArgumentListByCallId(Long callNodeId) { Iterable<BatchRelationship> rels = Neo4JBatchInserter .getRelationships(callNodeId); for (BatchRelationship rel : rels) { long childId = rel.getEndNode(); if (childId == callNodeId) continue; String childType = (String) Neo4JBatchInserter.getNodeProperties( childId).get("type"); if (childType.equals("ArgumentList")) return childId; } return -1; } private List<Long> getIdentifiersFromParams(List<Long> params) { List<Long> retval = new LinkedList<Long>(); for (Long paramId : params) { Iterable<BatchRelationship> rels = Neo4JBatchInserter .getRelationships(paramId); for (BatchRelationship rel : rels) { if (rel.getEndNode() == paramId) continue; long identifierNode = rel.getEndNode(); Object type = Neo4JBatchInserter.getNodeProperties( identifierNode).get("type"); if (type.equals("Identifier")) { retval.add(identifierNode); break; } } } return retval; } private List<Long> getParametersFromList(Long parameterListId) { return getChildrenByNodeId(parameterListId); } private List<Long> getChildrenByNodeId(Long nodeId) { List<Long> retval = new LinkedList<Long>(); Iterable<BatchRelationship> rels = Neo4JBatchInserter .getRelationships(nodeId); for (BatchRelationship rel : rels) { if (rel.getEndNode() == nodeId) continue; long childId = rel.getEndNode(); retval.add(childId); } return retval; } }