Mercurial Hosting > luan
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 }; |