org.luaj.vm2.lua2java.Lua2Java Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of luaj-jse Show documentation
Show all versions of luaj-jse Show documentation
Luaj 2.0 for the jse platform
package org.luaj.vm2.lua2java;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.ast.Chunk;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.parser.LuaParser;
public class Lua2Java implements LuaCompiler {
public static final Lua2Java instance = new Lua2Java();
public static final void install() {
LoadState.compiler = instance;
}
private Lua2Java() {
}
public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException {
// get first byte
if ( ! stream.markSupported() )
stream = new BufferedInputStream( stream );
stream.mark( 1 );
int firstByte = stream.read();
stream.reset();
// we can only sompile sources
if ( firstByte != '\033' ) {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null)
LuaValue.error("no java compiler");
// break into package and class
if ( filename.endsWith( ".lua") )
filename = filename.substring(0, filename.length()-4);
String s = filename.replace('\\', '/').replace('/','.').replaceAll("[^\\w]", "_");
int p = s.lastIndexOf('.');
final String packageName = p>=0? s.substring(0,p): null;
final String className = toClassname( s.substring(p+1) );
// open output file
final String pkgSubdir = (packageName!=null? packageName.replace('.','/'): "");
final String srcDirRoot = "lua2java/src";
final String binDirRoot = "lua2java/classes";
final String srcDirname = srcDirRoot+"/"+pkgSubdir;
final String binDirname = binDirRoot+"/"+pkgSubdir;
final String srcFilename = srcDirname + "/" + className + ".java";
// make directories
new File(srcDirname).mkdirs();
new File(binDirname).mkdirs();
// generate java source
try {
LuaParser parser = new LuaParser(stream,"ISO8859-1");
Chunk chunk = parser.Chunk();
File source = new File(srcFilename);
Writer writer = new OutputStreamWriter( new FileOutputStream(source) );
new JavaCodeGen(chunk,writer,packageName,className);
writer.close();
// set up output location
StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null);
fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(binDirRoot) }));
// compile the file
CompilationTask task = compiler.getTask(null, fm, null, null, null, fm.getJavaFileObjects(source));
boolean success = task.call().booleanValue();
// instantiate, config and return
if (success) {
// create instance
ClassLoader cl = new ClassLoader() {
public Class findClass(String classname) throws ClassNotFoundException {
if ( classname.startsWith(className) ) {
File f = new File( binDirname+"/"+classname+".class");
long n = f.length();
byte[] b = new byte[(int) n];
try {
DataInputStream dis = new DataInputStream( new FileInputStream(f) );
dis.readFully(b);
} catch ( Exception e ) {
throw new RuntimeException("failed to read class bytes: "+e );
}
return defineClass(classname, b, 0, b.length);
}
return super.findClass(classname);
}
};
Class clazz = cl.loadClass(className);
Object instance = clazz.newInstance();
LuaFunction value = (LuaFunction) instance;
value.setfenv( env );
return value;
} else {
}
} catch ( Exception e ) {
LuaValue.error("compile task failed: "+e);
}
// report compilation error
LuaValue.error("compile task failed:");
return null;
}
// fall back to plain compiler
return LuaC.instance.load( stream, filename, env);
}
/** Convert lua filename to valid class name */
public static final String toClassname( String filename ) {
int n=filename.length();
int j=n;
if ( filename.endsWith(".lua") )
j -= 4;
for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') )
return true;
switch ( c ) {
case '.':
case '$':
case '_':
return true;
default:
return false;
}
}
}