package xapi.dev.template;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Random;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import org.junit.Assert;
import org.junit.Test;
import xapi.dev.source.SourceBuilder;
import xapi.log.api.LogLevel;
import xapi.log.api.LogService;
/**
* A fairly simple test of our templating system;
* this class uses itself as the generator for the template we are testing.
*
* The template we are using is:
//@repackaged(xapi.generated)//
package xapi.template;
//@imports()//
import java.util.Date;
//@classDefinition(public class Success)//
abstract class Success{
//@generateWith(xapi.dev.template.TestTemplate)//
public static void main(String[] args){
new Success().injected(args);
}
//injected() //
abstract void injected(String ... args);
//@skipline(1)//
stuff to not compile! /
}
*
* This template, if successfully applied, will produce the source file:
*
package xapi.generated;
import java.util.Date;
import org.junit.Assert;
public class Success {
public static void main(String[] args){
new Success().injected(args);
}
private void injected(String ... args){
Assert.assertEquals(args[0], "success");
}
}
*
*
* @author "James X. Nelson (james@xapi)"
*
*/
public class TestTemplate implements TemplateClassGenerator{
@Override
public void initialize(LogService logger, TemplateGeneratorOptions options) {
logger.log(LogLevel.INFO, "Initializing "+getClass().getName());
}
public void injected(LogService logger, SourceBuilder<?> context, String payload){
context
.setLinesToSkip(1)
.getImports().addImport(Assert.class.getName());
context.getBuffer()
.indent()
.println("private void injected(String ... args){")
.indentln("Assert.assertEquals(args[0], \"success\");")
.println("}")
.outdent();
}
@Test
public void testSimpleGeneration() throws Exception{
//create a temp classpath
File tmp = new File(System.getProperty("java.io.tmpdir","/tmp"));
File cp = new File(tmp, "testCompile-"+Long.toHexString(new Random().nextLong()));
cp.mkdirs();
cp.deleteOnExit();
//apply template
TemplateToJava.main(new String[] {
"-template",getClass().getClassLoader().getResource("xapi/template/Success.x")
.toExternalForm().replace("file:", ""),
"-output",cp.getAbsolutePath()
});
//compile the file
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
String junit = Assert.class.getProtectionDomain().getCodeSource()
.getLocation().toExternalForm().substring(5);//removes file: prefix
//our argument list
String[] args = new String[] {
"-cp", junit, "-proc:none",
"-d", cp.getAbsolutePath()
//let file normalize our / slashes
,new File(cp.getAbsolutePath(),"xapi/generated/Success.java")
.getPath()
};
//run the compile
int result = compiler.run(System.in, System.out, System.err, args);
if (result != 0)
throw new RuntimeException("Java compile failed w/ status code "+result);
//create a thread with the required classes on the classpath
final URLClassLoader cl = new URLClassLoader(new URL[] {
new URL("file:"+junit+File.separator),
new URL("file:"+cp.getAbsolutePath()+File.separator)
});
Thread t = new Thread() {
@Override
public void run() {
//run the generated class reflectively
try {
Class<?> cls = cl.loadClass("xapi.generated.Success");
Method method = cls.getMethod("main", String[].class);
method.invoke(null, (Object)(new String[] {"success"}));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
t.setContextClassLoader(cl);
t.run();
}
}