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