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 /*
  25  * @test
  26  * @summary Test order of plugins
  27  * @author Jean-Francois Denise
  28  * @library ../../lib
  29  * @modules java.base/jdk.internal.jimage
  30  *          jdk.jdeps/com.sun.tools.classfile
  31  *          jdk.jlink/jdk.tools.jlink
  32  *          jdk.jlink/jdk.tools.jlink.internal
  33  *          jdk.jlink/jdk.tools.jmod
  34  *          jdk.jlink/jdk.tools.jimage
  35  *          jdk.compiler
  36  * @build tests.*
  37  * @run main/othervm PluginOrderTest
  38  */
  39 import java.io.IOException;
  40 import java.nio.ByteBuffer;
  41 import java.nio.ByteOrder;
  42 import java.util.ArrayList;
  43 import java.util.Arrays;
  44 import java.util.Collections;
  45 import java.util.List;
  46 import java.util.Map;
  47 
  48 import jdk.tools.jlink.internal.ImagePluginConfiguration;
  49 import jdk.tools.jlink.internal.ImagePluginProviderRepository;
  50 import jdk.tools.jlink.internal.ImagePluginStack;
  51 import jdk.tools.jlink.internal.ResourcePoolImpl;
  52 import jdk.tools.jlink.plugins.CmdResourcePluginProvider;
  53 import jdk.tools.jlink.plugins.Jlink.PluginsConfiguration;
  54 import jdk.tools.jlink.plugins.Jlink.StackedPluginConfiguration;
  55 import jdk.tools.jlink.plugins.PluginProvider;
  56 import jdk.tools.jlink.plugins.ResourcePlugin;
  57 import jdk.tools.jlink.plugins.ResourcePool;
  58 import jdk.tools.jlink.plugins.ResourcePool.Visitor;
  59 import jdk.tools.jlink.plugins.StringTable;
  60 
  61 import tests.Helper;
  62 import tests.Result;
  63 
  64 public class PluginOrderTest {
  65 
  66     public static void main(String[] args) throws Exception {
  67         new PluginOrderTest().test();
  68     }
  69 
  70     public void test() throws Exception {
  71         List<String> order = new ArrayList<>();
  72         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin1_F",
  73                 PluginProvider.FILTER, order));
  74         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin2_F",
  75                 PluginProvider.FILTER, order));
  76         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin3_F",
  77                 PluginProvider.FILTER, order));
  78         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin4_F",
  79                 PluginProvider.FILTER, order));
  80 
  81         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin1_T",
  82                 PluginProvider.TRANSFORMER, order));
  83         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin2_T",
  84                 PluginProvider.TRANSFORMER, order));
  85         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin3_T",
  86                 PluginProvider.TRANSFORMER, order));
  87         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin4_T",
  88                 PluginProvider.TRANSFORMER, order));
  89 
  90         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin1_S",
  91                 PluginProvider.SORTER, order));
  92         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin2_S",
  93                 PluginProvider.SORTER, order));
  94         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin3_S",
  95                 PluginProvider.SORTER, order));
  96         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin4_S",
  97                 PluginProvider.SORTER, order));
  98 
  99         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin1_C",
 100                 PluginProvider.COMPRESSOR, order));
 101         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin2_C",
 102                 PluginProvider.COMPRESSOR, order));
 103         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin3_C",
 104                 PluginProvider.COMPRESSOR, order));
 105         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin4_C",
 106                 PluginProvider.COMPRESSOR, order));
 107 
 108         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin1_A",
 109                 null, order));
 110         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin2_A",
 111                 null, order));
 112         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin3_A",
 113                 null, order));
 114         ImagePluginProviderRepository.registerPluginProvider(new PProvider("plugin4_A",
 115                 null, order));
 116 
 117         test1(order);
 118 
 119         test2(order);
 120 
 121         test3(order);
 122 
 123         test4(order);
 124 
 125         test5(order);
 126 
 127         test6(order);
 128 
 129         test7(order);
 130 
 131         testAbs(order);
 132 
 133         test8(order);
 134 
 135         test9(order);
 136     }
 137 
 138     private void check(PluginsConfiguration config, List<String> expected, List<String> order)
 139             throws Exception {
 140         order.clear();
 141         ImagePluginStack plugins = ImagePluginConfiguration.parseConfiguration(config);
 142         ResourcePoolImpl pool = new ResourcePoolImpl(ByteOrder.nativeOrder());
 143         pool.addResource(new ResourcePool.Resource("/mod/com/foo/bar/A.somthing",
 144                 ByteBuffer.allocate(0)));
 145         plugins.visitResources(pool, new StringTable() {
 146 
 147             @Override
 148             public int addString(String str) {
 149                 return -1;
 150             }
 151 
 152             @Override
 153             public String getString(int id) {
 154                 throw new UnsupportedOperationException("Not supported yet.");
 155             }
 156         });
 157         if (!order.equals(expected)) {
 158             throw new Exception("plugins not called in right order. Expected "
 159                     + expected + " actual " + order);
 160         }
 161         System.err.println("Gathered plugins: " + order);
 162     }
 163 
 164     private PluginsConfiguration createConfig(String... nameIndexAbs) {
 165         List<StackedPluginConfiguration> lst = new ArrayList<>();
 166         for (String s : nameIndexAbs) {
 167             String name = s.substring(0, s.indexOf(":"));
 168             int sep = s.indexOf("/");
 169             int index = Integer.valueOf(s.substring(s.indexOf(":") + 1, sep));
 170             boolean absolute = Boolean.valueOf(s.substring(sep + 1));
 171             lst.add(new StackedPluginConfiguration(name, index,
 172                     absolute, Collections.emptyMap()));
 173         }
 174         return new PluginsConfiguration(lst, Collections.emptyList(), null);
 175     }
 176 
 177     private void test1(List<String> order) throws Exception {
 178 
 179         Helper helper = Helper.newHelper();
 180         if (helper == null) {
 181             System.err.println("test1 not run");
 182             return;
 183         }
 184         helper.generateDefaultModules();
 185 
 186         {
 187             order.clear();
 188             String[] userOptions = {"--plugin1_C", "--plugin2_C", "--plugin1_S", "--plugin2_S", "--plugin1_T", "--plugin2_T", "--plugin1_F", "--plugin2_F"};
 189             String moduleName = "order1";
 190             helper.generateDefaultJModule(moduleName, "composite2");
 191             Result res = helper.generateDefaultImage(userOptions, moduleName);
 192             res.assertSuccess();
 193             if (!order.equals(Arrays.asList("plugin1_F", "plugin2_F", "plugin1_T", "plugin2_T", "plugin1_S", "plugin2_S", "plugin1_C", "plugin2_C"))) {
 194                 throw new Exception("plugins not called in right order. " + order);
 195             }
 196         }
 197 
 198         {
 199             order.clear();
 200             String[] userOptions = {"--plugin1_F:2", "--plugin2_F:1"};
 201             String moduleName = "order2";
 202             helper.generateDefaultJModule(moduleName, "composite2");
 203             Result res = helper.generateDefaultImage(userOptions, moduleName);
 204             res.assertSuccess();
 205             if (!order.equals(Arrays.asList("plugin2_F", "plugin1_F"))) {
 206                 throw new Exception("plugins not called in right order. " + order);
 207             }
 208         }
 209 
 210         {
 211             order.clear();
 212             String[] userOptions = {"--plugin1_C:LAST", "--plugin2_C:FIRST"};
 213             String moduleName = "order3";
 214             helper.generateDefaultJModule(moduleName, "composite2");
 215             Result res = helper.generateDefaultImage(userOptions, moduleName);
 216             res.assertSuccess();
 217             if (!order.equals(Arrays.asList("plugin2_C", "plugin1_C"))) {
 218                 throw new Exception("plugins not called in right order. " + order);
 219             }
 220         }
 221     }
 222 
 223     private void test2(List<String> order) throws Exception {
 224         check(createConfig("plugin1_F:0/false", "plugin1_T:0/false", "plugin1_S:0/false",
 225                 "plugin1_C:0/false", "plugin1_A:900000/true"),
 226                 Arrays.asList("plugin1_F", "plugin1_T", "plugin1_S", "plugin1_C", "plugin1_A"), order);
 227     }
 228 
 229     private void test3(List<String> order) throws Exception {
 230         check(createConfig("plugin1_F:250/false", "plugin1_T:100/false", "plugin1_S:50/false",
 231                 "plugin1_C:10/false", "plugin1_A:0/true"),
 232                 Arrays.asList("plugin1_A", "plugin1_F", "plugin1_T", "plugin1_S", "plugin1_C"), order);
 233     }
 234 
 235     private void test4(List<String> order) throws Exception {
 236         check(createConfig("plugin2_F:0/false", "plugin3_F:1/false", "plugin4_F:2/false",
 237                 "plugin1_F:3/false"),
 238                 Arrays.asList("plugin2_F", "plugin3_F", "plugin4_F", "plugin1_F"), order);
 239     }
 240 
 241     private void test5(List<String> order) throws Exception {
 242         check(createConfig("plugin2_T:0/false", "plugin3_T:1/false", "plugin4_T:2/false",
 243                 "plugin1_T:3/false"),
 244                 Arrays.asList("plugin2_T", "plugin3_T", "plugin4_T", "plugin1_T"), order);
 245     }
 246 
 247     private void test6(List<String> order) throws Exception {
 248         check(createConfig("plugin2_S:0/false", "plugin3_S:1/false", "plugin4_S:2/false",
 249                 "plugin1_S:3/false"),
 250                 Arrays.asList("plugin2_S", "plugin3_S", "plugin4_S", "plugin1_S"), order);
 251     }
 252 
 253     private void test7(List<String> order) throws Exception {
 254         check(createConfig("plugin2_C:0/false", "plugin3_C:1/false", "plugin4_C:2/false",
 255                 "plugin1_C:3/false"),
 256                 Arrays.asList("plugin2_C", "plugin3_C", "plugin4_C", "plugin1_C"), order);
 257     }
 258 
 259     private void testAbs(List<String> order) throws Exception {
 260         check(createConfig("plugin2_A:0/true", "plugin3_A:1/true", "plugin4_A:2/true",
 261                 "plugin1_A:3/true"),
 262                 Arrays.asList("plugin2_A", "plugin3_A", "plugin4_A", "plugin1_A"), order);
 263     }
 264 
 265     private void test8(List<String> order) throws Exception {
 266         check(createConfig("plugin1_F:" + ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.FILTER))[0] + "/true",
 267                 "plugin1_T:" + ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.TRANSFORMER))[0] + "/true",
 268                 "plugin1_S:" + ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.SORTER))[0] + "/true",
 269                 "plugin1_C:" + ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.COMPRESSOR))[0] + "/true"),
 270                 Arrays.asList("plugin1_F", "plugin1_T", "plugin1_S", "plugin1_C"), order);
 271     }
 272 
 273     private void test9(List<String> order) throws Exception {
 274         List<String> expected = new ArrayList<>();
 275         expected.add("plugin1_F");
 276         expected.add("plugin2_F");
 277         expected.add("plugin1_T");
 278         expected.add("plugin2_T");
 279         expected.add("plugin1_S");
 280         expected.add("plugin2_S");
 281         expected.add("plugin1_C");
 282         expected.add("plugin2_C");
 283 
 284         check(createConfig("plugin1_F:0/false", "plugin1_T:0/false", "plugin1_S:0/false",
 285                 "plugin1_C:0/false", "plugin2_F:" + (ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.FILTER))[0] + 1) + "/true",
 286                 "plugin2_T:" + (ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.TRANSFORMER))[0] + 1) + "/true",
 287                 "plugin2_S:" + (ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.SORTER))[0] + 1) + "/true",
 288                 "plugin2_C:" + (ImagePluginConfiguration.getRange(new CategoryProvider(PluginProvider.COMPRESSOR))[0] + 1) + "/true"), expected, order);
 289     }
 290 
 291     public static class PProvider extends CmdResourcePluginProvider {
 292 
 293         private final List<String> order;
 294         private final String category;
 295         private final String name;
 296         PProvider(String name, String category, List<String> order) {
 297             super(name, "");
 298             this.name = name;
 299             this.order = order;
 300             this.category = category;
 301         }
 302 
 303         @Override
 304         public ResourcePlugin[] newPlugins(String[] argument, Map<String, String> options) throws IOException {
 305             return new ResourcePlugin[]{new PluginTrap(getName(), order)
 306             };
 307         }
 308 
 309         @Override
 310         public String getCategory() {
 311             return category;
 312         }
 313 
 314         @Override
 315         public String getToolOption() {
 316             return name;
 317         }
 318 
 319         @Override
 320         public String getToolArgument() {
 321             return null;
 322         }
 323 
 324         @Override
 325         public Map<String, String> getAdditionalOptions() {
 326             return null;
 327         }
 328     }
 329 
 330     public static class PluginTrap implements ResourcePlugin {
 331 
 332         private final String name;
 333         private final List<String> order;
 334 
 335         private PluginTrap(String name, List<String> order) {
 336             this.name = name;
 337             this.order = order;
 338         }
 339 
 340         @Override
 341         public void visit(ResourcePool resources, ResourcePool output, StringTable strings)
 342                 throws Exception {
 343             order.add(name);
 344             resources.visit((resource, order, str) -> {
 345                 return resource;
 346             }, output, strings);
 347         }
 348 
 349         @Override
 350         public String getName() {
 351             return name;
 352         }
 353     }
 354 
 355     public static class CategoryProvider extends CmdResourcePluginProvider {
 356 
 357         private final String category;
 358 
 359         CategoryProvider(String category) {
 360             super("CategoryProvider", "");
 361             this.category = category;
 362         }
 363 
 364         @Override
 365         public ResourcePlugin[] newPlugins(String[] argument,
 366                 Map<String, String> options) throws IOException {
 367             throw new IOException("Shouldn't be called");
 368         }
 369 
 370         @Override
 371         public String getCategory() {
 372             return category;
 373         }
 374 
 375         @Override
 376         public String getToolArgument() {
 377             throw new UnsupportedOperationException("Shouldn't be called");
 378         }
 379 
 380         @Override
 381         public String getToolOption() {
 382             throw new UnsupportedOperationException("Shouldn't be called");
 383         }
 384 
 385         @Override
 386         public Map<String, String> getAdditionalOptions() {
 387             throw new UnsupportedOperationException("Shouldn't be called");
 388         }
 389     }
 390 }