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