rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/AOTLibrary.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Mar 2016 05:55:43 +0200
changeset 1914 88b00e03fc8f
parent 1824 9fb23d7831da
child 1916 a9d37af23a00
permissions -rw-r--r--
Introducing vmtest.precompiled=<regexp> to verify that bck2brwsr generated resources are really used
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012-2015 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.mojo;
    19 
    20 import java.io.File;
    21 import java.io.FileNotFoundException;
    22 import java.io.FileOutputStream;
    23 import java.io.IOException;
    24 import java.io.OutputStreamWriter;
    25 import java.io.Writer;
    26 import java.net.MalformedURLException;
    27 import java.net.URL;
    28 import java.net.URLClassLoader;
    29 import java.util.ArrayList;
    30 import java.util.Collection;
    31 import java.util.List;
    32 import java.util.jar.Attributes;
    33 import java.util.jar.JarEntry;
    34 import java.util.jar.JarOutputStream;
    35 import java.util.jar.Manifest;
    36 import org.apache.maven.artifact.Artifact;
    37 import org.apache.maven.plugin.AbstractMojo;
    38 import org.apache.maven.plugin.MojoExecutionException;
    39 import org.apache.maven.plugin.MojoFailureException;
    40 import org.apache.maven.plugins.annotations.Component;
    41 import org.apache.maven.plugins.annotations.LifecyclePhase;
    42 import org.apache.maven.plugins.annotations.Mojo;
    43 import org.apache.maven.plugins.annotations.Parameter;
    44 import org.apache.maven.plugins.annotations.ResolutionScope;
    45 import org.apache.maven.project.MavenProject;
    46 import org.apache.maven.project.MavenProjectHelper;
    47 import org.apidesign.bck2brwsr.aot.Bck2BrwsrJars;
    48 import org.apidesign.vm4brwsr.Bck2Brwsr;
    49 import org.apidesign.vm4brwsr.ObfuscationLevel;
    50 
    51 /**
    52  *
    53  * @author Jaroslav Tulach
    54  * @since 0.12
    55  */
    56 @Mojo(name = "library",
    57     requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
    58     defaultPhase = LifecyclePhase.PACKAGE
    59 )
    60 public class AOTLibrary extends AbstractMojo {
    61     @Parameter(defaultValue = "${project}")
    62     private MavenProject prj;
    63 
    64     @Component
    65     private MavenProjectHelper projectHelper;
    66     @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}.jar")
    67     private File mainJar;    
    68     @Parameter(defaultValue = "${project.build.finalName}-min.js")
    69     private String minified;
    70     @Parameter(defaultValue = "${project.build.finalName}-debug.js")
    71     private String debug;
    72     
    73     @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}-bck2brwsr.jar")
    74     private File aotJar;
    75     
    76     @Parameter
    77     private String[] exports;
    78     
    79     @Parameter
    80     private String[] aotDeps;
    81 
    82     @Parameter(defaultValue = "true")
    83     private boolean ignoreBootClassPath;
    84     
    85     /**
    86      * The obfuscation level for the generated minified JavaScript file.
    87      * @since 0.5
    88      */
    89     @Parameter(defaultValue = "FULL")
    90     private ObfuscationLevel obfuscation;
    91     
    92     @Override
    93     public void execute() throws MojoExecutionException, MojoFailureException {
    94         URLClassLoader loader;
    95         try {
    96             loader = buildClassLoader(mainJar, prj.getArtifacts());
    97         } catch (MalformedURLException ex) {
    98             throw new MojoFailureException("Can't initialize classloader");
    99         }
   100 
   101         try {
   102             Manifest m = new Manifest();
   103             if (!"false".equals(minified)) {
   104                 Attributes attr = new Attributes();
   105                 attr.putValue("Bck2BrwsrArtifactId", prj.getArtifactId());
   106                 attr.putValue("Bck2BrwsrGroupId", prj.getGroupId());
   107                 attr.putValue("Bck2BrwsrVersion", prj.getVersion());
   108                 attr.putValue("Bck2BrwsrMinified", "true");
   109                 m.getEntries().put(minified, attr);
   110             }
   111             if (!"false".equals(debug)) {
   112                 Attributes attr = new Attributes();
   113                 attr.putValue("Bck2BrwsrArtifactId", prj.getArtifactId());
   114                 attr.putValue("Bck2BrwsrGroupId", prj.getGroupId());
   115                 attr.putValue("Bck2BrwsrVersion", prj.getVersion());
   116                 attr.putValue("Bck2BrwsrDebug", "true");
   117                 m.getEntries().put(debug, attr);
   118             }
   119             
   120             if (aotDeps != null) {
   121                 for (Artifact a : prj.getArtifacts()) {
   122                     if (!matches(aotDeps, a)) {
   123                         continue;
   124                     }
   125                     
   126                     {
   127                         Attributes attr = new Attributes();
   128                         attr.putValue("Bck2BrwsrArtifactId", a.getArtifactId());
   129                         attr.putValue("Bck2BrwsrGroupId", a.getGroupId());
   130                         attr.putValue("Bck2BrwsrVersion", a.getVersion());
   131                         attr.putValue("Bck2BrwsrDebug", "true");
   132                         m.getEntries().put(artifactName(a, true), attr);
   133                     }
   134                     {
   135                         Attributes attr = new Attributes();
   136                         attr.putValue("Bck2BrwsrArtifactId", a.getArtifactId());
   137                         attr.putValue("Bck2BrwsrGroupId", a.getGroupId());
   138                         attr.putValue("Bck2BrwsrVersion", a.getVersion());
   139                         attr.putValue("Bck2BrwsrMinified", "true");
   140                         m.getEntries().put(artifactName(a, false), attr);
   141                     }
   142                 }
   143             }
   144             
   145 
   146             JarOutputStream os = null;
   147             if (!"false".equals(debug)) {
   148                 if (os == null) {
   149                     os = aotJar(m);
   150                 }
   151                 os.putNextEntry(new JarEntry(debug));
   152                 Writer w = new OutputStreamWriter(os, "UTF-8");
   153                 configureMain(loader).
   154                     obfuscation(ObfuscationLevel.NONE).
   155                     generate(w);
   156                 w.flush();
   157                 os.closeEntry();
   158             }
   159             if (!"false".equals(minified)) {
   160                 if (os == null) {
   161                     os = aotJar(m);
   162                 }
   163                 os.putNextEntry(new JarEntry(minified));
   164             
   165                 Writer w = new OutputStreamWriter(os, "UTF-8");
   166                 configureMain(loader).
   167                     obfuscation(obfuscation).
   168                     generate(w);
   169                 w.flush();
   170                 os.closeEntry();
   171             }
   172             
   173             if (aotDeps != null) {
   174                 for (Artifact a : prj.getArtifacts()) {
   175                     if (!matches(aotDeps, a)) {
   176                         continue;
   177                     }
   178                     getLog().info("Generating bck2brwsr for " + a.getFile());
   179                     Bck2Brwsr c = Bck2BrwsrJars.configureFrom(null, a.getFile(), loader, ignoreBootClassPath);
   180                     if (exports != null) {
   181                         for (String e : exports) {
   182                             c = c.addExported(e.replace('.', '/'));
   183                         }
   184                     }
   185                     {
   186                         if (os == null) {
   187                             os = aotJar(m);
   188                         }
   189                         os.putNextEntry(new JarEntry(artifactName(a, true)));
   190                         Writer w = new OutputStreamWriter(os, "UTF-8");
   191                         c.
   192                             obfuscation(ObfuscationLevel.NONE).
   193                             generate(w);
   194                         w.flush();
   195                         os.closeEntry();
   196                     }
   197                     {
   198                         os.putNextEntry(new JarEntry(artifactName(a, false)));
   199 
   200                         Writer w = new OutputStreamWriter(os, "UTF-8");
   201                         c.
   202                             obfuscation(ObfuscationLevel.FULL).
   203                             generate(w);
   204                         w.flush();
   205                         os.closeEntry();
   206                     }                    
   207                 }
   208             }
   209             if (os != null) {
   210                 os.close();
   211             }
   212             
   213             projectHelper.attachArtifact(prj, "jar", "bck2brwsr", aotJar);
   214         } catch (IOException ex) {
   215             throw new MojoFailureException("Cannot generate script for " + mainJar, ex);
   216         }
   217     }
   218 
   219     private JarOutputStream aotJar(Manifest m) throws IOException, FileNotFoundException {
   220         this.aotJar.getParentFile().mkdirs();
   221         FileOutputStream fos = new FileOutputStream(this.aotJar);
   222         JarOutputStream os = new JarOutputStream(fos, m);
   223         return os;
   224     }
   225 
   226     private Bck2Brwsr configureMain(URLClassLoader loader) throws IOException {
   227         Bck2Brwsr c = Bck2BrwsrJars.configureFrom(null, mainJar, loader, ignoreBootClassPath);
   228         if (exports != null) {
   229             for (String e : exports) {
   230                 c = c.addExported(e.replace('.', '/'));
   231             }
   232         }
   233         return c;
   234     }
   235 
   236     private static String artifactName(Artifact a, boolean debug) {
   237         return a.getGroupId() + "-" + a.getArtifactId() + (debug ? "-debug.js" : "-min.js");
   238     }
   239 
   240     private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
   241         List<URL> arr = new ArrayList<URL>();
   242         if (root != null) {
   243             arr.add(root.toURI().toURL());
   244         }
   245         for (Artifact a : deps) {
   246             if (a.getFile() != null) {
   247                 arr.add(a.getFile().toURI().toURL());
   248             }
   249         }
   250         return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
   251     }
   252 
   253     private static boolean matches(String[] aotDeps, Artifact a) {
   254         for (String d : aotDeps) {
   255             String[] parts = d.split(":");
   256             for (int i = 0; i < parts.length; i++) {
   257                 if ("*".equals(parts[i])) {
   258                     parts[i] = null;
   259                 }
   260             }
   261             
   262             if (parts[0] != null && !parts[0].equals(a.getGroupId())) {
   263                 continue;
   264             }
   265             if (parts[1] != null && !parts[1].equals(a.getArtifactId())) {
   266                 continue;
   267             }
   268             if (parts.length > 2 && parts[2] != null && !parts[2].equals(a.getClassifier())) {
   269                 continue;
   270             }
   271             return true;
   272         }
   273         return false;
   274     }
   275 }