dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java
author tzezula
Wed, 02 Oct 2013 21:00:24 +0200
changeset 1324 263482b074e9
parent 579 942deef87200
child 1325 f7f25ea1bbec
permissions -rw-r--r--
ClassLoaderFileManager
jaroslav@468
     1
/**
jaroslav@468
     2
 * Back 2 Browser Bytecode Translator
jaroslav@468
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@468
     4
 *
jaroslav@468
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@468
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@468
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@468
     8
 *
jaroslav@468
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@468
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@468
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@468
    12
 * GNU General Public License for more details.
jaroslav@468
    13
 *
jaroslav@468
    14
 * You should have received a copy of the GNU General Public License
jaroslav@468
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@468
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@468
    17
 */
jaroslav@462
    18
package org.apidesign.bck2brwsr.dew;
jaroslav@462
    19
jaroslav@463
    20
import java.io.ByteArrayInputStream;
jaroslav@463
    21
import java.io.ByteArrayOutputStream;
jaroslav@462
    22
import java.io.IOException;
jaroslav@463
    23
import java.io.InputStream;
jaroslav@463
    24
import java.io.OutputStream;
jaroslav@463
    25
import java.net.URI;
jaroslav@463
    26
import java.net.URISyntaxException;
jaroslav@462
    27
import java.util.ArrayList;
jaroslav@463
    28
import java.util.Arrays;
jaroslav@463
    29
import java.util.HashMap;
jaroslav@462
    30
import java.util.List;
jaroslav@462
    31
import java.util.Map;
jaroslav@462
    32
import java.util.regex.Matcher;
jaroslav@462
    33
import java.util.regex.Pattern;
jaroslav@462
    34
import javax.tools.Diagnostic;
jaroslav@462
    35
import javax.tools.DiagnosticListener;
jaroslav@462
    36
import javax.tools.FileObject;
jaroslav@463
    37
import javax.tools.ForwardingJavaFileManager;
jaroslav@462
    38
import javax.tools.JavaFileManager;
jaroslav@462
    39
import javax.tools.JavaFileObject;
jaroslav@462
    40
import javax.tools.JavaFileObject.Kind;
jaroslav@463
    41
import javax.tools.SimpleJavaFileObject;
jaroslav@462
    42
import javax.tools.StandardJavaFileManager;
jaroslav@462
    43
import javax.tools.StandardLocation;
jaroslav@463
    44
import javax.tools.ToolProvider;
jaroslav@462
    45
jaroslav@462
    46
/**
jaroslav@462
    47
 *
jaroslav@462
    48
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@462
    49
 */
jaroslav@464
    50
final class Compile implements DiagnosticListener<JavaFileObject> {
jaroslav@464
    51
    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
jaroslav@464
    52
    private final Map<String, byte[]> classes;
jaroslav@462
    53
    private final String pkg;
jaroslav@464
    54
    private final String cls;
jaroslav@579
    55
    private final String html;
jaroslav@462
    56
jaroslav@464
    57
    private Compile(String html, String code) throws IOException {
jaroslav@464
    58
        this.pkg = findPkg(code);
jaroslav@464
    59
        this.cls = findCls(code);
jaroslav@579
    60
        this.html = html;
jaroslav@464
    61
        classes = compile(html, code);
jaroslav@464
    62
    }
jaroslav@464
    63
jaroslav@464
    64
    /** Performs compilation of given HTML page and associated Java code
jaroslav@464
    65
     */
jaroslav@464
    66
    public static Compile create(String html, String code) throws IOException {
jaroslav@464
    67
        return new Compile(html, code);
jaroslav@462
    68
    }
jaroslav@462
    69
    
jaroslav@464
    70
    /** Checks for given class among compiled resources */
jaroslav@464
    71
    public byte[] get(String res) {
jaroslav@464
    72
        return classes.get(res);
jaroslav@464
    73
    }
jaroslav@464
    74
    
jaroslav@464
    75
    /** Obtains errors created during compilation.
jaroslav@464
    76
     */
jaroslav@464
    77
    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
jaroslav@464
    78
        List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
jaroslav@464
    79
        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
jaroslav@464
    80
            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
jaroslav@464
    81
                err.add(diagnostic);
jaroslav@464
    82
            }
jaroslav@462
    83
        }
jaroslav@464
    84
        return err;
jaroslav@462
    85
    }
jaroslav@464
    86
    
jaroslav@464
    87
    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
tzezula@1324
    88
        final ClassLoaderFileManager clfm = new ClassLoaderFileManager();
tzezula@1324
    89
        final JavaFileObject file = clfm.createMemoryFileObject(
tzezula@1324
    90
                ClassLoaderFileManager.convertFQNToResource(pkg.isEmpty() ? cls : pkg + "." + cls) + Kind.SOURCE.extension,
tzezula@1324
    91
                Kind.SOURCE,
tzezula@1324
    92
                code.getBytes());
tzezula@1324
    93
        final JavaFileObject htmlFile = clfm.createMemoryFileObject(
tzezula@1324
    94
            ClassLoaderFileManager.convertFQNToResource(pkg),
tzezula@1324
    95
            Kind.OTHER,
tzezula@1324
    96
            html.getBytes());
jaroslav@463
    97
tzezula@1324
    98
        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(clfm) {            
jaroslav@463
    99
            @Override
jaroslav@463
   100
            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
jaroslav@463
   101
                if (location == StandardLocation.SOURCE_PATH) {
jaroslav@463
   102
                    if (packageName.equals(pkg)) {
jaroslav@463
   103
                        return htmlFile;
jaroslav@463
   104
                    }
tzezula@1324
   105
                }                
jaroslav@463
   106
                return null;
jaroslav@463
   107
            }
jaroslav@463
   108
        };
jaroslav@463
   109
tzezula@1324
   110
        final Boolean res = ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
tzezula@1324
   111
jaroslav@463
   112
jaroslav@464
   113
        Map<String, byte[]> result = new HashMap<>();
tzezula@1324
   114
        for (MemoryFileObject generated : clfm.getGeneratedFiles(Kind.CLASS)) {
tzezula@1324
   115
            result.put(generated.infer(), generated.getContent());
jaroslav@463
   116
        }
jaroslav@463
   117
        return result;
jaroslav@463
   118
    }
jaroslav@462
   119
jaroslav@462
   120
jaroslav@462
   121
    @Override
jaroslav@462
   122
    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
jaroslav@462
   123
        errors.add(diagnostic);
jaroslav@462
   124
    }
jaroslav@462
   125
    private static String findPkg(String java) throws IOException {
jaroslav@462
   126
        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
jaroslav@462
   127
        Matcher m = p.matcher(java);
jaroslav@462
   128
        if (!m.find()) {
jaroslav@462
   129
            throw new IOException("Can't find package declaration in the java file");
jaroslav@462
   130
        }
jaroslav@462
   131
        String pkg = m.group(1);
jaroslav@462
   132
        return pkg;
jaroslav@462
   133
    }
jaroslav@462
   134
    private static String findCls(String java) throws IOException {
jaroslav@462
   135
        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
jaroslav@462
   136
        Matcher m = p.matcher(java);
jaroslav@462
   137
        if (!m.find()) {
jaroslav@462
   138
            throw new IOException("Can't find package declaration in the java file");
jaroslav@462
   139
        }
jaroslav@462
   140
        String cls = m.group(1);
jaroslav@462
   141
        return cls;
jaroslav@462
   142
    }
jaroslav@579
   143
jaroslav@579
   144
    String getHtml() {
jaroslav@579
   145
        String fqn = "'" + pkg + '.' + cls + "'";
jaroslav@579
   146
        return html.replace("'${fqn}'", fqn);
jaroslav@579
   147
    }
jaroslav@462
   148
}