rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/AheadOfTime.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 26 Jun 2014 07:42:54 +0200
changeset 1638 a84f511654ae
parent 1636 eb97a082741b
child 1694 615bae775606
permissions -rw-r--r--
Using Object.defineProperty to specify non-enumerable properties on Object
jaroslav@1584
     1
/**
jaroslav@1584
     2
 * Back 2 Browser Bytecode Translator
jaroslav@1584
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@1584
     4
 *
jaroslav@1584
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@1584
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@1584
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@1584
     8
 *
jaroslav@1584
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@1584
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@1584
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@1584
    12
 * GNU General Public License for more details.
jaroslav@1584
    13
 *
jaroslav@1584
    14
 * You should have received a copy of the GNU General Public License
jaroslav@1584
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@1584
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@1584
    17
 */
jaroslav@1584
    18
jaroslav@1584
    19
package org.apidesign.bck2brwsr.mojo;
jaroslav@1584
    20
jaroslav@1584
    21
import java.io.File;
jaroslav@1584
    22
import java.io.FileWriter;
jaroslav@1584
    23
import java.io.IOException;
jaroslav@1584
    24
import java.io.InputStream;
jaroslav@1584
    25
import java.net.MalformedURLException;
jaroslav@1584
    26
import java.net.URL;
jaroslav@1584
    27
import java.net.URLClassLoader;
jaroslav@1584
    28
import java.util.ArrayList;
jaroslav@1584
    29
import java.util.Collection;
jaroslav@1584
    30
import java.util.List;
jaroslav@1584
    31
import org.apache.maven.artifact.Artifact;
jaroslav@1584
    32
import org.apache.maven.plugin.AbstractMojo;
jaroslav@1584
    33
import org.apache.maven.plugin.MojoExecutionException;
jaroslav@1584
    34
import org.apache.maven.plugin.MojoFailureException;
jaroslav@1584
    35
import org.apache.maven.plugins.annotations.LifecyclePhase;
jaroslav@1584
    36
import org.apache.maven.plugins.annotations.Mojo;
jaroslav@1584
    37
import org.apache.maven.plugins.annotations.Parameter;
jaroslav@1584
    38
import org.apache.maven.plugins.annotations.ResolutionScope;
jaroslav@1584
    39
import org.apache.maven.project.MavenProject;
jaroslav@1599
    40
import org.apidesign.bck2brwsr.aot.Bck2BrwsrJars;
jaroslav@1584
    41
import org.apidesign.vm4brwsr.Bck2Brwsr;
jaroslav@1584
    42
import org.apidesign.vm4brwsr.ObfuscationLevel;
jaroslav@1584
    43
jaroslav@1584
    44
/**
jaroslav@1584
    45
 *
jaroslav@1584
    46
 * @author Jaroslav Tulach
jaroslav@1584
    47
 * @since 0.9
jaroslav@1584
    48
 */
jaroslav@1584
    49
@Mojo(name = "aot",
jaroslav@1584
    50
    requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
jaroslav@1584
    51
    defaultPhase = LifecyclePhase.PACKAGE
jaroslav@1584
    52
)
jaroslav@1584
    53
public class AheadOfTime extends AbstractMojo {
jaroslav@1584
    54
    @Parameter(defaultValue = "${project}")
jaroslav@1584
    55
    private MavenProject prj;
jaroslav@1604
    56
    
jaroslav@1604
    57
    @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}.jar")
jaroslav@1604
    58
    private File mainJar;
jaroslav@1584
    59
jaroslav@1604
    60
    @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}.js")
jaroslav@1604
    61
    private File mainJavaScript;
jaroslav@1604
    62
    
jaroslav@1604
    63
    @Parameter
jaroslav@1604
    64
    private String[] exports;
jaroslav@1604
    65
    
jaroslav@1584
    66
    /**
jaroslav@1584
    67
     * Directory where to generate ahead-of-time JavaScript files for
jaroslav@1584
    68
     * required libraries.
jaroslav@1584
    69
     */
jaroslav@1604
    70
    @Parameter(defaultValue = "lib")
jaroslav@1604
    71
    private String classPathPrefix;
jaroslav@1584
    72
jaroslav@1584
    73
    /** Root JavaScript file to generate */
jaroslav@1584
    74
    @Parameter(defaultValue="${project.build.directory}/bck2brwsr.js")
jaroslav@1584
    75
    private File vm;
jaroslav@1584
    76
    
jaroslav@1584
    77
    /**
jaroslav@1584
    78
     * The obfuscation level for the generated JavaScript file.
jaroslav@1584
    79
     *
jaroslav@1584
    80
     * @since 0.5
jaroslav@1584
    81
     */
jaroslav@1584
    82
    @Parameter(defaultValue = "NONE")
jaroslav@1584
    83
    private ObfuscationLevel obfuscation;
jaroslav@1584
    84
    
jaroslav@1584
    85
    @Override
jaroslav@1584
    86
    public void execute() throws MojoExecutionException, MojoFailureException {
jaroslav@1594
    87
        URLClassLoader loader;
jaroslav@1584
    88
        try {
jaroslav@1604
    89
            loader = buildClassLoader(mainJar, prj.getArtifacts());
jaroslav@1594
    90
        } catch (MalformedURLException ex) {
jaroslav@1594
    91
            throw new MojoFailureException("Can't initialize classloader");
jaroslav@1594
    92
        }
jaroslav@1594
    93
        for (Artifact a : prj.getArtifacts()) {
jaroslav@1594
    94
            if (a.getFile() == null) {
jaroslav@1594
    95
                continue;
jaroslav@1594
    96
            }
jaroslav@1594
    97
            String n = a.getFile().getName();
jaroslav@1594
    98
            if (!n.endsWith(".jar")) {
jaroslav@1594
    99
                continue;
jaroslav@1594
   100
            }
jaroslav@1594
   101
            if ("provided".equals(a.getScope())) {
jaroslav@1594
   102
                continue;
jaroslav@1594
   103
            }
jaroslav@1604
   104
            File aot = new File(prj.getBuild().getDirectory(), classPathPrefix);
jaroslav@1594
   105
            aot.mkdirs();
jaroslav@1594
   106
            File js = new File(aot, n.substring(0, n.length() - 4) + ".js");
jaroslav@1618
   107
            if (js.exists()) {
jaroslav@1618
   108
                getLog().info("Skipping " + js + " as it already exists.");
jaroslav@1618
   109
                continue;
jaroslav@1618
   110
            }
jaroslav@1594
   111
            try {
jaroslav@1618
   112
                getLog().info("Generating " + js);
jaroslav@1584
   113
                aotLibrary(a, js , loader);
jaroslav@1594
   114
            } catch (IOException ex) {
jaroslav@1594
   115
                throw new MojoFailureException("Can't compile" + a.getFile(), ex);
jaroslav@1584
   116
            }
jaroslav@1594
   117
        }
jaroslav@1604
   118
        
jaroslav@1604
   119
        try {
jaroslav@1618
   120
            if (mainJavaScript.exists()) {
jaroslav@1618
   121
                getLog().info("Skipping " + mainJavaScript + " as it already exists.");
jaroslav@1618
   122
            } else {
jaroslav@1618
   123
                getLog().info("Generating " + mainJavaScript);
jaroslav@1618
   124
                Bck2Brwsr c = Bck2BrwsrJars.configureFrom(null, mainJar);
jaroslav@1618
   125
                if (exports != null) {
jaroslav@1618
   126
                    for (String e : exports) {
jaroslav@1618
   127
                        c = c.addExported(e.replace('.', '/'));
jaroslav@1618
   128
                    }
jaroslav@1604
   129
                }
jaroslav@1618
   130
                FileWriter w = new FileWriter(mainJavaScript);
jaroslav@1618
   131
                c.
jaroslav@1618
   132
                        obfuscation(obfuscation).
jaroslav@1618
   133
                        resources(loader).
jaroslav@1618
   134
                        generate(w);
jaroslav@1618
   135
                w.close();
jaroslav@1604
   136
            }
jaroslav@1604
   137
        } catch (IOException ex) {
jaroslav@1604
   138
            throw new MojoFailureException("Cannot generate script for " + mainJar, ex);
jaroslav@1604
   139
        }
jaroslav@1584
   140
            
jaroslav@1594
   141
        try {
jaroslav@1584
   142
            FileWriter w = new FileWriter(vm);
jaroslav@1584
   143
            Bck2Brwsr.newCompiler().
jaroslav@1584
   144
                    obfuscation(obfuscation).
jaroslav@1584
   145
                    standalone(false).
jaroslav@1584
   146
                    resources(new Bck2Brwsr.Resources() {
jaroslav@1584
   147
jaroslav@1584
   148
                @Override
jaroslav@1584
   149
                public InputStream get(String resource) throws IOException {
jaroslav@1584
   150
                    return null;
jaroslav@1584
   151
                }
jaroslav@1584
   152
            }).
jaroslav@1584
   153
                    generate(w);
jaroslav@1584
   154
            w.close();
jaroslav@1584
   155
            
jaroslav@1584
   156
        } catch (IOException ex) {
jaroslav@1584
   157
            throw new MojoExecutionException("Can't compile", ex);
jaroslav@1584
   158
        }
jaroslav@1584
   159
    }
jaroslav@1584
   160
jaroslav@1584
   161
    private void aotLibrary(Artifact a, File js, URLClassLoader loader) throws IOException {
jaroslav@1584
   162
        FileWriter w = new FileWriter(js);
jaroslav@1599
   163
        Bck2Brwsr c = Bck2BrwsrJars.configureFrom(null, a.getFile());
jaroslav@1599
   164
        c.
jaroslav@1599
   165
            obfuscation(obfuscation).
jaroslav@1599
   166
            resources(loader).
jaroslav@1599
   167
            generate(w);
jaroslav@1584
   168
        w.close();
jaroslav@1584
   169
    }
jaroslav@1584
   170
    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
jaroslav@1584
   171
        List<URL> arr = new ArrayList<URL>();
jaroslav@1584
   172
        if (root != null) {
jaroslav@1584
   173
            arr.add(root.toURI().toURL());
jaroslav@1584
   174
        }
jaroslav@1584
   175
        for (Artifact a : deps) {
jaroslav@1584
   176
            if (a.getFile() != null) {
jaroslav@1584
   177
                arr.add(a.getFile().toURI().toURL());
jaroslav@1584
   178
            }
jaroslav@1584
   179
        }
jaroslav@1584
   180
        return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
jaroslav@1584
   181
    }
jaroslav@1584
   182
}