Skip to content

Commit 98f9d39

Browse files
committed
slim json
Signed-off-by: Rahul Krishna <[email protected]>
1 parent b94873b commit 98f9d39

File tree

11 files changed

+276
-96
lines changed

11 files changed

+276
-96
lines changed

src/main/java/com/ibm/cldk/CodeAnalyzer.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,8 @@ private static void analyze() throws Exception {
174174
build = build == null ? "auto" : build;
175175
// Is noBuild is true, we will not build the project
176176
build = noBuild ? null : build;
177-
String sdgAsJSONString = SystemDependencyGraph.construct(input, dependencies, build);
178-
JsonElement sdgAsJSONElement = gson.fromJson(sdgAsJSONString, JsonElement.class);
179-
JsonObject sdgAsJSONObject = sdgAsJSONElement.getAsJsonObject();
180-
JsonElement edges = sdgAsJSONObject.get("edges");
181-
182-
// We don't really need these fields, so we'll remove it.
183-
sdgAsJSONObject.remove("nodes");
184-
sdgAsJSONObject.remove("creator");
185-
sdgAsJSONObject.remove("version");
186-
// Remove the 'edges' element and move the list of edges up one level
187-
combinedJsonObject.add("system_dependency_graph", edges);
177+
List<Dependency> sdgEdges = SystemDependencyGraph.construct(input, dependencies, build);
178+
combinedJsonObject.add("system_dependency_graph", gson.toJsonTree(sdgEdges));
188179
}
189180
}
190181
// Cleanup library dependencies directory

src/main/java/com/ibm/cldk/SymbolTable.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseR
194194
typeNode.setCallableDeclarations(typeDecl.findAll(CallableDeclaration.class).stream()
195195
.filter(c -> c.getParentNode().isPresent() && c.getParentNode().get() == typeDecl)
196196
.map(meth -> {
197-
Pair<String, Callable> callableDeclaration = processCallableDeclaration(meth, fieldNames, typeName);
197+
Pair<String, Callable> callableDeclaration = processCallableDeclaration(meth, fieldNames, typeName, parseResult.getStorage().map(s -> s.getPath().toString()).orElse("<in-memory>"));
198198
declaredMethodsAndConstructors.put(typeName, callableDeclaration.getLeft(), callableDeclaration.getRight());
199199
return callableDeclaration;
200200
}).collect(Collectors.toMap(p -> p.getLeft(), p -> p.getRight())));
@@ -249,9 +249,12 @@ private static ParameterInCallable processParameterDeclaration(Parameter paramDe
249249
*/
250250
@SuppressWarnings("unchecked")
251251
private static Pair<String, Callable> processCallableDeclaration(CallableDeclaration callableDecl,
252-
List<String> classFields, String typeName) {
252+
List<String> classFields, String typeName, String filePath) {
253253
Callable callableNode = new Callable();
254254

255+
// Set file path
256+
callableNode.setFilePath(filePath);
257+
255258
// add callable signature
256259
callableNode.setSignature(callableDecl.getSignature().asString());
257260

src/main/java/com/ibm/cldk/SystemDependencyGraph.java

Lines changed: 93 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import com.ibm.cldk.entities.AbstractGraphEdge;
1717
import com.ibm.cldk.entities.CallEdge;
18-
import com.ibm.cldk.entities.Callable;
18+
import com.ibm.cldk.entities.CallableVertex;
1919
import com.ibm.cldk.entities.SystemDepEdge;
2020
import com.ibm.cldk.utils.AnalysisUtils;
2121
import com.ibm.cldk.utils.Log;
@@ -40,20 +40,60 @@
4040
import com.ibm.wala.util.graph.Graph;
4141
import com.ibm.wala.util.graph.GraphSlicer;
4242
import com.ibm.wala.util.graph.traverse.DFS;
43+
import lombok.Data;
44+
import lombok.EqualsAndHashCode;
4345
import org.apache.commons.io.output.NullOutputStream;
44-
import org.apache.commons.lang3.tuple.Pair;
4546
import org.jgrapht.graph.DefaultDirectedGraph;
4647
import org.jgrapht.nio.json.JSONExporter;
4748

4849
import java.io.IOException;
4950
import java.io.PrintStream;
50-
import java.io.StringWriter;
5151
import java.util.*;
5252
import java.util.function.BiFunction;
5353
import java.util.function.Supplier;
54-
55-
import static com.ibm.cldk.CodeAnalyzer.gson;
56-
import static com.ibm.cldk.utils.AnalysisUtils.*;
54+
import java.util.stream.Collectors;
55+
56+
import static com.ibm.cldk.utils.AnalysisUtils.createAndPutNewCallableInSymbolTable;
57+
import static com.ibm.cldk.utils.AnalysisUtils.getCallableFromSymbolTable;
58+
59+
60+
@Data
61+
abstract class Dependency {
62+
public CallableVertex source;
63+
public CallableVertex target;
64+
}
65+
66+
@Data
67+
@EqualsAndHashCode(callSuper = true)
68+
class SDGDependency extends Dependency {
69+
public String sourceKind;
70+
public String destinationKind;
71+
public String type;
72+
public String weight;
73+
74+
public SDGDependency(CallableVertex source, CallableVertex target, SystemDepEdge edge) {
75+
super.source = source;
76+
super.target = target;
77+
this.sourceKind = edge.getSourceKind();
78+
this.destinationKind = edge.getDestinationKind();
79+
this.type = edge.getType();
80+
this.weight = String.valueOf(edge.getWeight());
81+
}
82+
}
83+
84+
@Data
85+
@EqualsAndHashCode(callSuper = true)
86+
class CallDependency extends Dependency {
87+
public String type;
88+
public String weight;
89+
90+
public CallDependency(CallableVertex source, CallableVertex target, AbstractGraphEdge edge) {
91+
this.source = source;
92+
this.target = target;
93+
this.type = edge.toString();
94+
this.weight = String.valueOf(edge.getWeight());
95+
}
96+
}
5797

5898
/**
5999
* The type Sdg 2 json.
@@ -66,19 +106,10 @@ public class SystemDependencyGraph {
66106
* @return the graph exporter
67107
*/
68108

69-
70-
private static JSONExporter<Pair<String, Callable>, AbstractGraphEdge> getGraphExporter() {
71-
JSONExporter<Pair<String, Callable>, AbstractGraphEdge> exporter = new JSONExporter<>(
72-
pair -> {
73-
Map <String, String> vertex = new HashMap<>();
74-
vertex.put("type_declaration", pair.getLeft());
75-
vertex.put("file_path", pair.getRight().getFilePath());
76-
vertex.put("signature", pair.getRight().getSignature());
77-
vertex.put("callable_declaration", pair.getRight().getDeclaration());
78-
return gson.toJson(vertex);
79-
}
80-
);
109+
private static JSONExporter<CallableVertex, AbstractGraphEdge> getGraphExporter() {
110+
JSONExporter<CallableVertex, AbstractGraphEdge> exporter = new JSONExporter<>();
81111
exporter.setEdgeAttributeProvider(AbstractGraphEdge::getAttributes);
112+
exporter.setVertexAttributeProvider(CallableVertex::getAttributes);
82113
return exporter;
83114
}
84115

@@ -91,12 +122,12 @@ private static JSONExporter<Pair<String, Callable>, AbstractGraphEdge> getGraphE
91122
* @param edgeLabels
92123
* @return
93124
*/
94-
private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buildGraph(
125+
private static org.jgrapht.Graph<CallableVertex, AbstractGraphEdge> buildGraph(
95126
Supplier<Iterator<Statement>> entryPoints,
96127
Graph<Statement> sdg, CallGraph callGraph,
97128
BiFunction<Statement, Statement, String> edgeLabels) {
98129

99-
org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> graph = new DefaultDirectedGraph<>(
130+
org.jgrapht.Graph<CallableVertex, AbstractGraphEdge> graph = new DefaultDirectedGraph<>(
100131
AbstractGraphEdge.class);
101132

102133
// We'll use forward and backward search on the DFS to identify which CFG nodes
@@ -131,21 +162,22 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
131162
&& !p.getNode().getMethod().equals(s.getNode().getMethod())) {
132163

133164
// Add the source nodes to the graph as vertices
134-
Pair<String, Callable> source = Optional.ofNullable(getCallableFromSymbolTable(p.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getNode().getMethod()));
135-
graph.addVertex(source);
136-
165+
Map<String, String> source = Optional.ofNullable(getCallableFromSymbolTable(p.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getNode().getMethod()));
137166
// Add the target nodes to the graph as vertices
138-
Pair<String, Callable> target = Optional.ofNullable(getCallableFromSymbolTable(s.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(s.getNode().getMethod()));
139-
graph.addVertex(target);
140-
141-
String edgeType = edgeLabels.apply(p, s);
142-
SystemDepEdge graphEdge = new SystemDepEdge(p, s, edgeType);
143-
SystemDepEdge cgEdge = (SystemDepEdge) graph.getEdge(source, target);
144-
if (source.getRight() != null && target.getRight() != null) {
167+
Map<String, String> target = Optional.ofNullable(getCallableFromSymbolTable(s.getNode().getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(s.getNode().getMethod()));
168+
169+
if (source != null && target != null) {
170+
CallableVertex source_vertex = new CallableVertex(source);
171+
CallableVertex target_vertex = new CallableVertex(target);
172+
graph.addVertex(source_vertex);
173+
graph.addVertex(target_vertex);
174+
String edgeType = edgeLabels.apply(p, s);
175+
SystemDepEdge graphEdge = new SystemDepEdge(p, s, edgeType);
176+
SystemDepEdge cgEdge = (SystemDepEdge) graph.getEdge(source_vertex, target_vertex);
145177
if (cgEdge == null || !cgEdge.equals(graphEdge)) {
146178
graph.addEdge(
147-
source,
148-
target,
179+
source_vertex,
180+
target_vertex,
149181
graphEdge);
150182
} else {
151183
graphEdge.incrementWeight();
@@ -164,21 +196,22 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
164196
.forEach(o -> {
165197

166198
// Add the source nodes to the graph as vertices
167-
Pair<String, Callable> source = Optional.ofNullable(getCallableFromSymbolTable(p.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getMethod()));
168-
graph.addVertex(source);
199+
Map<String, String> source = Optional.ofNullable(getCallableFromSymbolTable(p.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(p.getMethod()));
200+
CallableVertex source_vertex = new CallableVertex(source);
169201

170202
// Add the target nodes to the graph as vertices
171-
Pair<String, Callable> target = Optional.ofNullable(getCallableFromSymbolTable(o.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(o.getMethod()));
172-
graph.addVertex(target);
173-
174-
if (!source.equals(target) && source.getRight() != null && target.getRight() != null) {
203+
Map<String, String> target = Optional.ofNullable(getCallableFromSymbolTable(o.getMethod())).orElseGet(() -> createAndPutNewCallableInSymbolTable(o.getMethod()));
204+
CallableVertex target_vertex = new CallableVertex(target);
175205

206+
if (!source.equals(target) && target != null) {
176207
// Get the edge between the source and the target
177-
AbstractGraphEdge cgEdge = graph.getEdge(source, target);
208+
graph.addVertex(source_vertex);
209+
graph.addVertex(target_vertex);
210+
AbstractGraphEdge cgEdge = graph.getEdge(source_vertex, target_vertex);
178211
if (cgEdge instanceof CallEdge) {
179212
((CallEdge) cgEdge).incrementWeight();
180213
} else {
181-
graph.addEdge(source, target, new CallEdge());
214+
graph.addEdge(source_vertex, target_vertex, new CallEdge());
182215
}
183216
}
184217
});
@@ -193,15 +226,15 @@ private static org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> buil
193226
*
194227
* @param input the input
195228
* @param dependencies the dependencies
196-
* @param build The build options
229+
* @param build The build options
197230
* @return A List of triples containing the source, destination, and edge type
198231
* @throws IOException the io exception
199232
* @throws ClassHierarchyException the class hierarchy exception
200233
* @throws IllegalArgumentException the illegal argument exception
201234
* @throws CallGraphBuilderCancelException the call graph builder cancel
202235
* exception
203236
*/
204-
public static String construct(
237+
public static List<Dependency> construct(
205238
String input, String dependencies, String build)
206239
throws IOException, ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException {
207240

@@ -244,12 +277,7 @@ public static String construct(
244277
+ Math.ceil((double) (System.currentTimeMillis() - start_time) / 1000) + " seconds.");
245278

246279
// set cyclomatic complexity for callables in the symbol table
247-
callGraph.forEach(cgNode -> {
248-
Callable callable = getCallableFromSymbolTable(cgNode.getMethod()).getRight();
249-
if (callable != null) {
250-
callable.setCyclomaticComplexity(getCyclomaticComplexity(cgNode.getIR()));
251-
}
252-
});
280+
AnalysisUtils.setCyclomaticComplexity(callGraph);
253281

254282
// Build SDG graph
255283
Log.info("Building System Dependency Graph.");
@@ -267,22 +295,31 @@ public static String construct(
267295
.getDeclaringClass()
268296
.getClassLoader()
269297
.getReference()
270-
.equals(ClassLoaderReference.Application)));
298+
.equals(ClassLoaderReference.Application))
299+
);
271300

272301
// A supplier to get entries
273302
Supplier<Iterator<Statement>> sdgEntryPointsSupplier = () -> callGraph.getEntrypointNodes().stream()
274303
.map(n -> (Statement) new MethodEntryStatement(n)).iterator();
275304

276-
org.jgrapht.Graph<Pair<String, Callable>, AbstractGraphEdge> sdgGraph = buildGraph(
305+
org.jgrapht.Graph<CallableVertex, AbstractGraphEdge> sdgGraph = buildGraph(
277306
sdgEntryPointsSupplier,
278307
prunedGraph, callGraph,
279-
(p, s) -> String.valueOf(sdg.getEdgeLabels(p, s).iterator().next()));
280-
281-
JSONExporter<Pair<String, Callable>, AbstractGraphEdge> graphExporter = getGraphExporter();
308+
(p, s) -> String.valueOf(sdg.getEdgeLabels(p, s).iterator().next())
309+
);
282310

283-
StringWriter sdgWriter = new StringWriter();
284-
graphExporter.exportGraph(sdgGraph, sdgWriter);
311+
List<Dependency> edges = sdgGraph.edgeSet().stream()
312+
.map(abstractGraphEdge -> {
313+
CallableVertex source = sdgGraph.getEdgeSource(abstractGraphEdge);
314+
CallableVertex target = sdgGraph.getEdgeTarget(abstractGraphEdge);
315+
if (abstractGraphEdge instanceof CallEdge) {
316+
return new CallDependency(source, target, abstractGraphEdge);
317+
} else {
318+
return new SDGDependency(source, target, (SystemDepEdge) abstractGraphEdge);
319+
}
320+
})
321+
.collect(Collectors.toList());
285322

286-
return sdgWriter.toString();
323+
return edges;
287324
}
288325
}

src/main/java/com/ibm/cldk/entities/AbstractGraphEdge.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,34 @@
1818
import com.ibm.wala.shrike.shrikeCT.InvalidClassFileException;
1919
import com.ibm.wala.ssa.IR;
2020
import com.ibm.wala.ssa.SSAInstruction;
21+
import lombok.Getter;
2122
import org.jgrapht.nio.Attribute;
22-
2323
import java.io.Serializable;
2424
import java.util.Map;
2525

26+
import static com.ibm.cldk.CodeAnalyzer.gson;
27+
2628
/**
2729
* The type Abstract graph edge.
2830
*/
31+
@Getter
2932
public abstract class AbstractGraphEdge implements Serializable {
3033
/**
3134
* The Context.
35+
* -- GETTER --
36+
* Gets context.
37+
*
38+
* @return the context
39+
3240
*/
3341
public final String context;
3442
/**
3543
* The Weight.
44+
* -- GETTER --
45+
* Gets weight.
46+
*
47+
* @return the weight
48+
3649
*/
3750
public Integer weight = 1;
3851

@@ -59,15 +72,6 @@ public void incrementWeight() {
5972
this.weight += 1;
6073
}
6174

62-
/**
63-
* Gets context.
64-
*
65-
* @return the context
66-
*/
67-
public String getContext() {
68-
return this.context;
69-
}
70-
7175
/**
7276
* Gets id.
7377
*
@@ -77,15 +81,6 @@ public Integer getId() {
7781
return this.hashCode();
7882
}
7983

80-
/**
81-
* Gets weight.
82-
*
83-
* @return the weight
84-
*/
85-
public Integer getWeight() {
86-
return this.weight;
87-
}
88-
8984
/**
9085
* Gets statement position.
9186
*
@@ -112,10 +107,17 @@ Integer getStatementPosition(Statement statement) {
112107
return pos;
113108
}
114109

110+
@Override
111+
public String toString() {
112+
return gson.toJson(this);
113+
}
114+
115115
/**
116116
* Gets attributes.
117117
*
118118
* @return the attributes
119119
*/
120120
public abstract Map<String, Attribute> getAttributes();
121+
122+
public abstract Map<String, String> getAttributesMap();
121123
}

0 commit comments

Comments
 (0)