jaroslav@462: /* jaroslav@462: * To change this template, choose Tools | Templates jaroslav@462: * and open the template in the editor. jaroslav@462: */ jaroslav@462: package org.apidesign.bck2brwsr.dew; jaroslav@462: jaroslav@463: import java.io.ByteArrayInputStream; jaroslav@463: import java.io.ByteArrayOutputStream; jaroslav@462: import java.io.IOException; jaroslav@463: import java.io.InputStream; jaroslav@463: import java.io.OutputStream; jaroslav@463: import java.net.URI; jaroslav@463: import java.net.URISyntaxException; jaroslav@462: import java.nio.charset.Charset; jaroslav@462: import java.util.ArrayList; jaroslav@463: import java.util.Arrays; jaroslav@462: import java.util.Collections; jaroslav@463: import java.util.HashMap; jaroslav@462: import java.util.Iterator; jaroslav@462: import java.util.List; jaroslav@462: import java.util.Locale; jaroslav@462: import java.util.Map; jaroslav@462: import java.util.Set; jaroslav@463: import java.util.logging.Level; jaroslav@463: import java.util.logging.Logger; jaroslav@462: import java.util.regex.Matcher; jaroslav@462: import java.util.regex.Pattern; jaroslav@462: import javax.tools.Diagnostic; jaroslav@462: import javax.tools.DiagnosticListener; jaroslav@462: import javax.tools.FileObject; jaroslav@463: import javax.tools.ForwardingJavaFileManager; jaroslav@462: import javax.tools.JavaCompiler; jaroslav@462: import javax.tools.JavaCompiler.CompilationTask; jaroslav@462: import javax.tools.JavaFileManager; jaroslav@462: import javax.tools.JavaFileObject; jaroslav@462: import javax.tools.JavaFileObject.Kind; jaroslav@463: import javax.tools.SimpleJavaFileObject; jaroslav@462: import javax.tools.StandardJavaFileManager; jaroslav@462: import javax.tools.StandardLocation; jaroslav@463: import javax.tools.ToolProvider; jaroslav@462: jaroslav@462: /** jaroslav@462: * jaroslav@462: * @author Jaroslav Tulach jaroslav@462: */ jaroslav@462: final class Compile implements JavaFileManager, DiagnosticListener { jaroslav@462: private final JFO jfo; jaroslav@462: private final String pkg; jaroslav@462: private StandardJavaFileManager delegate; jaroslav@462: private List> errors = new ArrayList<>(); jaroslav@462: jaroslav@462: public Compile(String pkg, JFO jfo) { jaroslav@462: this.pkg = pkg; jaroslav@462: this.jfo = jfo; jaroslav@462: } jaroslav@462: jaroslav@463: /* jaroslav@462: public static Map compile(String html, String java) throws IOException { jaroslav@462: JavaCompiler jc = javax.tools.ToolProvider.getSystemJavaCompiler(); jaroslav@462: String pkg = findPkg(java); jaroslav@462: String cls = findCls(java); jaroslav@462: jaroslav@462: JFO jfo = new JFO(java, pkg.replace('.', '/') + '/' + cls + ".java"); jaroslav@462: final Compile cmp = new Compile(pkg, jfo); jaroslav@462: cmp.delegate = jc.getStandardFileManager(cmp, Locale.ENGLISH, Charset.forName("UTF-8")); jaroslav@462: jaroslav@462: Set toCmp = Collections.singleton(pkg + '.' + cls); jaroslav@462: Set unit = Collections.singleton(jfo); jaroslav@462: CompilationTask task = jc.getTask(null, cmp, cmp, null, null, unit); jaroslav@462: if (task.call() != true) { jaroslav@462: throw new IOException("Compilation failed: " + cmp.errors); jaroslav@462: } jaroslav@462: return Collections.emptyMap(); jaroslav@462: } jaroslav@463: */ jaroslav@463: public static Map compile(final String html, final String code) throws IOException { jaroslav@463: final String pkg = findPkg(code); jaroslav@463: // String cls = findCls(code); jaroslav@463: jaroslav@463: DiagnosticListener devNull = new DiagnosticListener() { jaroslav@463: public void report(Diagnostic diagnostic) { jaroslav@463: System.err.println("diagnostic=" + diagnostic); jaroslav@463: } jaroslav@463: }; jaroslav@463: StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(devNull, null, null); jaroslav@463: jaroslav@463: // sjfm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, toFiles(boot)); jaroslav@463: // sjfm.setLocation(StandardLocation.CLASS_PATH, toFiles(compile)); jaroslav@463: jaroslav@463: final Map class2BAOS = new HashMap(); jaroslav@463: jaroslav@463: JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) { jaroslav@463: @Override jaroslav@463: public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { jaroslav@463: return code; jaroslav@463: } jaroslav@463: }; jaroslav@463: final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) { jaroslav@463: @Override jaroslav@463: public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { jaroslav@463: return html; jaroslav@463: } jaroslav@463: jaroslav@463: @Override jaroslav@463: public InputStream openInputStream() throws IOException { jaroslav@463: return new ByteArrayInputStream(html.getBytes()); jaroslav@463: } jaroslav@463: }; jaroslav@463: jaroslav@463: final URI scratch; jaroslav@463: try { jaroslav@463: scratch = new URI("mem://mem3"); jaroslav@463: } catch (URISyntaxException ex) { jaroslav@463: throw new IOException(ex); jaroslav@463: } jaroslav@463: jaroslav@463: JavaFileManager jfm = new ForwardingJavaFileManager(sjfm) { jaroslav@463: @Override jaroslav@463: public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { jaroslav@463: if (kind == Kind.CLASS) { jaroslav@463: final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); jaroslav@463: jaroslav@463: class2BAOS.put(className.replace('.', '/') + ".class", buffer); jaroslav@463: return new SimpleJavaFileObject(sibling.toUri(), kind) { jaroslav@463: @Override jaroslav@463: public OutputStream openOutputStream() throws IOException { jaroslav@463: return buffer; jaroslav@463: } jaroslav@463: }; jaroslav@463: } jaroslav@463: jaroslav@463: if (kind == Kind.SOURCE) { jaroslav@463: return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) { jaroslav@463: private final ByteArrayOutputStream data = new ByteArrayOutputStream(); jaroslav@463: @Override jaroslav@463: public OutputStream openOutputStream() throws IOException { jaroslav@463: return data; jaroslav@463: } jaroslav@463: jaroslav@463: @Override jaroslav@463: public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { jaroslav@463: data.close(); jaroslav@463: return new String(data.toByteArray()); jaroslav@463: } jaroslav@463: }; jaroslav@463: } jaroslav@463: jaroslav@463: throw new IllegalStateException(); jaroslav@463: } jaroslav@463: // @Override jaroslav@463: // public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { jaroslav@463: // if (location == StandardLocation.PLATFORM_CLASS_PATH) { jaroslav@463: // return super.list(location, packageName, kinds, recurse); jaroslav@463: // } jaroslav@463: // if (location == StandardLocation.CLASS_PATH) { jaroslav@463: // return super.list(location, packageName, kinds, recurse); jaroslav@463: // } jaroslav@463: // if (location == StandardLocation.SOURCE_PATH) { jaroslav@463: // System.out.println("src path for " + packageName + " kinds: " + kinds); jaroslav@463: // if (packageName.equals(pkg) && kinds.contains(Kind.OTHER)) { jaroslav@463: // return Collections.singleton(htmlFile); jaroslav@463: // } jaroslav@463: // return Collections.emptyList(); jaroslav@463: // } jaroslav@463: // throw new UnsupportedOperationException("Loc: " + location + " pkg: " + packageName + " kinds: " + kinds + " rec: " + recurse); jaroslav@463: // } jaroslav@463: jaroslav@463: @Override jaroslav@463: public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { jaroslav@463: if (location == StandardLocation.SOURCE_PATH) { jaroslav@463: // System.out.println("src path for " + packageName + " kinds: " + kinds); jaroslav@463: if (packageName.equals(pkg)) { jaroslav@463: return htmlFile; jaroslav@463: } jaroslav@463: } jaroslav@463: jaroslav@463: return null; jaroslav@463: } jaroslav@463: jaroslav@463: }; jaroslav@463: jaroslav@463: ToolProvider.getSystemJavaCompiler().getTask(null, jfm, devNull, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call(); jaroslav@463: jaroslav@463: Map result = new HashMap(); jaroslav@463: jaroslav@463: for (Map.Entry e : class2BAOS.entrySet()) { jaroslav@463: result.put(e.getKey(), e.getValue().toByteArray()); jaroslav@463: } jaroslav@463: jaroslav@463: return result; jaroslav@463: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public ClassLoader getClassLoader(Location location) { jaroslav@462: return null;//Compile.class.getClassLoader(); jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { jaroslav@462: if (location == StandardLocation.PLATFORM_CLASS_PATH) { jaroslav@462: return delegate.list(location, packageName, kinds, recurse); jaroslav@462: } jaroslav@462: if (location == StandardLocation.CLASS_PATH) { jaroslav@462: return delegate.list(location, packageName, kinds, recurse); jaroslav@462: } jaroslav@462: if (location == StandardLocation.SOURCE_PATH) { jaroslav@462: if (packageName.equals(pkg)) { jaroslav@462: return Collections.singleton(jfo); jaroslav@462: } jaroslav@462: return Collections.emptyList(); jaroslav@462: } jaroslav@462: throw new UnsupportedOperationException("Loc: " + location + " pkg: " + packageName + " kinds: " + kinds + " rec: " + recurse); jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public String inferBinaryName(Location location, JavaFileObject file) { jaroslav@462: if (file == jfo) { jaroslav@462: return pkg + "." + file.getName(); jaroslav@462: } jaroslav@462: return delegate.inferBinaryName(location, file); jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public boolean isSameFile(FileObject a, FileObject b) { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public boolean handleOption(String current, Iterator remaining) { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public boolean hasLocation(Location location) { jaroslav@462: return true; jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public void flush() throws IOException { jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public void close() throws IOException { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public int isSupportedOption(String option) { jaroslav@462: throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. jaroslav@462: } jaroslav@462: jaroslav@462: @Override jaroslav@462: public void report(Diagnostic diagnostic) { jaroslav@462: errors.add(diagnostic); jaroslav@462: } jaroslav@462: private static String findPkg(String java) throws IOException { jaroslav@462: Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE); jaroslav@462: Matcher m = p.matcher(java); jaroslav@462: if (!m.find()) { jaroslav@462: throw new IOException("Can't find package declaration in the java file"); jaroslav@462: } jaroslav@462: String pkg = m.group(1); jaroslav@462: return pkg; jaroslav@462: } jaroslav@462: private static String findCls(String java) throws IOException { jaroslav@462: Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE); jaroslav@462: Matcher m = p.matcher(java); jaroslav@462: if (!m.find()) { jaroslav@462: throw new IOException("Can't find package declaration in the java file"); jaroslav@462: } jaroslav@462: String cls = m.group(1); jaroslav@462: return cls; jaroslav@462: } jaroslav@462: }