Skip to content

Commit c00c9aa

Browse files
authored
Merge pull request #8 from sse-labs/development
BuildTypeHierarchy
2 parents eeaa517 + 45c1075 commit c00c9aa

File tree

7 files changed

+416
-2
lines changed

7 files changed

+416
-2
lines changed

Diff for: src/main/java/org/tudo/sse/Main.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
import org.apache.logging.log4j.LogManager;
44
import org.apache.logging.log4j.Logger;
55
import org.tudo.sse.model.Artifact;
6-
import org.tudo.sse.resolution.PomResolutionException;
6+
import org.tudo.sse.model.ArtifactIdent;
7+
import org.tudo.sse.model.jar.ClassFileNode;
8+
import org.tudo.sse.model.jar.FoundInfoNode;
9+
import org.tudo.sse.resolution.*;
710
import org.tudo.sse.utils.GAUtils;
811

912
import java.io.IOException;
1013
import java.net.URISyntaxException;
1114
import java.util.List;
15+
import java.util.Map;
1216

1317
public class Main {
1418

Diff for: src/main/java/org/tudo/sse/model/Artifact.java

+145-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
package org.tudo.sse.model;
22

3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
5+
import org.tudo.sse.Main;
36
import org.tudo.sse.model.index.IndexInformation;
4-
import org.tudo.sse.model.jar.JarInformation;
7+
import org.tudo.sse.model.jar.*;
58
import org.tudo.sse.model.pom.PomInformation;
9+
import org.tudo.sse.resolution.JarResolutionException;
10+
import org.tudo.sse.resolution.JarResolver;
11+
12+
import java.util.ArrayList;
13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.Map;
616

717
/**
818
* This class holds all the artifact information. For each artifact index, jar, and pom information can be defined.
@@ -13,6 +23,8 @@ public class Artifact {
1323
* The identifier object for the artifact.
1424
*/
1525
public final ArtifactIdent ident;
26+
public static final Logger log = LogManager.getLogger(Artifact.class);
27+
1628
/**
1729
* A secondary identifier, for if its pom information has been moved on the maven central repository.
1830
*/
@@ -75,4 +87,136 @@ public void setJarInformation(JarInformation jarInformation) {
7587
this.jarInformation = jarInformation;
7688
}
7789

90+
91+
public Map<String, ClassFileNode> buildTypeStructure() {
92+
Map<String, ClassFileNode> roots = new HashMap<>();
93+
roots.put("java/lang/Object", new NotFoundNode(new ObjType(0, "java/lang/Object", "java/lang")));
94+
if(jarInformation != null) {
95+
Map<String, List<ClassFile>> packages = jarInformation.getPackages();
96+
Map<String, Artifact> depArts = new HashMap<>();
97+
98+
if(pomInformation != null) {
99+
JarResolver resolver = new JarResolver();
100+
for(Artifact artifact : pomInformation.getEffectiveTransitiveDependencies()) {
101+
try {
102+
artifact.setJarInformation(resolver.parseJar(artifact.getIdent()).getJarInformation());
103+
depArts.put(artifact.getIdent().getGroupID() + ":" + artifact.getIdent().getArtifactID(), artifact);
104+
} catch (JarResolutionException e) {
105+
log.error(e);
106+
}
107+
}
108+
}
109+
110+
for(Map.Entry<String, List<ClassFile>> classes : packages.entrySet()) {
111+
for(ClassFile clase : classes.getValue()) {
112+
resolveNode(roots, clase, packages, depArts);
113+
}
114+
}
115+
}
116+
return roots;
117+
}
118+
119+
private ClassFileNode resolveNode(Map<String, ClassFileNode> root, ClassFile clase, Map<String, List<ClassFile>> packages, Map<String, Artifact> depArts) {
120+
ClassFileNode node = new FoundInfoNode(clase.getAccessFlags(), clase.getThistype(), clase.getVersion());
121+
122+
if(clase.getSuperType() != null) {
123+
resolveSuperClass(root, node, clase, packages, depArts);
124+
}
125+
126+
if(!clase.getInterfaceTypes().isEmpty()) {
127+
resolveInterfaces(root, node, clase, packages, depArts);
128+
}
129+
130+
return node;
131+
}
132+
133+
private void resolveSuperClass(Map<String, ClassFileNode> roots, ClassFileNode node, ClassFile clase, Map<String, List<ClassFile>> packages, Map<String, Artifact> depArts) {
134+
String packName = clase.getSuperType().getPackageName();
135+
136+
//Check if the superclass can be found in the root map
137+
if(roots.containsKey(clase.getSuperType().getFqn())) {
138+
node.setSuperClass(roots.get(clase.getSuperType().getFqn()));
139+
roots.get(clase.getSuperType().getFqn()).addChild(node);
140+
}
141+
//Check if
142+
else if(packages.containsKey(packName)) {
143+
List<ClassFile> toLookThrough = packages.get(packName);
144+
for(ClassFile cls : toLookThrough) {
145+
if(cls.getThistype().getFqn().equals(clase.getSuperType().getFqn())) {
146+
node.setSuperClass(resolveNode(roots, cls, packages, depArts));
147+
node.getSuperClass().addChild(node);
148+
break;
149+
}
150+
}
151+
} else {
152+
boolean found = false;
153+
154+
for(Map.Entry<String, Artifact> entry : depArts.entrySet()) {
155+
if(entry.getValue().getJarInformation().getPackages().containsKey(packName)) {
156+
for(ClassFile depClass : entry.getValue().getJarInformation().getPackages().get(packName)) {
157+
if(depClass.getThistype().getFqn().equals(clase.getSuperType().getFqn())) {
158+
found = true;
159+
node.setSuperClass(resolveNode(roots, depClass, entry.getValue().getJarInformation().getPackages(), depArts));
160+
node.getSuperClass().addChild(node);
161+
break;
162+
}
163+
}
164+
if(found) {
165+
break;
166+
}
167+
}
168+
}
169+
170+
//add a new root to the map
171+
if(!found) {
172+
node.setSuperClass(new NotFoundNode(clase.getSuperType()));
173+
node.getSuperClass().addChild(node);
174+
roots.put(node.getSuperClass().getThistype().getFqn(), node.getSuperClass());
175+
}
176+
}
177+
}
178+
179+
private void resolveInterfaces(Map<String, ClassFileNode> roots, ClassFileNode node, ClassFile clase, Map<String, List<ClassFile>> packages, Map<String, Artifact> depArts) {
180+
for(ObjType itfe : clase.getInterfaceTypes()) {
181+
String packName = itfe.getPackageName();
182+
183+
if(packages.containsKey(packName)) {
184+
List<ClassFile> toLookThrough = packages.get(packName);
185+
for(ClassFile cls : toLookThrough) {
186+
if(cls.getThistype().getFqn().equals(itfe.getFqn())) {
187+
ClassFileNode resolved = resolveNode(roots, cls, packages, depArts);
188+
resolved.addChild(node);
189+
((FoundInfoNode) node).addInterfaceNode(resolved);
190+
break;
191+
}
192+
}
193+
} else {
194+
boolean found = false;
195+
196+
for(Map.Entry<String, Artifact> entry : depArts.entrySet()) {
197+
if(entry.getValue().getJarInformation().getPackages().containsKey(packName)) {
198+
for(ClassFile depClass : entry.getValue().getJarInformation().getPackages().get(packName)) {
199+
if(depClass.getThistype().getFqn().equals(itfe.getFqn())) {
200+
found = true;
201+
ClassFileNode resolved = resolveNode(roots, depClass, entry.getValue().getJarInformation().getPackages(), depArts);
202+
resolved.addChild(node);
203+
((FoundInfoNode) node).addInterfaceNode(resolved);
204+
break;
205+
}
206+
}
207+
if(found) {
208+
break;
209+
}
210+
}
211+
}
212+
213+
if(!found) {
214+
ClassFileNode notFound = new NotFoundNode(itfe);
215+
((FoundInfoNode) node).addInterfaceNode(notFound);
216+
notFound.addChild(node);
217+
}
218+
}
219+
}
220+
}
221+
78222
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.tudo.sse.model.jar;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class ClassFileNode {
7+
private final ObjType thistype;
8+
private ClassFileNode superclass;
9+
private List<ClassFileNode> children;
10+
11+
public ClassFileNode(ObjType thistype) {
12+
this.thistype = thistype;
13+
children = new ArrayList<>();
14+
}
15+
16+
public ClassFileNode getSuperClass() {
17+
return superclass;
18+
}
19+
20+
public void setSuperClass(ClassFileNode superclass) {
21+
this.superclass = superclass;
22+
}
23+
24+
public ObjType getThistype() {
25+
return thistype;
26+
}
27+
28+
public List<ClassFileNode> getChildren() {
29+
return children;
30+
}
31+
32+
public void addChild(ClassFileNode child) {
33+
children.add(child);
34+
}
35+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.tudo.sse.model.jar;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class FoundInfoNode extends ClassFileNode {
7+
private final int accessFlags;
8+
private final long version;
9+
private List<ClassFileNode> interfaceNodes;
10+
11+
12+
public FoundInfoNode(int accessFlags, ObjType thisType, long version) {
13+
super(thisType);
14+
this.accessFlags = accessFlags;
15+
this.version = version;
16+
interfaceNodes = new ArrayList<>();
17+
}
18+
19+
public int getAccessFlags() {
20+
return accessFlags;
21+
}
22+
23+
public long getVersion() {
24+
return version;
25+
}
26+
27+
public List<ClassFileNode> getInterfaceNodes() {
28+
return interfaceNodes;
29+
}
30+
31+
public void addInterfaceNode(ClassFileNode interfaceNode) {
32+
interfaceNodes.add(interfaceNode);
33+
}
34+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.tudo.sse.model.jar;
2+
3+
public class NotFoundNode extends ClassFileNode {
4+
5+
public NotFoundNode(ObjType thistype) {
6+
super(thistype);
7+
}
8+
}
+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package org.tudo.sse.model;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.reflect.TypeToken;
5+
import org.apache.logging.log4j.LogManager;
6+
import org.apache.logging.log4j.Logger;
7+
import org.junit.jupiter.api.Test;
8+
import org.tudo.sse.ArtifactFactory;
9+
import org.tudo.sse.model.jar.ClassFileNode;
10+
import org.tudo.sse.model.jar.FoundInfoNode;
11+
import org.tudo.sse.resolution.*;
12+
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
import java.io.InputStreamReader;
16+
import java.io.Reader;
17+
import java.util.List;
18+
import java.util.Map;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
22+
23+
class TypeStructureTest {
24+
25+
JarResolver resolver = new JarResolver();
26+
PomResolver pomResolver = new PomResolver(true);
27+
Map<String, Object> json;
28+
Gson gson = new Gson();
29+
30+
private static final Logger log = LogManager.getLogger(TypeStructureTest.class);
31+
32+
{
33+
InputStream resource = this.getClass().getClassLoader().getResourceAsStream("TypeStructure.json");
34+
assert resource != null;
35+
Reader targetReader = new InputStreamReader(resource);
36+
json = gson.fromJson(targetReader, new TypeToken<Map<String, Object>>() {}.getType());
37+
}
38+
39+
@Test
40+
void buildTypeStructure() {
41+
42+
Artifact jarArt1;
43+
ArtifactIdent ident = new ArtifactIdent("org.springframework", "spring-web", "6.1.11");
44+
Artifact jarArt2;
45+
jarArt2 = ArtifactFactory.getArtifact(ident);
46+
try {
47+
jarArt1 = resolver.parseJar(new ArtifactIdent("org.bouncycastle", "bcpg-lts8on", "2.73.6"));
48+
jarArt2 = resolver.parseJar(ident);
49+
pomResolver.resolveArtifact(ident);
50+
} catch (JarResolutionException | PomResolutionException | FileNotFoundException | IOException e) {
51+
throw new RuntimeException(e);
52+
}
53+
54+
ClassFileNode results1 = jarArt1.buildTypeStructure().get("java/lang/Object");
55+
Map<String, Object> expected1 = (Map<String, Object>) json.get("artifact1");
56+
57+
singleChild(results1, (Map<String, Object>) expected1.get("test1"));
58+
interfacesCheck(results1, (Map<String, Object>) expected1.get("test2"));
59+
interfacesCheck(results1, (Map<String, Object>) expected1.get("test3"));
60+
61+
Map<String, ClassFileNode> results2 = jarArt2.buildTypeStructure();
62+
Map<String, Object> expected2 = (Map<String, Object>) json.get("artifact2");
63+
64+
65+
multipleChildren(results2.get("reactor/core/observability/DefaultSignalListener"), (Map<String, Object>) expected2.get("test1"));
66+
multiLevelChild(results2.get("java/lang/RuntimeException"), (Map<String, Object>) expected2.get("test2"));
67+
interfacesCheck(results2.get("java/lang/Object"), (Map<String, Object>) expected2.get("test3"));
68+
69+
}
70+
71+
ClassFileNode findNode(ClassFileNode root, String toFind) {
72+
73+
for(ClassFileNode cur : root.getChildren()) {
74+
if(cur.getThistype().getFqn().equals(toFind)) {
75+
return cur;
76+
}
77+
}
78+
79+
throw new RuntimeException("Didn't find expected node");
80+
}
81+
82+
void singleChild(ClassFileNode root, Map<String, Object> expected) {
83+
ClassFileNode toTest = findNode(root, (String) expected.get("name"));
84+
Map<String, Object> child = (Map<String, Object>) expected.get("child");
85+
assert(toTest.getChildren().get(0).getThistype().getFqn().equals((String) child.get("name")));
86+
}
87+
88+
void interfacesCheck(ClassFileNode root, Map<String, Object> expected) {
89+
ClassFileNode toTest = findNode(root, (String) expected.get("name"));
90+
91+
List<Map<String, String>> expectedInterfaces = (List<Map<String, String>>) expected.get("interfaces");
92+
List<ClassFileNode> interfaces = ((FoundInfoNode) toTest).getInterfaceNodes();
93+
94+
assertEquals(interfaces.size(), expectedInterfaces.size());
95+
96+
for(int i = 0; i < interfaces.size(); i++) {
97+
assertEquals(interfaces.get(i).getThistype().getFqn(), expectedInterfaces.get(i).get("name"));
98+
assertEquals(((FoundInfoNode) interfaces.get(i)).getSuperClass().getThistype().getFqn(), expectedInterfaces.get(i).get("super"));
99+
}
100+
}
101+
102+
void multipleChildren(ClassFileNode root, Map<String, Object> expected) {
103+
assertEquals(root.getThistype().getFqn(), expected.get("name"));
104+
105+
List<Map<String, String>> children = (List<Map<String, String>>) expected.get("children");
106+
assertEquals(root.getChildren().size(), children.size());
107+
108+
for(int i = 0; i < root.getChildren().size(); i++) {
109+
assertEquals(children.get(i).get("name"), root.getChildren().get(i).getThistype().getFqn());
110+
}
111+
log.info("Got here");
112+
}
113+
114+
void multiLevelChild(ClassFileNode root, Map<String, Object> expected) {
115+
assertEquals(root.getThistype().getFqn(), expected.get("name"));
116+
List<Map<String, Object>> children = (List<Map<String, Object>>) expected.get("children");
117+
assertEquals(root.getChildren().get(0).getThistype().getFqn(), children.get(0).get("name"));
118+
List<Map<String, String>> secondLevel = (List<Map<String, String>>) children.get(0).get("children");
119+
assertEquals(root.getChildren().get(0).getChildren().get(0).getThistype().getFqn(), secondLevel.get(0).get("name"));
120+
}
121+
122+
}

0 commit comments

Comments
 (0)