1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.File;
  25 import java.io.IOException;
  26 import java.io.UncheckedIOException;
  27 import java.nio.file.Files;
  28 import java.nio.file.Path;
  29 import java.nio.file.Paths;
  30 import java.util.ArrayList;
  31 import java.util.Collections;
  32 import java.util.HashMap;
  33 import java.util.HashSet;
  34 import java.util.List;
  35 import java.util.Map;
  36 import java.util.Set;
  37 import jdk.tools.jlink.Jlink;
  38 import jdk.tools.jlink.Jlink.JlinkConfiguration;
  39 import jdk.tools.jlink.Jlink.PluginsConfiguration;
  40 import jdk.tools.jlink.builder.DefaultImageBuilder;
  41 import jdk.tools.jlink.plugin.ExecutableImage;
  42 import jdk.tools.jlink.plugin.Pool;
  43 import jdk.tools.jlink.plugin.PostProcessorPlugin;
  44 import jdk.tools.jlink.plugin.TransformerPlugin;
  45 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
  46 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
  47 import jdk.tools.jlink.plugin.Plugin;
  48 
  49 import tests.Helper;
  50 import tests.JImageGenerator;
  51 
  52 /*
  53  * @test
  54  * @summary Test integration API
  55  * @author Jean-Francois Denise
  56  * @library ../lib
  57  * @modules java.base/jdk.internal.jimage
  58  *          jdk.jdeps/com.sun.tools.classfile
  59  *          jdk.jlink/jdk.tools.jlink.internal
  60  *          jdk.jlink/jdk.tools.jlink.internal.plugins
  61  *          jdk.jlink/jdk.tools.jmod
  62  *          jdk.jlink/jdk.tools.jimage
  63  *          jdk.compiler
  64  * @build tests.*
  65  * @run main IntegrationTest
  66  */
  67 public class IntegrationTest {
  68 
  69     private static final List<Integer> ordered = new ArrayList<>();
  70 
  71     public static class MyPostProcessor implements PostProcessorPlugin {
  72 
  73         public static final String NAME = "mypostprocessor";
  74 
  75         @Override
  76         public List<String> process(ExecutableImage image) {
  77             try {
  78                 Files.createFile(image.getHome().resolve("toto.txt"));
  79                 return null;
  80             } catch (IOException ex) {
  81                 throw new UncheckedIOException(ex);
  82             }
  83         }
  84 
  85         @Override
  86         public String getName() {
  87             return NAME;
  88         }
  89 
  90         @Override
  91         public Set<PluginType> getType() {
  92             Set<PluginType> set = new HashSet<>();
  93             set.add(CATEGORY.PROCESSOR);
  94             return Collections.unmodifiableSet(set);
  95         }
  96 
  97         @Override
  98         public void configure(Map<String, String> config) {
  99             throw new UnsupportedOperationException("Shouldn't be called");
 100         }
 101     }
 102 
 103     public static class MyPlugin1 implements TransformerPlugin {
 104 
 105         Integer index;
 106         Set<String> after;
 107         Set<String> before;
 108 
 109         private MyPlugin1(Integer index, Set<String> after, Set<String> before) {
 110             this.index = index;
 111             this.after = after;
 112             this.before = before;
 113         }
 114 
 115         @Override
 116         public Set<String> isAfter() {
 117             return after;
 118         }
 119 
 120         @Override
 121         public Set<String> isBefore() {
 122             return before;
 123         }
 124 
 125         @Override
 126         public String getName() {
 127             return NAME + index;
 128         }
 129 
 130         @Override
 131         public void visit(Pool in, Pool out) {
 132             System.err.println(NAME + index);
 133             ordered.add(index);
 134             in.visit((file) -> {
 135                 return file;
 136             }, out);
 137         }
 138 
 139         @Override
 140         public Set<PluginType> getType() {
 141             Set<PluginType> set = new HashSet<>();
 142             set.add(CATEGORY.TRANSFORMER);
 143             return Collections.unmodifiableSet(set);
 144         }
 145 
 146         @Override
 147         public String getDescription() {
 148             return null;
 149         }
 150 
 151         @Override
 152         public String getOption() {
 153             return null;
 154         }
 155         static final String NAME = "myprovider";
 156         static final String INDEX = "INDEX";
 157 
 158         @Override
 159         public void configure(Map<String, String> config) {
 160             throw new UnsupportedOperationException("Shouldn't be called");
 161         }
 162     }
 163 
 164     public static void main(String[] args) throws Exception {
 165 
 166         Helper helper = Helper.newHelper();
 167         if (helper == null) {
 168             System.err.println("Test not run");
 169             return;
 170         }
 171         apitest();
 172         test();
 173         testOrder();
 174         testCycleOrder();
 175     }
 176 
 177     private static void apitest() throws Exception {
 178         boolean failed = false;
 179         Jlink jl = new Jlink();
 180 
 181         try {
 182             jl.build(null);
 183             failed = true;
 184         } catch (Exception ex) {
 185             // XXX OK
 186         }
 187         if (failed) {
 188             throw new Exception("Should have failed");
 189         }
 190         System.out.println(jl);
 191 
 192         JlinkConfiguration config
 193                 = new JlinkConfiguration(null, null, null, null);
 194 
 195         System.out.println(config);
 196 
 197         Plugin p = Jlink.newPlugin("toto", Collections.emptyMap(), null);
 198         if (p != null) {
 199             throw new Exception("Plugin should be null");
 200         }
 201 
 202         Plugin p2 = Jlink.newPlugin("compress", Collections.emptyMap(), null);
 203         if (p2 == null) {
 204             throw new Exception("Plugin should not be null");
 205         }
 206     }
 207 
 208     private static void test() throws Exception {
 209         Jlink jlink = new Jlink();
 210         Path output = Paths.get("integrationout");
 211         List<Path> modulePaths = new ArrayList<>();
 212         File jmods
 213                 = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
 214         modulePaths.add(jmods.toPath());
 215         Set<String> mods = new HashSet<>();
 216         mods.add("java.management");
 217         Set<String> limits = new HashSet<>();
 218         limits.add("java.management");
 219         JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
 220                 modulePaths, mods, limits, null);
 221 
 222         List<Plugin> lst = new ArrayList<>();
 223 
 224         //Strip debug
 225         {
 226             Map<String, String> config1 = new HashMap<>();
 227             config1.put(StripDebugPlugin.NAME, "");
 228             Plugin strip = Jlink.newPlugin("strip-debug", config1, null);
 229             lst.add(strip);
 230         }
 231         // compress
 232         {
 233             Map<String, String> config1 = new HashMap<>();
 234             config1.put(DefaultCompressPlugin.NAME, "2");
 235             Plugin compress
 236                     = Jlink.newPlugin("compress", config1, null);
 237             lst.add(compress);
 238         }
 239         // Post processor
 240         {
 241             lst.add(new MyPostProcessor());
 242         }
 243         // Image builder
 244         DefaultImageBuilder builder = new DefaultImageBuilder(true, output);
 245         PluginsConfiguration plugins
 246                 = new Jlink.PluginsConfiguration(lst, builder, null);
 247 
 248         jlink.build(config, plugins);
 249 
 250         if (!Files.exists(output)) {
 251             throw new AssertionError("Directory not created");
 252         }
 253         File jimage = new File(output.toString(), "lib" + File.separator + "modules");
 254         if (!jimage.exists()) {
 255             throw new AssertionError("jimage not generated");
 256         }
 257         File bom = new File(output.toString(), "bom");
 258         if (!bom.exists()) {
 259             throw new AssertionError("bom not generated");
 260         }
 261         File release = new File(output.toString(), "release");
 262         if (!release.exists()) {
 263             throw new AssertionError("release not generated");
 264         }
 265 
 266         if (!Files.exists(output.resolve("toto.txt"))) {
 267             throw new AssertionError("Post processing not called");
 268         }
 269 
 270     }
 271 
 272     private static void testOrder() throws Exception {
 273         Jlink jlink = new Jlink();
 274         Path output = Paths.get("integrationout2");
 275         List<Path> modulePaths = new ArrayList<>();
 276         File jmods
 277                 = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
 278         modulePaths.add(jmods.toPath());
 279         Set<String> mods = new HashSet<>();
 280         mods.add("java.management");
 281         Set<String> limits = new HashSet<>();
 282         limits.add("java.management");
 283         JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
 284                 modulePaths, mods, limits, null);
 285 
 286         List<Plugin> lst = new ArrayList<>();
 287 
 288         // Order is Plug1>Plug2>Plug3
 289         // Plug1
 290 
 291 
 292         // TRANSFORMER 3, must be after 2.
 293         {
 294             Set<String> after = new HashSet<>();
 295             after.add(MyPlugin1.NAME+"2");
 296             lst.add(new MyPlugin1(3, after, Collections.emptySet()));
 297         }
 298 
 299         // TRANSFORMER 2, must be after 1.
 300         {
 301             Set<String> after = new HashSet<>();
 302             after.add(MyPlugin1.NAME+"1");
 303             lst.add(new MyPlugin1(2, after, Collections.emptySet()));
 304         }
 305 
 306         // TRANSFORMER 1
 307         {
 308             Set<String> before = new HashSet<>();
 309             before.add(MyPlugin1.NAME+"2");
 310             lst.add(new MyPlugin1(1, Collections.emptySet(), before));
 311         }
 312 
 313         // Image builder
 314         DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
 315         PluginsConfiguration plugins
 316                 = new Jlink.PluginsConfiguration(lst, builder, null);
 317 
 318         jlink.build(config, plugins);
 319 
 320         if (ordered.isEmpty()) {
 321             throw new AssertionError("Plugins not called");
 322         }
 323         List<Integer> clone = new ArrayList<>();
 324         clone.addAll(ordered);
 325         Collections.sort(clone);
 326         if (!clone.equals(ordered)) {
 327             throw new AssertionError("Ordered is not properly sorted" + ordered);
 328         }
 329     }
 330 
 331     private static void testCycleOrder() throws Exception {
 332         Jlink jlink = new Jlink();
 333         Path output = Paths.get("integrationout3");
 334         List<Path> modulePaths = new ArrayList<>();
 335         File jmods
 336                 = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
 337         modulePaths.add(jmods.toPath());
 338         Set<String> mods = new HashSet<>();
 339         mods.add("java.management");
 340         Set<String> limits = new HashSet<>();
 341         limits.add("java.management");
 342         JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
 343                 modulePaths, mods, limits, null);
 344 
 345         List<Plugin> lst = new ArrayList<>();
 346 
 347         // packager 1
 348         {
 349             Set<String> before = new HashSet<>();
 350             before.add(MyPlugin1.NAME+"2");
 351             lst.add(new MyPlugin1(1, Collections.emptySet(), before));
 352         }
 353 
 354         // packager 2
 355         {
 356             Set<String> before = new HashSet<>();
 357             before.add(MyPlugin1.NAME+"1");
 358             lst.add(new MyPlugin1(2, Collections.emptySet(), before));
 359         }
 360 
 361         // Image builder
 362         DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
 363         PluginsConfiguration plugins
 364                 = new Jlink.PluginsConfiguration(lst, builder, null);
 365         boolean failed = false;
 366         try {
 367             jlink.build(config, plugins);
 368             failed = true;
 369         } catch (Exception ex) {
 370             // XXX OK
 371         }
 372         if (failed) {
 373             throw new AssertionError("Should have failed");
 374         }
 375     }
 376 }