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