Skip to content

Instantly share code, notes, and snippets.

@johncarl81
Last active August 29, 2015 13:56
Show Gist options
  • Save johncarl81/9230572 to your computer and use it in GitHub Desktop.
Save johncarl81/9230572 to your computer and use it in GitHub Desktop.
package org.test;
import org.junit.Test;
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.*;
import static org.junit.Assert.assertEquals;
public class ClassLoaderTest {
@Test
public void testLoading() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
One one = new One();
one.value = "test";
MemoryClassLoader classLoader = new MemoryClassLoader();
String name = "org.test.Two";
classLoader.add(name,
"package org.test;\n" +
"\n" +
"public class Two{\n" +
" public static String getValue(ClassLoaderTest.One one){\n" +
" return one.value;\n" +
" }\n" +
"}");
Class<?> twoClass = classLoader.loadClass(name);
assertEquals("test", twoClass.getMethod("getValue", One.class).invoke(null, one));
}
public class One{
String value;
}
public class MemoryClassLoader extends ClassLoader {
private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
private final MemoryFileManager manager = new MemoryFileManager(this.compiler);
public MemoryClassLoader(){
super(MemoryClassLoader.class.getClassLoader());
}
public void add(String classname, String fileContent) {
add(Collections.singletonMap(classname, fileContent));
}
public void add(Map<String, String> map) {
List<Source> list = new ArrayList<Source>();
for (Map.Entry<String, String> entry : map.entrySet()) {
list.add(new Source(entry.getKey(), JavaFileObject.Kind.SOURCE, entry.getValue()));
}
this.compiler.getTask(null, this.manager, null, null, null, list).call();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
synchronized (this.manager) {
Output mc = this.manager.map.remove(name);
if (mc != null) {
byte[] array = mc.toByteArray();
return defineClass(name, array, 0, array.length);
}
}
return super.findClass(name);
}
}
class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
public final Map<String, Output> map = new HashMap<String, Output>();
MemoryFileManager(JavaCompiler compiler) {
super(compiler.getStandardFileManager(null, null, null));
}
@Override
public Output getJavaFileForOutput
(Location location, String name, JavaFileObject.Kind kind, FileObject source) {
Output mc = new Output(name, kind);
this.map.put(name, mc);
return mc;
}
}
class Output extends SimpleJavaFileObject {
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Output(String name, Kind kind) {
super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);
}
byte[] toByteArray() {
return this.outputStream.toByteArray();
}
@Override
public ByteArrayOutputStream openOutputStream() {
return this.outputStream;
}
}
class Source extends SimpleJavaFileObject {
private final String content;
Source(String name, Kind kind, String content) {
super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);
this.content = content;
}
@Override
public CharSequence getCharContent(boolean ignore) {
return this.content;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment