vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
branchjavap
changeset 162 70e7710a65dc
parent 156 3bb1a148a795
child 167 77f7135b6eb1
     1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Nov 12 21:05:23 2012 +0100
     1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Nov 16 07:36:32 2012 +0100
     1.3 @@ -19,9 +19,6 @@
     1.4  
     1.5  import java.io.IOException;
     1.6  import java.io.InputStream;
     1.7 -import java.util.ArrayList;
     1.8 -import java.util.Collection;
     1.9 -import java.util.List;
    1.10  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    1.11  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    1.12  import sun.tools.javap.AnnotationParser;
    1.13 @@ -34,63 +31,57 @@
    1.14   *
    1.15   * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.16   */
    1.17 -public final class ByteCodeToJavaScript {
    1.18 -    private final ClassData jc;
    1.19 +public abstract class ByteCodeToJavaScript {
    1.20 +    private ClassData jc;
    1.21      private final Appendable out;
    1.22 -    private final Collection<? super String> references;
    1.23  
    1.24 -    private ByteCodeToJavaScript(
    1.25 -        ClassData jc, Appendable out, Collection<? super String> references
    1.26 -    ) {
    1.27 -        this.jc = jc;
    1.28 +    protected ByteCodeToJavaScript(Appendable out) {
    1.29          this.out = out;
    1.30 -        this.references = references;
    1.31      }
    1.32 +    
    1.33 +    /* Collects additional required resources.
    1.34 +     * 
    1.35 +     * @param internalClassName classes that were referenced and should be loaded in order the
    1.36 +     *   generated JavaScript code works properly. The names are in internal 
    1.37 +     *   JVM form so String is <code>java/lang/String</code>. 
    1.38 +     */
    1.39 +    protected abstract boolean requireReference(String internalClassName);
    1.40 +    
    1.41 +    /*
    1.42 +     * @param resourcePath name of resources to read
    1.43 +     */
    1.44 +    protected abstract void requireScript(String resourcePath);
    1.45  
    1.46      /**
    1.47       * Converts a given class file to a JavaScript version.
    1.48       *
    1.49       * @param classFile input stream with code of the .class file
    1.50 -     * @param out a {@link StringBuilder} or similar to generate the output to
    1.51 -     * @param references a write only collection where the system adds list of
    1.52 -     *   other classes that were referenced and should be loaded in order the
    1.53 -     *   generated JavaScript code works properly. The names are in internal 
    1.54 -     *   JVM form so String is <code>java/lang/String</code>. Can be <code>null</code>
    1.55 -     *   if one is not interested in knowing references
    1.56 -     * @param scripts write only collection with names of resources to read
    1.57       * @return the initialization code for this class, if any. Otherwise <code>null</code>
    1.58       * 
    1.59       * @throws IOException if something goes wrong during read or write or translating
    1.60       */
    1.61      
    1.62 -    public static String compile(
    1.63 -        InputStream classFile, Appendable out,
    1.64 -        Collection<? super String> references,
    1.65 -        Collection<? super String> scripts
    1.66 -    ) throws IOException {
    1.67 -        ClassData jc = new ClassData(classFile);
    1.68 +    public String compile(InputStream classFile) throws IOException {
    1.69 +        this.jc = new ClassData(classFile);
    1.70          byte[] arrData = jc.findAnnotationData(true);
    1.71          String[] arr = findAnnotation(arrData, jc, ExtraJavaScript.class.getName(), "resource", "processByteCode");
    1.72          if (arr != null) {
    1.73 -            scripts.add(arr[0]);
    1.74 +            requireScript(arr[0]);
    1.75              if ("0".equals(arr[1])) {
    1.76                  return null;
    1.77              }
    1.78          }
    1.79 -        ByteCodeToJavaScript compiler = new ByteCodeToJavaScript(
    1.80 -            jc, out, references
    1.81 -        );
    1.82 -        List<String> toInitilize = new ArrayList<String>();
    1.83 +        StringArray toInitilize = new StringArray();
    1.84          for (MethodData m : jc.getMethods()) {
    1.85              if (m.isStatic()) {
    1.86 -                compiler.generateStaticMethod(m, toInitilize);
    1.87 +                generateStaticMethod(m, toInitilize);
    1.88              } else {
    1.89 -                compiler.generateInstanceMethod(m);
    1.90 +                generateInstanceMethod(m);
    1.91              }
    1.92          }
    1.93          for (FieldData v : jc.getFields()) {
    1.94              if (v.isStatic()) {
    1.95 -                compiler.generateStaticField(v);
    1.96 +                generateStaticField(v);
    1.97              }
    1.98          }
    1.99          
   1.100 @@ -119,7 +110,7 @@
   1.101          }
   1.102          for (MethodData m : jc.getMethods()) {
   1.103              if (!m.getName().contains("<init>") && !m.getName().contains("<cinit>")) {
   1.104 -                compiler.generateMethodReference("\n  p.", m);
   1.105 +                generateMethodReference("\n  p.", m);
   1.106              }
   1.107          }
   1.108          out.append("\n  p.$instOf_").append(className).append(" = true;");
   1.109 @@ -130,12 +121,12 @@
   1.110          out.append("\n}");
   1.111          out.append("\n").append(className).append("_proto();");
   1.112          StringBuilder sb = new StringBuilder();
   1.113 -        for (String init : toInitilize) {
   1.114 +        for (String init : toInitilize.toArray()) {
   1.115              sb.append("\n").append(init).append("();");
   1.116          }
   1.117          return sb.toString();
   1.118      }
   1.119 -    private void generateStaticMethod(MethodData m, List<String> toInitilize) throws IOException {
   1.120 +    private void generateStaticMethod(MethodData m, StringArray toInitilize) throws IOException {
   1.121          if (javaScriptBody(m, true)) {
   1.122              return;
   1.123          }
   1.124 @@ -952,10 +943,8 @@
   1.125      }
   1.126      
   1.127      private void addReference(String cn) throws IOException {
   1.128 -        if (references != null) {
   1.129 -            if (references.add(cn)) {
   1.130 -                out.append(" /* needs ").append(cn).append(" */");
   1.131 -            }
   1.132 +        if (requireReference(cn)) {
   1.133 +            out.append(" /* needs ").append(cn).append(" */");
   1.134          }
   1.135      }
   1.136