Last active
August 29, 2015 13:56
-
-
Save johncarl81/9230572 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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