|
@@ -38,18 +38,18 @@ public class JavaBytecodeRunUnit {
|
38
|
38
|
private final List<JavaScriptMethod> scripts = new ArrayList<>();
|
39
|
39
|
private final List<FunctionParameter> scriptParameters = new ArrayList<>();
|
40
|
40
|
private final List<JavaParameterInfo> scriptParameterInfo = new ArrayList<>();
|
41
|
|
-
|
|
41
|
+
|
42
|
42
|
private boolean scriptsWritten = false;
|
43
|
|
-
|
|
43
|
+
|
44
|
44
|
public void add(JavaBytecodeModule module) {
|
45
|
45
|
scriptsWritten = false;
|
46
|
|
-
|
|
46
|
+
|
47
|
47
|
for (Map.Entry<String, byte[]> classEntry : module.getClasses().entrySet())
|
48
|
48
|
classes.put(classEntry.getKey().replace('/', '.'), classEntry.getValue());
|
49
|
|
-
|
|
49
|
+
|
50
|
50
|
for (JavaScriptMethod script : module.getScripts()) {
|
51
|
51
|
scripts.add(script);
|
52
|
|
-
|
|
52
|
+
|
53
|
53
|
for (int i = 0; i < script.parameters.length; i++) {
|
54
|
54
|
FunctionParameter parameter = script.parameters[i];
|
55
|
55
|
if (!scriptParameters.contains(parameter)) {
|
|
@@ -59,22 +59,26 @@ public class JavaBytecodeRunUnit {
|
59
|
59
|
}
|
60
|
60
|
}
|
61
|
61
|
}
|
62
|
|
-
|
|
62
|
+
|
63
|
63
|
public void run() {
|
64
|
|
- run(Collections.emptyMap());
|
|
64
|
+ run(Collections.emptyMap(), this.getClass().getClassLoader());
|
65
|
65
|
}
|
66
|
|
-
|
|
66
|
+
|
67
|
67
|
public void run(Map<FunctionParameter, Object> arguments) {
|
|
68
|
+ run(arguments, this.getClass().getClassLoader());
|
|
69
|
+ }
|
|
70
|
+
|
|
71
|
+ public void run(Map<FunctionParameter, Object> arguments, ClassLoader parentClassLoader) {
|
68
|
72
|
writeScripts();
|
69
|
|
-
|
70
|
|
- ScriptClassLoader classLoader = new ScriptClassLoader();
|
|
73
|
+
|
|
74
|
+ ScriptClassLoader classLoader = new ScriptClassLoader(parentClassLoader);
|
71
|
75
|
|
72
|
76
|
Object[] argumentsArray = new Object[scriptParameters.size()];
|
73
|
77
|
for (int i = 0; i < scriptParameters.size(); i++) {
|
74
|
78
|
FunctionParameter parameter = scriptParameters.get(i);
|
75
|
79
|
if (!arguments.containsKey(parameter))
|
76
|
80
|
throw new IllegalArgumentException("Missing script argument for parameter " + parameter.name);
|
77
|
|
-
|
|
81
|
+
|
78
|
82
|
argumentsArray[i] = arguments.get(parameter);
|
79
|
83
|
}
|
80
|
84
|
try {
|
|
@@ -86,13 +90,13 @@ public class JavaBytecodeRunUnit {
|
86
|
90
|
Logger.getLogger(JavaBytecodeRunUnit.class.getName()).log(Level.SEVERE, null, ex);
|
87
|
91
|
}
|
88
|
92
|
}
|
89
|
|
-
|
|
93
|
+
|
90
|
94
|
public void dump(File directory) {
|
91
|
95
|
writeScripts();
|
92
|
|
-
|
|
96
|
+
|
93
|
97
|
if (!directory.exists())
|
94
|
98
|
directory.mkdirs();
|
95
|
|
-
|
|
99
|
+
|
96
|
100
|
for (Map.Entry<String, byte[]> classEntry : classes.entrySet()) {
|
97
|
101
|
File output = new File(directory, classEntry.getKey() + ".class");
|
98
|
102
|
try (FileOutputStream outputStream = new FileOutputStream(output)) {
|
|
@@ -102,18 +106,18 @@ public class JavaBytecodeRunUnit {
|
102
|
106
|
}
|
103
|
107
|
}
|
104
|
108
|
}
|
105
|
|
-
|
|
109
|
+
|
106
|
110
|
private int getParameterIndex(FunctionParameter parameter) {
|
107
|
111
|
return scriptParameters.indexOf(parameter);
|
108
|
112
|
}
|
109
|
|
-
|
|
113
|
+
|
110
|
114
|
private void writeScripts() {
|
111
|
115
|
if (scriptsWritten)
|
112
|
116
|
return;
|
113
|
|
-
|
|
117
|
+
|
114
|
118
|
JavaClassWriter scriptsClassWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
|
115
|
119
|
scriptsClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Scripts", null, "java/lang/Object", null);
|
116
|
|
-
|
|
120
|
+
|
117
|
121
|
FunctionHeader header = new FunctionHeader(BasicTypeID.VOID, scriptParameters.toArray(new FunctionParameter[scriptParameters.size()]));
|
118
|
122
|
StringBuilder headerBuilder = new StringBuilder();
|
119
|
123
|
headerBuilder.append('(');
|
|
@@ -121,7 +125,7 @@ public class JavaBytecodeRunUnit {
|
121
|
125
|
headerBuilder.append(scriptParameterInfo.get(i).typeDescriptor);
|
122
|
126
|
}
|
123
|
127
|
headerBuilder.append(")V");
|
124
|
|
-
|
|
128
|
+
|
125
|
129
|
JavaMethod runMethod = JavaMethod.getStatic(new JavaClass("script", "Scripts", JavaClass.Kind.CLASS), "run", headerBuilder.toString(), Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
|
126
|
130
|
final JavaWriter runWriter = new JavaWriter(CodePosition.GENERATED, scriptsClassWriter, runMethod, null, null, null);
|
127
|
131
|
runWriter.start();
|
|
@@ -131,10 +135,10 @@ public class JavaBytecodeRunUnit {
|
131
|
135
|
}
|
132
|
136
|
runWriter.invokeStatic(method.method);
|
133
|
137
|
}
|
134
|
|
-
|
|
138
|
+
|
135
|
139
|
runWriter.ret();
|
136
|
140
|
runWriter.end();
|
137
|
|
-
|
|
141
|
+
|
138
|
142
|
classes.put("Scripts", scriptsClassWriter.toByteArray());
|
139
|
143
|
scriptsWritten = true;
|
140
|
144
|
}
|
|
@@ -142,10 +146,18 @@ public class JavaBytecodeRunUnit {
|
142
|
146
|
public class ScriptClassLoader extends ClassLoader {
|
143
|
147
|
private final Map<String, Class> customClasses = new HashMap<>();
|
144
|
148
|
|
|
149
|
+ ScriptClassLoader() {
|
|
150
|
+ super();
|
|
151
|
+ }
|
|
152
|
+
|
|
153
|
+ public ScriptClassLoader(ClassLoader parent) {
|
|
154
|
+ super(parent);
|
|
155
|
+ }
|
|
156
|
+
|
145
|
157
|
@Override
|
146
|
158
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
147
|
159
|
//System.out.println("LoadClass " + name);
|
148
|
|
-
|
|
160
|
+
|
149
|
161
|
if (customClasses.containsKey(name))
|
150
|
162
|
return customClasses.get(name);
|
151
|
163
|
if (classes.containsKey(name)) {
|
|
@@ -156,7 +168,7 @@ public class JavaBytecodeRunUnit {
|
156
|
168
|
return super.loadClass(name);
|
157
|
169
|
}
|
158
|
170
|
}
|
159
|
|
-
|
|
171
|
+
|
160
|
172
|
private static Class<?> loadClass(ClassLoader classLoader, String descriptor) throws ClassNotFoundException {
|
161
|
173
|
switch (descriptor) {
|
162
|
174
|
case "Z": return boolean.class;
|
|
@@ -172,10 +184,10 @@ public class JavaBytecodeRunUnit {
|
172
|
184
|
case "[Ljava/lang/Object;": return Object[].class;
|
173
|
185
|
case "[Ljava/lang/String;": return String[].class;
|
174
|
186
|
}
|
175
|
|
-
|
|
187
|
+
|
176
|
188
|
return classLoader.loadClass(getClassName(descriptor));
|
177
|
189
|
}
|
178
|
|
-
|
|
190
|
+
|
179
|
191
|
private static String getClassName(String descriptor) {
|
180
|
192
|
if (descriptor.startsWith("[")) {
|
181
|
193
|
return "[" + getClassName(descriptor.substring(1));
|