comparison core/src/luan/impl/LuanJavaCompiler.java @ 665:41f8fdbc3a0a

compile modules
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 07 Apr 2016 17:06:22 -0600
parents e038905512d3
children
comparison
equal deleted inserted replaced
664:71f8f5075df8 665:41f8fdbc3a0a
4 import java.io.ByteArrayOutputStream; 4 import java.io.ByteArrayOutputStream;
5 import java.io.StringWriter; 5 import java.io.StringWriter;
6 import java.io.IOException; 6 import java.io.IOException;
7 import java.net.URI; 7 import java.net.URI;
8 import java.util.Collections; 8 import java.util.Collections;
9 import java.util.Map;
10 import java.util.HashMap;
9 import javax.tools.FileObject; 11 import javax.tools.FileObject;
10 import javax.tools.JavaFileObject; 12 import javax.tools.JavaFileObject;
11 import javax.tools.SimpleJavaFileObject; 13 import javax.tools.SimpleJavaFileObject;
12 import javax.tools.JavaCompiler; 14 import javax.tools.JavaCompiler;
13 import javax.tools.ToolProvider; 15 import javax.tools.ToolProvider;
16 import javax.tools.ForwardingJavaFileManager; 18 import javax.tools.ForwardingJavaFileManager;
17 19
18 20
19 public final class LuanJavaCompiler { 21 public final class LuanJavaCompiler {
20 private LuanJavaCompiler() {} // never 22 private LuanJavaCompiler() {} // never
23
24 private static class MyJavaFileObject extends SimpleJavaFileObject {
25 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
26
27 MyJavaFileObject() {
28 super(URI.create("whatever"),JavaFileObject.Kind.CLASS);
29 }
30
31 @Override public OutputStream openOutputStream() {
32 return baos;
33 }
34
35 byte[] byteCode(String sourceName) {
36 byte[] byteCode = baos.toByteArray();
37 final int len = sourceName.length();
38 int max = byteCode.length-len-3;
39 outer:
40 for( int i=0; true; i++ ) {
41 if( i > max )
42 throw new RuntimeException("len="+len);
43 if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) {
44 for( int j=i+3; j<i+3+len; j++ ) {
45 if( byteCode[j] != '$' )
46 continue outer;
47 }
48 System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len);
49 break;
50 }
51 }
52 return byteCode;
53 }
54 }
21 55
22 public static Class compile(final String className,final String sourceName,final String code) throws ClassNotFoundException { 56 public static Class compile(final String className,final String sourceName,final String code) throws ClassNotFoundException {
23 final int len = sourceName.length(); 57 final int len = sourceName.length();
24 StringBuilder sb = new StringBuilder(sourceName); 58 StringBuilder sb = new StringBuilder(sourceName);
25 for( int i=0; i<len; i++ ) 59 for( int i=0; i<len; i++ )
33 } 67 }
34 @Override public boolean isNameCompatible(String simpleName,JavaFileObject.Kind kind) { 68 @Override public boolean isNameCompatible(String simpleName,JavaFileObject.Kind kind) {
35 return true; 69 return true;
36 } 70 }
37 }; 71 };
38 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 72 final Map<String,MyJavaFileObject> map = new HashMap<String,MyJavaFileObject>();
39 JavaFileObject classFile = new SimpleJavaFileObject(URI.create("whatever"),JavaFileObject.Kind.CLASS) {
40 @Override public OutputStream openOutputStream() {
41 return baos;
42 }
43 };
44 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 73 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
45 StandardJavaFileManager sjfm = compiler.getStandardFileManager(null,null,null); 74 StandardJavaFileManager sjfm = compiler.getStandardFileManager(null,null,null);
46 ForwardingJavaFileManager fjfm = new ForwardingJavaFileManager(sjfm) { 75 ForwardingJavaFileManager fjfm = new ForwardingJavaFileManager(sjfm) {
47 @Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { 76 @Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
77 if( map.containsKey(className) )
78 throw new RuntimeException(className);
79 MyJavaFileObject classFile = new MyJavaFileObject();
80 map.put(className,classFile);
48 return classFile; 81 return classFile;
49 } 82 }
50 }; 83 };
51 StringWriter out = new StringWriter(); 84 StringWriter out = new StringWriter();
52 boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call(); 85 boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call();
53 if( !b ) 86 if( !b )
54 throw new RuntimeException("\n"+out+"\ncode:\n"+code+"\n"); 87 throw new RuntimeException("\n"+out+"\ncode:\n"+code+"\n");
55 final byte[] byteCode = baos.toByteArray();
56 int max = byteCode.length-len-3;
57 outer:
58 for( int i=0; true; i++ ) {
59 if( i > max )
60 throw new RuntimeException("len="+len);
61 if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) {
62 for( int j=i+3; j<i+3+len; j++ ) {
63 if( byteCode[j] != '$' )
64 continue outer;
65 }
66 System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len);
67 break;
68 }
69 }
70 ClassLoader cl = new ClassLoader() { 88 ClassLoader cl = new ClassLoader() {
71 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { 89 @Override protected Class<?> findClass(String name) throws ClassNotFoundException {
72 if( name.equals(className) ) { 90 MyJavaFileObject jfo = map.get(name);
91 if( jfo != null ) {
92 byte[] byteCode = jfo.byteCode(sourceName);
73 return defineClass(name, byteCode, 0, byteCode.length); 93 return defineClass(name, byteCode, 0, byteCode.length);
74 } 94 }
75 return super.findClass(name); 95 return super.findClass(name);
76 } 96 }
77 }; 97 };