-
Notifications
You must be signed in to change notification settings - Fork 43
/
LibClassWriter.java
124 lines (114 loc) · 3.71 KB
/
LibClassWriter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package me.nov.cafebabe.utils.asm;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import me.nov.cafebabe.loading.Loader;
import me.nov.cafebabe.translations.Translations;
public class LibClassWriter extends ClassWriter {
private Map<String, ClassNode> classes;
private ParentUtils util;
private Map<String, String> knownCommons;
public LibClassWriter(int flags, Map<String, ClassNode> classes, Map<String, ClassNode> libraries,
Map<String, String> knownCommons) {
super(flags);
this.classes = new HashMap<>(classes);
this.util = new ParentUtils(classes);
if (libraries != null) {
classes.putAll(libraries);
}
this.knownCommons = knownCommons;
}
@Override
protected String getCommonSuperClass(String type1, String type2) {
if (knownCommons.containsKey(type1 + ":" + type2)) {
return knownCommons.get(type1 + ":" + type2);
}
if (type1.length() <= 1 || type2.length() <= 1) {
return "java/lang/Object";
}
if (type1.equals("java/lang/Object") || type2.equals("java/lang/Object")) {
return "java/lang/Object";
}
try {
ClassNode cn1 = get(type1);
ClassNode cn2 = get(type2);
if (cn1 == null || cn2 == null) {
System.err.println((cn1 == null ? (cn2 == null ? (type1 + " and " + type2) : type1) : type2)
+ " not found. Check your classpath!");
try {
return super.getCommonSuperClass(type1, type2);
} catch (Exception e) {
}
return "java/lang/Object";
}
ClassNode common = findCommonParent(cn1, cn2);
if (common == null) {
try {
System.err.println("Couldn't get common superclass of the classes " + type1 + " " + type2);
return super.getCommonSuperClass(type1, type2);
} catch (Exception e) {
}
return "java/lang/Object";
}
return common.name;
} catch (Exception e) {
System.err
.println("Couldn't find out common superclass of the classes " + type1 + " " + type2 + ", asking user!");
JFrame dummy = new JFrame();
dummy.setVisible(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
dummy.setLocation(screenSize.width / 2, screenSize.height / 2);
dummy.setAlwaysOnTop(true);
String superclass = JOptionPane.showInputDialog(dummy,
Translations.get("Please enter a common super class of those classes:") + " " + type1 + " " + type2,
"java/lang/Object");
dummy.dispose();
if (superclass == null || superclass.isEmpty()) {
return "java/lang/Object";
}
knownCommons.put(type1 + ":" + type2, superclass.trim());
return superclass.trim();
}
}
public ClassNode findCommonParent(ClassNode cn1, ClassNode cn2) {
if (cn1.name.equals(cn2.name)) {
return cn1;
}
if (util.isAssignableFrom(cn1, cn2)) {
return cn1;
}
if (util.isAssignableFrom(cn2, cn1)) {
return cn2;
}
if (Access.isInterface(cn1.access) || Access.isInterface(cn2.access) || cn1.superName == null
|| cn1.superName == null) {
return get("java/lang/Object");
} else {
do {
cn1 = get(cn1.superName);
} while (cn1.superName != null && !util.isAssignableFrom(cn1, cn2));
return cn1;
}
}
private ClassNode get(String name) {
if (classes.containsKey(name)) {
return classes.get(name);
}
try {
ClassNode cn = Loader.loadLocalClass(name);
if (cn != null) {
classes.put(name, cn);
return cn;
}
} catch (IOException e) {
e.printStackTrace();
}
throw new RuntimeException(name + " not found in your classpath");
}
}