Mercurial Hosting > luan
comparison core/src/luan/impl/LuanJavaCompiler.java @ 648:e387e4021afe
start compiler with len operator
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 30 Mar 2016 19:40:48 -0600 |
parents | |
children | d658eab7bf4c |
comparison
equal
deleted
inserted
replaced
647:8e8c30b72e9b | 648:e387e4021afe |
---|---|
1 package luan.impl; | |
2 | |
3 import java.io.OutputStream; | |
4 import java.io.ByteArrayOutputStream; | |
5 import java.io.StringWriter; | |
6 import java.io.IOException; | |
7 import java.net.URI; | |
8 import java.util.Collections; | |
9 import javax.tools.FileObject; | |
10 import javax.tools.JavaFileObject; | |
11 import javax.tools.SimpleJavaFileObject; | |
12 import javax.tools.JavaCompiler; | |
13 import javax.tools.ToolProvider; | |
14 import javax.tools.JavaFileManager; | |
15 import javax.tools.StandardJavaFileManager; | |
16 import javax.tools.ForwardingJavaFileManager; | |
17 | |
18 | |
19 public final class LuanJavaCompiler { | |
20 private LuanJavaCompiler() {} // never | |
21 | |
22 public static Class compile(final String className,final String sourceName,final String code) throws ClassNotFoundException { | |
23 final int len = sourceName.length(); | |
24 StringBuilder sb = new StringBuilder(sourceName); | |
25 for( int i=0; i<len; i++ ) | |
26 sb.setCharAt(i,'$'); | |
27 JavaFileObject sourceFile = new SimpleJavaFileObject(URI.create(sb.toString()),JavaFileObject.Kind.SOURCE) { | |
28 @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { | |
29 return code; | |
30 } | |
31 @Override public String getName() { | |
32 return sourceName; | |
33 } | |
34 @Override public boolean isNameCompatible(String simpleName,JavaFileObject.Kind kind) { | |
35 return true; | |
36 } | |
37 }; | |
38 ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
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(); | |
45 StandardJavaFileManager sjfm = compiler.getStandardFileManager(null,null,null); | |
46 ForwardingJavaFileManager fjfm = new ForwardingJavaFileManager(sjfm) { | |
47 @Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { | |
48 return classFile; | |
49 } | |
50 }; | |
51 StringWriter out = new StringWriter(); | |
52 boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call(); | |
53 if( !b ) | |
54 throw new RuntimeException("\n"+out); | |
55 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(); | |
61 if( byteCode[i]==1 && byteCode[i+1]*256 + 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() { | |
71 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { | |
72 if( name.equals(className) ) { | |
73 return defineClass(name, byteCode, 0, byteCode.length); | |
74 } | |
75 return super.findClass(name); | |
76 } | |
77 }; | |
78 return cl.loadClass(className); | |
79 } | |
80 } |