Trying to compile Java source via the javax.tools.ToolProvider.getSystemJavaCompiler dew
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 15 Jan 2013 22:48:17 +0100
branchdew
changeset 462aa69b1387624
parent 461 ccc3fd318cb1
child 463 3641fd0663d3
Trying to compile Java source via the javax.tools.ToolProvider.getSystemJavaCompiler
launcher/nb-configuration.xml
launcher/pom.xml
launcher/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java
launcher/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java
launcher/src/main/java/org/apidesign/bck2brwsr/dew/JFO.java
launcher/src/test/java/org/apidesign/bck2brwsr/dew/CompileTest.java
     1.1 --- a/launcher/nb-configuration.xml	Tue Jan 15 16:56:18 2013 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,18 +0,0 @@
     1.4 -<?xml version="1.0" encoding="UTF-8"?>
     1.5 -<project-shared-configuration>
     1.6 -    <!--
     1.7 -This file contains additional configuration written by modules in the NetBeans IDE.
     1.8 -The configuration is intended to be shared among all the users of project and
     1.9 -therefore it is assumed to be part of version control checkout.
    1.10 -Without this configuration present, some functionality in the IDE may be limited or fail altogether.
    1.11 --->
    1.12 -    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
    1.13 -        <!--
    1.14 -Properties that influence various parts of the IDE, especially code formatting and the like. 
    1.15 -You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
    1.16 -That way multiple projects can share the same settings (useful for formatting rules for example).
    1.17 -Any value defined here will override the pom.xml file value but is only applicable to the current project.
    1.18 --->
    1.19 -        <netbeans.compile.on.save>app</netbeans.compile.on.save>
    1.20 -    </properties>
    1.21 -</project-shared-configuration>
     2.1 --- a/launcher/pom.xml	Tue Jan 15 16:56:18 2013 +0100
     2.2 +++ b/launcher/pom.xml	Tue Jan 15 22:48:17 2013 +0100
     2.3 @@ -30,12 +30,6 @@
     2.4    </properties>
     2.5    <dependencies>
     2.6      <dependency>
     2.7 -      <groupId>junit</groupId>
     2.8 -      <artifactId>junit</artifactId>
     2.9 -      <version>3.8.1</version>
    2.10 -      <scope>test</scope>
    2.11 -    </dependency>
    2.12 -    <dependency>
    2.13        <groupId>org.glassfish.grizzly</groupId>
    2.14        <artifactId>grizzly-http-server</artifactId>
    2.15        <version>2.2.19</version>
    2.16 @@ -50,5 +44,16 @@
    2.17        <artifactId>json</artifactId>
    2.18        <version>20090211</version>
    2.19      </dependency>
    2.20 +    <dependency>
    2.21 +      <groupId>org.testng</groupId>
    2.22 +      <artifactId>testng</artifactId>
    2.23 +      <scope>test</scope>
    2.24 +      <exclusions>
    2.25 +        <exclusion>
    2.26 +          <artifactId>junit</artifactId>
    2.27 +          <groupId>junit</groupId>
    2.28 +        </exclusion>
    2.29 +      </exclusions>
    2.30 +    </dependency>
    2.31    </dependencies>
    2.32  </project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Tue Jan 15 22:48:17 2013 +0100
     3.3 @@ -0,0 +1,163 @@
     3.4 +/*
     3.5 + * To change this template, choose Tools | Templates
     3.6 + * and open the template in the editor.
     3.7 + */
     3.8 +package org.apidesign.bck2brwsr.dew;
     3.9 +
    3.10 +import java.io.IOException;
    3.11 +import java.nio.charset.Charset;
    3.12 +import java.util.ArrayList;
    3.13 +import java.util.Collections;
    3.14 +import java.util.Iterator;
    3.15 +import java.util.List;
    3.16 +import java.util.Locale;
    3.17 +import java.util.Map;
    3.18 +import java.util.Set;
    3.19 +import java.util.regex.Matcher;
    3.20 +import java.util.regex.Pattern;
    3.21 +import javax.tools.Diagnostic;
    3.22 +import javax.tools.DiagnosticListener;
    3.23 +import javax.tools.FileObject;
    3.24 +import javax.tools.JavaCompiler;
    3.25 +import javax.tools.JavaCompiler.CompilationTask;
    3.26 +import javax.tools.JavaFileManager;
    3.27 +import javax.tools.JavaFileObject;
    3.28 +import javax.tools.JavaFileObject.Kind;
    3.29 +import javax.tools.StandardJavaFileManager;
    3.30 +import javax.tools.StandardLocation;
    3.31 +
    3.32 +/**
    3.33 + *
    3.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.35 + */
    3.36 +final class Compile implements JavaFileManager, DiagnosticListener<JavaFileObject> {
    3.37 +    private final JFO jfo;
    3.38 +    private final String pkg;
    3.39 +    private StandardJavaFileManager delegate;
    3.40 +    private List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
    3.41 +
    3.42 +    public Compile(String pkg, JFO jfo) {
    3.43 +        this.pkg = pkg;
    3.44 +        this.jfo = jfo;
    3.45 +    }
    3.46 +    
    3.47 +    public static Map<String,byte[]> compile(String html, String java) throws IOException {
    3.48 +        JavaCompiler jc = javax.tools.ToolProvider.getSystemJavaCompiler();
    3.49 +        String pkg = findPkg(java);
    3.50 +        String cls = findCls(java);
    3.51 +        
    3.52 +        JFO jfo = new JFO(java, pkg.replace('.', '/') + '/' + cls + ".java");
    3.53 +        final Compile cmp = new Compile(pkg, jfo);
    3.54 +        cmp.delegate = jc.getStandardFileManager(cmp, Locale.ENGLISH, Charset.forName("UTF-8"));
    3.55 +        
    3.56 +        Set<String> toCmp = Collections.singleton(pkg + '.' + cls);
    3.57 +        Set<JFO> unit = Collections.singleton(jfo);
    3.58 +        CompilationTask task = jc.getTask(null, cmp, cmp, null, null, unit);
    3.59 +        if (task.call() != true) {
    3.60 +            throw new IOException("Compilation failed: " + cmp.errors);
    3.61 +        }
    3.62 +        return Collections.emptyMap();
    3.63 +    }
    3.64 +
    3.65 +    @Override
    3.66 +    public ClassLoader getClassLoader(Location location) {
    3.67 +        return null;//Compile.class.getClassLoader();
    3.68 +    }
    3.69 +
    3.70 +    @Override
    3.71 +    public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
    3.72 +        if (location == StandardLocation.PLATFORM_CLASS_PATH) {
    3.73 +            return delegate.list(location, packageName, kinds, recurse);
    3.74 +        }
    3.75 +        if (location == StandardLocation.CLASS_PATH) {
    3.76 +            return delegate.list(location, packageName, kinds, recurse);
    3.77 +        }
    3.78 +        if (location == StandardLocation.SOURCE_PATH) {
    3.79 +            if (packageName.equals(pkg)) {
    3.80 +                return Collections.<JavaFileObject>singleton(jfo);
    3.81 +            }
    3.82 +            return Collections.emptyList();
    3.83 +        }
    3.84 +        throw new UnsupportedOperationException("Loc: " + location + " pkg: " + packageName + " kinds: " + kinds + " rec: " + recurse);
    3.85 +    }
    3.86 +
    3.87 +    @Override
    3.88 +    public String inferBinaryName(Location location, JavaFileObject file) {
    3.89 +        if (file == jfo) {
    3.90 +            return pkg + "." + file.getName();
    3.91 +        }
    3.92 +        return delegate.inferBinaryName(location, file);
    3.93 +    }
    3.94 +
    3.95 +    @Override
    3.96 +    public boolean isSameFile(FileObject a, FileObject b) {
    3.97 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    3.98 +    }
    3.99 +
   3.100 +    @Override
   3.101 +    public boolean handleOption(String current, Iterator<String> remaining) {
   3.102 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.103 +    }
   3.104 +
   3.105 +    @Override
   3.106 +    public boolean hasLocation(Location location) {
   3.107 +        return true;
   3.108 +    }
   3.109 +
   3.110 +    @Override
   3.111 +    public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
   3.112 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.113 +    }
   3.114 +
   3.115 +    @Override
   3.116 +    public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   3.117 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.118 +    }
   3.119 +
   3.120 +    @Override
   3.121 +    public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   3.122 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.123 +    }
   3.124 +
   3.125 +    @Override
   3.126 +    public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   3.127 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.128 +    }
   3.129 +
   3.130 +    @Override
   3.131 +    public void flush() throws IOException {
   3.132 +    }
   3.133 +
   3.134 +    @Override
   3.135 +    public void close() throws IOException {
   3.136 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.137 +    }
   3.138 +
   3.139 +    @Override
   3.140 +    public int isSupportedOption(String option) {
   3.141 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   3.142 +    }
   3.143 +
   3.144 +    @Override
   3.145 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   3.146 +        errors.add(diagnostic);
   3.147 +    }
   3.148 +    private static String findPkg(String java) throws IOException {
   3.149 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
   3.150 +        Matcher m = p.matcher(java);
   3.151 +        if (!m.find()) {
   3.152 +            throw new IOException("Can't find package declaration in the java file");
   3.153 +        }
   3.154 +        String pkg = m.group(1);
   3.155 +        return pkg;
   3.156 +    }
   3.157 +    private static String findCls(String java) throws IOException {
   3.158 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
   3.159 +        Matcher m = p.matcher(java);
   3.160 +        if (!m.find()) {
   3.161 +            throw new IOException("Can't find package declaration in the java file");
   3.162 +        }
   3.163 +        String cls = m.group(1);
   3.164 +        return cls;
   3.165 +    }
   3.166 +}
     4.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java	Tue Jan 15 16:56:18 2013 +0100
     4.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java	Tue Jan 15 22:48:17 2013 +0100
     4.3 @@ -24,7 +24,8 @@
     4.4   * @author phrebejk
     4.5   */
     4.6  public class Dew extends HttpHandler {
     4.7 -    private static String html = "Nazdar!";
     4.8 +    private String html = "Nazdar!";
     4.9 +    private String java = "class C {\n}\n";
    4.10  
    4.11      @Override
    4.12      public void service(Request request, Response response) throws Exception {
    4.13 @@ -34,7 +35,9 @@
    4.14              JSONTokener tok = new JSONTokener(new InputStreamReader(is));
    4.15              JSONObject obj = new JSONObject(tok);
    4.16              html = obj.getString("html");
    4.17 +            java = obj.getString("java");
    4.18              LOG.info(html);
    4.19 +            LOG.info(java);
    4.20              
    4.21              response.getOutputStream().write("[]".getBytes());
    4.22              response.setStatus(HttpStatus.OK_200);
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/dew/JFO.java	Tue Jan 15 22:48:17 2013 +0100
     5.3 @@ -0,0 +1,96 @@
     5.4 +/*
     5.5 + * To change this template, choose Tools | Templates
     5.6 + * and open the template in the editor.
     5.7 + */
     5.8 +package org.apidesign.bck2brwsr.dew;
     5.9 +
    5.10 +import java.io.IOException;
    5.11 +import java.io.InputStream;
    5.12 +import java.io.OutputStream;
    5.13 +import java.io.Reader;
    5.14 +import java.io.StringReader;
    5.15 +import java.io.Writer;
    5.16 +import java.net.URI;
    5.17 +import javax.lang.model.element.Modifier;
    5.18 +import javax.lang.model.element.NestingKind;
    5.19 +import javax.tools.JavaFileObject;
    5.20 +
    5.21 +/**
    5.22 + *
    5.23 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.24 + */
    5.25 +final class JFO implements JavaFileObject {
    5.26 +    private final String text;
    5.27 +    private final String name;
    5.28 +
    5.29 +    public JFO(String text, String name) {
    5.30 +        this.text = text;
    5.31 +        this.name = name;
    5.32 +    }
    5.33 +
    5.34 +    @Override
    5.35 +    public Kind getKind() {
    5.36 +        return Kind.SOURCE;
    5.37 +    }
    5.38 +
    5.39 +    @Override
    5.40 +    public boolean isNameCompatible(String simpleName, Kind kind) {
    5.41 +        return false;
    5.42 +    }
    5.43 +
    5.44 +    @Override
    5.45 +    public NestingKind getNestingKind() {
    5.46 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.47 +    }
    5.48 +
    5.49 +    @Override
    5.50 +    public Modifier getAccessLevel() {
    5.51 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.52 +    }
    5.53 +
    5.54 +    @Override
    5.55 +    public URI toUri() {
    5.56 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.57 +    }
    5.58 +
    5.59 +    @Override
    5.60 +    public String getName() {
    5.61 +        return name;
    5.62 +    }
    5.63 +
    5.64 +    @Override
    5.65 +    public InputStream openInputStream() throws IOException {
    5.66 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.67 +    }
    5.68 +
    5.69 +    @Override
    5.70 +    public OutputStream openOutputStream() throws IOException {
    5.71 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.72 +    }
    5.73 +
    5.74 +    @Override
    5.75 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    5.76 +        return new StringReader(text);
    5.77 +    }
    5.78 +
    5.79 +    @Override
    5.80 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    5.81 +        return text;
    5.82 +    }
    5.83 +
    5.84 +    @Override
    5.85 +    public Writer openWriter() throws IOException {
    5.86 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.87 +    }
    5.88 +
    5.89 +    @Override
    5.90 +    public long getLastModified() {
    5.91 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.92 +    }
    5.93 +
    5.94 +    @Override
    5.95 +    public boolean delete() {
    5.96 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    5.97 +    }
    5.98 +    
    5.99 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/launcher/src/test/java/org/apidesign/bck2brwsr/dew/CompileTest.java	Tue Jan 15 22:48:17 2013 +0100
     6.3 @@ -0,0 +1,28 @@
     6.4 +/*
     6.5 + * To change this template, choose Tools | Templates
     6.6 + * and open the template in the editor.
     6.7 + */
     6.8 +package org.apidesign.bck2brwsr.dew;
     6.9 +
    6.10 +import java.io.IOException;
    6.11 +import java.util.Map;
    6.12 +import static org.testng.Assert.*;
    6.13 +import org.testng.annotations.Test;
    6.14 +
    6.15 +/**
    6.16 + *
    6.17 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.18 + */
    6.19 +public class CompileTest  {
    6.20 +    @Test public void testCompile() throws IOException {
    6.21 +        String html = "<html><body>"
    6.22 +                + " <button id='btn'>Hello!</button>"
    6.23 +                + "</body></html>";
    6.24 +        String java = "package x.y.z;"
    6.25 +                + "class X {"
    6.26 +                + "}";
    6.27 +        Map<String,byte[]> result = Compile.compile(html, java);
    6.28 +
    6.29 +        assertNotNull(result.get("x/y/z/X.class"), "Class X is compiled: " + result);
    6.30 +    }
    6.31 +}