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