vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 30 Sep 2012 19:40:04 -0700
branchstrings
changeset 90 e7be3cb29a72
parent 36 95330dd02c47
child 91 f3b685bd7243
permissions -rw-r--r--
Separate the read method
     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/String")
    52                 && !name.equals("java/lang/StringBuilder")
    53                 && !name.equals("java/lang/AbstractStringBuilder")
    54             ) {
    55                 continue;
    56             }
    57             InputStream emul = GenJS.class.getResourceAsStream("emulation/" + name.replace('/', '_') + ".js");
    58             if (emul != null) {
    59                 readResource(emul, out);
    60                 continue;
    61             }
    62             
    63             InputStream is = GenJS.class.getClassLoader().getResourceAsStream(name + ".class");
    64             if (is == null) {
    65                 throw new IOException("Can't find class " + name); 
    66             }
    67             try {
    68                 ByteCodeToJavaScript.compile(is, out, toProcess);
    69             } catch (RuntimeException ex) {
    70                 if (out instanceof CharSequence) {
    71                     CharSequence seq = (CharSequence)out;
    72                     int lastBlock = seq.length();
    73                     while (lastBlock-- >= 0) {
    74                         if (seq.charAt(lastBlock) == '{') {
    75                             break;
    76                         }
    77                     }
    78                     throw new IOException("Error while compiling " + name + "\n" 
    79                         + seq.subSequence(lastBlock + 1, seq.length()), ex
    80                     );
    81                 } else {
    82                     throw new IOException("Error while compiling " + name + "\n" 
    83                         + out, ex
    84                     );
    85                 }
    86             }
    87         }
    88     }
    89     private static void readResource(InputStream emul, Appendable out) throws IOException {
    90         try {
    91             int state = 0;
    92             for (;;) {
    93                 int ch = emul.read();
    94                 if (ch == -1) {
    95                     break;
    96                 }
    97                 if (ch < 0 || ch > 255) {
    98                     throw new IOException("Invalid char in emulation " + ch);
    99                 }
   100                 switch (state) {
   101                     case 0: 
   102                         if (ch == '/') {
   103                             state = 1;
   104                         } else {
   105                             out.append((char)ch);
   106                         }
   107                         break;
   108                     case 1:
   109                         if (ch == '*') {
   110                             state = 2;
   111                         } else {
   112                             out.append('/').append((char)ch);
   113                             state = 0;
   114                         }
   115                         break;
   116                     case 2:
   117                         if (ch == '*') {
   118                             state = 3;
   119                         }
   120                         break;
   121                     case 3:
   122                         if (ch == '/') {
   123                             state = 0;
   124                         } else {
   125                             state = 2;
   126                         }
   127                         break;
   128                 }
   129             }
   130         } finally {
   131             emul.close();
   132         }
   133     }
   134     
   135 }