javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 02 May 2013 09:18:22 +0200
branchelements
changeset 1072 3800d11c0bdb
parent 913 dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java@146ae7b52b64
parent 769 dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java@0c0fe97fe0c7
permissions -rw-r--r--
Merging with latest state - e.g. 0.7 version
     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.htmlpage;
    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         StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
    89 
    90         final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
    91 
    92         JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
    93             @Override
    94             public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    95                 return code;
    96             }
    97         };
    98         final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
    99             @Override
   100             public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   101                 return html;
   102             }
   103 
   104             @Override
   105             public InputStream openInputStream() throws IOException {
   106                 return new ByteArrayInputStream(html.getBytes());
   107             }
   108         };
   109         
   110         final URI scratch;
   111         try {
   112             scratch = new URI("mem://mem3");
   113         } catch (URISyntaxException ex) {
   114             throw new IOException(ex);
   115         }
   116         
   117         JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
   118             @Override
   119             public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   120                 if (kind  == Kind.CLASS) {
   121                     final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
   122 
   123                     class2BAOS.put(className.replace('.', '/') + ".class", buffer);
   124                     return new SimpleJavaFileObject(sibling.toUri(), kind) {
   125                         @Override
   126                         public OutputStream openOutputStream() throws IOException {
   127                             return buffer;
   128                         }
   129                     };
   130                 }
   131                 
   132                 if (kind == Kind.SOURCE) {
   133                     return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
   134                         private final ByteArrayOutputStream data = new ByteArrayOutputStream();
   135                         @Override
   136                         public OutputStream openOutputStream() throws IOException {
   137                             return data;
   138                         }
   139 
   140                         @Override
   141                         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   142                             data.close();
   143                             return new String(data.toByteArray());
   144                         }
   145                     };
   146                 }
   147                 
   148                 throw new IllegalStateException();
   149             }
   150 
   151             @Override
   152             public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   153                 if (location == StandardLocation.SOURCE_PATH) {
   154                     if (packageName.equals(pkg)) {
   155                         return htmlFile;
   156                     }
   157                 }
   158                 
   159                 return null;
   160             }
   161 
   162             @Override
   163             public boolean isSameFile(FileObject a, FileObject b) {
   164                 if (a == null || b == null) {
   165                     throw new NullPointerException();
   166                 }
   167                 if (!(a instanceof SimpleJavaFileObject)) {
   168                     throw new IllegalArgumentException("Not supported: " + a);
   169                 }
   170                 if (!(b instanceof SimpleJavaFileObject)) {
   171                     throw new IllegalArgumentException("Not supported: " + b);
   172                 }
   173                 return a.equals(b);
   174             }
   175         };
   176 
   177         ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
   178 
   179         Map<String, byte[]> result = new HashMap<>();
   180 
   181         for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
   182             result.put(e.getKey(), e.getValue().toByteArray());
   183         }
   184 
   185         return result;
   186     }
   187 
   188 
   189     @Override
   190     public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   191         errors.add(diagnostic);
   192     }
   193     private static String findPkg(String java) throws IOException {
   194         Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
   195         Matcher m = p.matcher(java);
   196         if (!m.find()) {
   197             throw new IOException("Can't find package declaration in the java file");
   198         }
   199         String pkg = m.group(1);
   200         return pkg;
   201     }
   202     private static String findCls(String java) throws IOException {
   203         Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
   204         Matcher m = p.matcher(java);
   205         if (!m.find()) {
   206             throw new IOException("Can't find package declaration in the java file");
   207         }
   208         String cls = m.group(1);
   209         return cls;
   210     }
   211 
   212     String getHtml() {
   213         String fqn = "'" + pkg + '.' + cls + "'";
   214         return html.replace("'${fqn}'", fqn);
   215     }
   216 }