vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 03 Oct 2012 08:19:44 -0700
branchemul
changeset 92 bf4f95784c62
parent 90 e7be3cb29a72
child 93 a236a9f137ac
permissions -rw-r--r--
Merging the strings work into the emulation attempt
     1 package org.apidesign.vm4brwsr;
     2 
     3 import java.io.BufferedWriter;
     4 import java.io.FileWriter;
     5 import java.io.IOException;
     6 import java.io.InputStream;
     7 import java.io.Writer;
     8 import java.util.Arrays;
     9 import java.util.HashSet;
    10 import java.util.LinkedList;
    11 import java.util.List;
    12 import java.util.Set;
    13 
    14 /** Generator of JavaScript from bytecode of classes on classpath of the VM.
    15  *
    16  * @author Jaroslav Tulach <jtulach@netbeans.org>
    17  */
    18 final class GenJS {
    19     private GenJS() {}
    20     
    21     public static void main(String... args) throws IOException {
    22         if (args.length < 2) {
    23             System.err.println("Usage: java -cp ... -jar ... <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
    24             return;
    25         }
    26         
    27         Writer w = new BufferedWriter(new FileWriter(args[0]));
    28         List<String> classes = Arrays.asList(args).subList(1, args.length);
    29         compile(w, classes);
    30         w.close();
    31     }
    32     
    33     static void compile(Appendable out, String... names) throws IOException {
    34         compile(out, Arrays.asList(names));
    35     }
    36     static void compile(Appendable out, List<String> names) throws IOException {
    37         Set<String> processed = new HashSet<String>();
    38         LinkedList<String> toProcess = new LinkedList<String>(names);
    39         for (;;) {
    40             toProcess.removeAll(processed);
    41             if (toProcess.isEmpty()) {
    42                 break;
    43             }
    44             String name = toProcess.getFirst();
    45             processed.add(name);
    46             if (name.startsWith("sun/")) {
    47                 continue;
    48             }
    49             if (name.startsWith("java/") 
    50                 && !name.equals("java/lang/Object")
    51                 && !name.equals("java/lang/StringBuilder")
    52                 && !name.equals("java/lang/AbstractStringBuilder")
    53             ) {
    54                 continue;
    55             }
    56             InputStream is = GenJS.class.getClassLoader().getResourceAsStream(name + ".class");
    57             if (is == null) {
    58                 throw new IOException("Can't find class " + name); 
    59             }
    60             LinkedList<String> scripts = new LinkedList<String>();
    61             try {
    62                 ByteCodeToJavaScript.compile(is, out, toProcess, scripts);
    63             } catch (RuntimeException ex) {
    64                 if (out instanceof CharSequence) {
    65                     CharSequence seq = (CharSequence)out;
    66                     int lastBlock = seq.length();
    67                     while (lastBlock-- >= 0) {
    68                         if (seq.charAt(lastBlock) == '{') {
    69                             break;
    70                         }
    71                     }
    72                     throw new IOException("Error while compiling " + name + "\n" 
    73                         + seq.subSequence(lastBlock + 1, seq.length()), ex
    74                     );
    75                 } else {
    76                     throw new IOException("Error while compiling " + name + "\n" 
    77                         + out, ex
    78                     );
    79                 }
    80             }
    81             for (String resource : scripts) {
    82                 InputStream emul = GenJS.class.getResourceAsStream(resource);
    83                 if (emul == null) {
    84                     throw new IOException("Can't find " + resource);
    85                 }
    86                 readResource(emul, out);
    87             }
    88         }
    89     }
    90     private static void readResource(InputStream emul, Appendable out) throws IOException {
    91         try {
    92             int state = 0;
    93             for (;;) {
    94                 int ch = emul.read();
    95                 if (ch == -1) {
    96                     break;
    97                 }
    98                 if (ch < 0 || ch > 255) {
    99                     throw new IOException("Invalid char in emulation " + ch);
   100                 }
   101                 switch (state) {
   102                     case 0: 
   103                         if (ch == '/') {
   104                             state = 1;
   105                         } else {
   106                             out.append((char)ch);
   107                         }
   108                         break;
   109                     case 1:
   110                         if (ch == '*') {
   111                             state = 2;
   112                         } else {
   113                             out.append('/').append((char)ch);
   114                             state = 0;
   115                         }
   116                         break;
   117                     case 2:
   118                         if (ch == '*') {
   119                             state = 3;
   120                         }
   121                         break;
   122                     case 3:
   123                         if (ch == '/') {
   124                             state = 0;
   125                         } else {
   126                             state = 2;
   127                         }
   128                         break;
   129                 }
   130             }
   131         } finally {
   132             emul.close();
   133         }
   134     }
   135     
   136 }