launcher/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 16 Jan 2013 10:52:06 +0100
branchdew
changeset 463 3641fd0663d3
parent 462 aa69b1387624
child 464 9823859d253a
permissions -rw-r--r--
After Lahvac's tweaks the compilation seems to run OK
jaroslav@462
     1
/*
jaroslav@462
     2
 * To change this template, choose Tools | Templates
jaroslav@462
     3
 * and open the template in the editor.
jaroslav@462
     4
 */
jaroslav@462
     5
package org.apidesign.bck2brwsr.dew;
jaroslav@462
     6
jaroslav@463
     7
import java.io.ByteArrayInputStream;
jaroslav@463
     8
import java.io.ByteArrayOutputStream;
jaroslav@462
     9
import java.io.IOException;
jaroslav@463
    10
import java.io.InputStream;
jaroslav@463
    11
import java.io.OutputStream;
jaroslav@463
    12
import java.net.URI;
jaroslav@463
    13
import java.net.URISyntaxException;
jaroslav@462
    14
import java.nio.charset.Charset;
jaroslav@462
    15
import java.util.ArrayList;
jaroslav@463
    16
import java.util.Arrays;
jaroslav@462
    17
import java.util.Collections;
jaroslav@463
    18
import java.util.HashMap;
jaroslav@462
    19
import java.util.Iterator;
jaroslav@462
    20
import java.util.List;
jaroslav@462
    21
import java.util.Locale;
jaroslav@462
    22
import java.util.Map;
jaroslav@462
    23
import java.util.Set;
jaroslav@463
    24
import java.util.logging.Level;
jaroslav@463
    25
import java.util.logging.Logger;
jaroslav@462
    26
import java.util.regex.Matcher;
jaroslav@462
    27
import java.util.regex.Pattern;
jaroslav@462
    28
import javax.tools.Diagnostic;
jaroslav@462
    29
import javax.tools.DiagnosticListener;
jaroslav@462
    30
import javax.tools.FileObject;
jaroslav@463
    31
import javax.tools.ForwardingJavaFileManager;
jaroslav@462
    32
import javax.tools.JavaCompiler;
jaroslav@462
    33
import javax.tools.JavaCompiler.CompilationTask;
jaroslav@462
    34
import javax.tools.JavaFileManager;
jaroslav@462
    35
import javax.tools.JavaFileObject;
jaroslav@462
    36
import javax.tools.JavaFileObject.Kind;
jaroslav@463
    37
import javax.tools.SimpleJavaFileObject;
jaroslav@462
    38
import javax.tools.StandardJavaFileManager;
jaroslav@462
    39
import javax.tools.StandardLocation;
jaroslav@463
    40
import javax.tools.ToolProvider;
jaroslav@462
    41
jaroslav@462
    42
/**
jaroslav@462
    43
 *
jaroslav@462
    44
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@462
    45
 */
jaroslav@462
    46
final class Compile implements JavaFileManager, DiagnosticListener<JavaFileObject> {
jaroslav@462
    47
    private final JFO jfo;
jaroslav@462
    48
    private final String pkg;
jaroslav@462
    49
    private StandardJavaFileManager delegate;
jaroslav@462
    50
    private List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
jaroslav@462
    51
jaroslav@462
    52
    public Compile(String pkg, JFO jfo) {
jaroslav@462
    53
        this.pkg = pkg;
jaroslav@462
    54
        this.jfo = jfo;
jaroslav@462
    55
    }
jaroslav@462
    56
    
jaroslav@463
    57
    /*
jaroslav@462
    58
    public static Map<String,byte[]> compile(String html, String java) throws IOException {
jaroslav@462
    59
        JavaCompiler jc = javax.tools.ToolProvider.getSystemJavaCompiler();
jaroslav@462
    60
        String pkg = findPkg(java);
jaroslav@462
    61
        String cls = findCls(java);
jaroslav@462
    62
        
jaroslav@462
    63
        JFO jfo = new JFO(java, pkg.replace('.', '/') + '/' + cls + ".java");
jaroslav@462
    64
        final Compile cmp = new Compile(pkg, jfo);
jaroslav@462
    65
        cmp.delegate = jc.getStandardFileManager(cmp, Locale.ENGLISH, Charset.forName("UTF-8"));
jaroslav@462
    66
        
jaroslav@462
    67
        Set<String> toCmp = Collections.singleton(pkg + '.' + cls);
jaroslav@462
    68
        Set<JFO> unit = Collections.singleton(jfo);
jaroslav@462
    69
        CompilationTask task = jc.getTask(null, cmp, cmp, null, null, unit);
jaroslav@462
    70
        if (task.call() != true) {
jaroslav@462
    71
            throw new IOException("Compilation failed: " + cmp.errors);
jaroslav@462
    72
        }
jaroslav@462
    73
        return Collections.emptyMap();
jaroslav@462
    74
    }
jaroslav@463
    75
    */
jaroslav@463
    76
    public static Map<String, byte[]> compile(final String html, final String code) throws IOException {
jaroslav@463
    77
        final String pkg = findPkg(code);
jaroslav@463
    78
//        String cls = findCls(code);
jaroslav@463
    79
        
jaroslav@463
    80
        DiagnosticListener<JavaFileObject> devNull = new DiagnosticListener<JavaFileObject>() {
jaroslav@463
    81
            public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
jaroslav@463
    82
                System.err.println("diagnostic=" + diagnostic);
jaroslav@463
    83
            }
jaroslav@463
    84
        };
jaroslav@463
    85
        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(devNull, null, null);
jaroslav@463
    86
jaroslav@463
    87
//        sjfm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, toFiles(boot));
jaroslav@463
    88
//        sjfm.setLocation(StandardLocation.CLASS_PATH, toFiles(compile));
jaroslav@463
    89
jaroslav@463
    90
        final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<String, ByteArrayOutputStream>();
jaroslav@463
    91
jaroslav@463
    92
        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
jaroslav@463
    93
            @Override
jaroslav@463
    94
            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
jaroslav@463
    95
                return code;
jaroslav@463
    96
            }
jaroslav@463
    97
        };
jaroslav@463
    98
        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
jaroslav@463
    99
            @Override
jaroslav@463
   100
            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
jaroslav@463
   101
                return html;
jaroslav@463
   102
            }
jaroslav@463
   103
jaroslav@463
   104
            @Override
jaroslav@463
   105
            public InputStream openInputStream() throws IOException {
jaroslav@463
   106
                return new ByteArrayInputStream(html.getBytes());
jaroslav@463
   107
            }
jaroslav@463
   108
        };
jaroslav@463
   109
        
jaroslav@463
   110
        final URI scratch;
jaroslav@463
   111
        try {
jaroslav@463
   112
            scratch = new URI("mem://mem3");
jaroslav@463
   113
        } catch (URISyntaxException ex) {
jaroslav@463
   114
            throw new IOException(ex);
jaroslav@463
   115
        }
jaroslav@463
   116
        
jaroslav@463
   117
        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
jaroslav@463
   118
            @Override
jaroslav@463
   119
            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
jaroslav@463
   120
                if (kind  == Kind.CLASS) {
jaroslav@463
   121
                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
jaroslav@463
   122
jaroslav@463
   123
                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
jaroslav@463
   124
                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
jaroslav@463
   125
                        @Override
jaroslav@463
   126
                        public OutputStream openOutputStream() throws IOException {
jaroslav@463
   127
                            return buffer;
jaroslav@463
   128
                        }
jaroslav@463
   129
                    };
jaroslav@463
   130
                }
jaroslav@463
   131
                
jaroslav@463
   132
                if (kind == Kind.SOURCE) {
jaroslav@463
   133
                    return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
jaroslav@463
   134
                        private final ByteArrayOutputStream data = new ByteArrayOutputStream();
jaroslav@463
   135
                        @Override
jaroslav@463
   136
                        public OutputStream openOutputStream() throws IOException {
jaroslav@463
   137
                            return data;
jaroslav@463
   138
                        }
jaroslav@463
   139
jaroslav@463
   140
                        @Override
jaroslav@463
   141
                        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
jaroslav@463
   142
                            data.close();
jaroslav@463
   143
                            return new String(data.toByteArray());
jaroslav@463
   144
                        }
jaroslav@463
   145
                    };
jaroslav@463
   146
                }
jaroslav@463
   147
                
jaroslav@463
   148
                throw new IllegalStateException();
jaroslav@463
   149
            }
jaroslav@463
   150
//            @Override
jaroslav@463
   151
//            public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
jaroslav@463
   152
//                if (location == StandardLocation.PLATFORM_CLASS_PATH) {
jaroslav@463
   153
//                    return super.list(location, packageName, kinds, recurse);
jaroslav@463
   154
//                }
jaroslav@463
   155
//                if (location == StandardLocation.CLASS_PATH) {
jaroslav@463
   156
//                    return super.list(location, packageName, kinds, recurse);
jaroslav@463
   157
//                }
jaroslav@463
   158
//                if (location == StandardLocation.SOURCE_PATH) {
jaroslav@463
   159
//                    System.out.println("src path for " + packageName + " kinds: " + kinds);
jaroslav@463
   160
//                    if (packageName.equals(pkg) && kinds.contains(Kind.OTHER)) {
jaroslav@463
   161
//                        return Collections.<JavaFileObject>singleton(htmlFile);
jaroslav@463
   162
//                    }
jaroslav@463
   163
//                    return Collections.emptyList();
jaroslav@463
   164
//                }
jaroslav@463
   165
//                throw new UnsupportedOperationException("Loc: " + location + " pkg: " + packageName + " kinds: " + kinds + " rec: " + recurse);
jaroslav@463
   166
//            }
jaroslav@463
   167
jaroslav@463
   168
            @Override
jaroslav@463
   169
            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
jaroslav@463
   170
                if (location == StandardLocation.SOURCE_PATH) {
jaroslav@463
   171
//                    System.out.println("src path for " + packageName + " kinds: " + kinds);
jaroslav@463
   172
                    if (packageName.equals(pkg)) {
jaroslav@463
   173
                        return htmlFile;
jaroslav@463
   174
                    }
jaroslav@463
   175
                }
jaroslav@463
   176
                
jaroslav@463
   177
                return null;
jaroslav@463
   178
            }
jaroslav@463
   179
            
jaroslav@463
   180
        };
jaroslav@463
   181
jaroslav@463
   182
        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, devNull, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
jaroslav@463
   183
jaroslav@463
   184
        Map<String, byte[]> result = new HashMap<String, byte[]>();
jaroslav@463
   185
jaroslav@463
   186
        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
jaroslav@463
   187
            result.put(e.getKey(), e.getValue().toByteArray());
jaroslav@463
   188
        }
jaroslav@463
   189
jaroslav@463
   190
        return result;
jaroslav@463
   191
    }
jaroslav@462
   192
jaroslav@462
   193
    @Override
jaroslav@462
   194
    public ClassLoader getClassLoader(Location location) {
jaroslav@462
   195
        return null;//Compile.class.getClassLoader();
jaroslav@462
   196
    }
jaroslav@462
   197
jaroslav@462
   198
    @Override
jaroslav@462
   199
    public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
jaroslav@462
   200
        if (location == StandardLocation.PLATFORM_CLASS_PATH) {
jaroslav@462
   201
            return delegate.list(location, packageName, kinds, recurse);
jaroslav@462
   202
        }
jaroslav@462
   203
        if (location == StandardLocation.CLASS_PATH) {
jaroslav@462
   204
            return delegate.list(location, packageName, kinds, recurse);
jaroslav@462
   205
        }
jaroslav@462
   206
        if (location == StandardLocation.SOURCE_PATH) {
jaroslav@462
   207
            if (packageName.equals(pkg)) {
jaroslav@462
   208
                return Collections.<JavaFileObject>singleton(jfo);
jaroslav@462
   209
            }
jaroslav@462
   210
            return Collections.emptyList();
jaroslav@462
   211
        }
jaroslav@462
   212
        throw new UnsupportedOperationException("Loc: " + location + " pkg: " + packageName + " kinds: " + kinds + " rec: " + recurse);
jaroslav@462
   213
    }
jaroslav@462
   214
jaroslav@462
   215
    @Override
jaroslav@462
   216
    public String inferBinaryName(Location location, JavaFileObject file) {
jaroslav@462
   217
        if (file == jfo) {
jaroslav@462
   218
            return pkg + "." + file.getName();
jaroslav@462
   219
        }
jaroslav@462
   220
        return delegate.inferBinaryName(location, file);
jaroslav@462
   221
    }
jaroslav@462
   222
jaroslav@462
   223
    @Override
jaroslav@462
   224
    public boolean isSameFile(FileObject a, FileObject b) {
jaroslav@462
   225
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   226
    }
jaroslav@462
   227
jaroslav@462
   228
    @Override
jaroslav@462
   229
    public boolean handleOption(String current, Iterator<String> remaining) {
jaroslav@462
   230
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   231
    }
jaroslav@462
   232
jaroslav@462
   233
    @Override
jaroslav@462
   234
    public boolean hasLocation(Location location) {
jaroslav@462
   235
        return true;
jaroslav@462
   236
    }
jaroslav@462
   237
jaroslav@462
   238
    @Override
jaroslav@462
   239
    public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
jaroslav@462
   240
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   241
    }
jaroslav@462
   242
jaroslav@462
   243
    @Override
jaroslav@462
   244
    public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
jaroslav@462
   245
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   246
    }
jaroslav@462
   247
jaroslav@462
   248
    @Override
jaroslav@462
   249
    public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
jaroslav@462
   250
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   251
    }
jaroslav@462
   252
jaroslav@462
   253
    @Override
jaroslav@462
   254
    public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
jaroslav@462
   255
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   256
    }
jaroslav@462
   257
jaroslav@462
   258
    @Override
jaroslav@462
   259
    public void flush() throws IOException {
jaroslav@462
   260
    }
jaroslav@462
   261
jaroslav@462
   262
    @Override
jaroslav@462
   263
    public void close() throws IOException {
jaroslav@462
   264
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   265
    }
jaroslav@462
   266
jaroslav@462
   267
    @Override
jaroslav@462
   268
    public int isSupportedOption(String option) {
jaroslav@462
   269
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@462
   270
    }
jaroslav@462
   271
jaroslav@462
   272
    @Override
jaroslav@462
   273
    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
jaroslav@462
   274
        errors.add(diagnostic);
jaroslav@462
   275
    }
jaroslav@462
   276
    private static String findPkg(String java) throws IOException {
jaroslav@462
   277
        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
jaroslav@462
   278
        Matcher m = p.matcher(java);
jaroslav@462
   279
        if (!m.find()) {
jaroslav@462
   280
            throw new IOException("Can't find package declaration in the java file");
jaroslav@462
   281
        }
jaroslav@462
   282
        String pkg = m.group(1);
jaroslav@462
   283
        return pkg;
jaroslav@462
   284
    }
jaroslav@462
   285
    private static String findCls(String java) throws IOException {
jaroslav@462
   286
        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
jaroslav@462
   287
        Matcher m = p.matcher(java);
jaroslav@462
   288
        if (!m.find()) {
jaroslav@462
   289
            throw new IOException("Can't find package declaration in the java file");
jaroslav@462
   290
        }
jaroslav@462
   291
        String cls = m.group(1);
jaroslav@462
   292
        return cls;
jaroslav@462
   293
    }
jaroslav@462
   294
}