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 previsitor
  27  * @author Andrei Eremeev
  28  * @modules jdk.jlink/jdk.tools.jlink.internal
  29  *          jdk.jlink/jdk.tools.jlink
  30  * @run main/othervm PrevisitorTest
  31  */
  32 import java.nio.ByteOrder;
  33 import java.util.ArrayList;
  34 import java.util.Collection;
  35 import java.util.Collections;
  36 import java.util.HashMap;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Optional;
  40 import java.util.stream.Collectors;
  41 
  42 import jdk.tools.jlink.internal.ImagePluginConfiguration;
  43 import jdk.tools.jlink.internal.Jlink;
  44 import jdk.tools.jlink.internal.PluginRepository;
  45 import jdk.tools.jlink.internal.ImagePluginStack;
  46 import jdk.tools.jlink.internal.ResourcePoolManager;
  47 import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
  48 import jdk.tools.jlink.internal.ResourcePrevisitor;
  49 import jdk.tools.jlink.internal.StringTable;
  50 import jdk.tools.jlink.plugin.Plugin;
  51 import jdk.tools.jlink.plugin.ResourcePool;
  52 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
  53 import jdk.tools.jlink.plugin.ResourcePoolEntry;
  54 
  55 public class PrevisitorTest {
  56 
  57     public static void main(String[] args) throws Exception {
  58         new PrevisitorTest().test();
  59     }
  60 
  61     private static Plugin createPlugin(String name) {
  62         return Jlink.newPlugin(name, Collections.emptyMap(), null);
  63     }
  64 
  65     public void test() throws Exception {
  66         CustomPlugin plugin = new CustomPlugin();
  67         PluginRepository.registerPlugin(plugin);
  68         List<Plugin> plugins = new ArrayList<>();
  69         plugins.add(createPlugin(CustomPlugin.NAME));
  70         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new Jlink.PluginsConfiguration(plugins,
  71                 null, null));
  72         ResourcePoolManager inResources = new ResourcePoolManager(ByteOrder.nativeOrder(), new CustomStringTable());
  73         inResources.add(ResourcePoolEntry.create("/aaa/bbb/res1.class", new byte[90]));
  74         inResources.add(ResourcePoolEntry.create("/aaa/bbb/res2.class", new byte[90]));
  75         inResources.add(ResourcePoolEntry.create("/aaa/bbb/res3.class", new byte[90]));
  76         inResources.add(ResourcePoolEntry.create("/aaa/ddd/res1.class", new byte[90]));
  77         inResources.add(ResourcePoolEntry.create("/aaa/res1.class", new byte[90]));
  78         ResourcePool outResources = stack.visitResources(inResources);
  79         Collection<String> input = inResources.entries()
  80                 .map(Object::toString)
  81                 .collect(Collectors.toList());
  82         Collection<String> output = outResources.entries()
  83                 .map(Object::toString)
  84                 .collect(Collectors.toList());
  85         if (!input.equals(output)) {
  86             throw new AssertionError("Input and output resources differ: input: "
  87                     + input + ", output: " + output);
  88         }
  89     }
  90 
  91     private static class CustomStringTable implements StringTable {
  92 
  93         private final List<String> strings = new ArrayList<>();
  94 
  95         @Override
  96         public int addString(String str) {
  97             strings.add(str);
  98             return strings.size() - 1;
  99         }
 100 
 101         @Override
 102         public String getString(int id) {
 103             return strings.get(id);
 104         }
 105 
 106         public int size() {
 107             return strings.size();
 108         }
 109     }
 110 
 111     private static class CustomPlugin implements Plugin, ResourcePrevisitor {
 112 
 113         private static String NAME = "plugin";
 114 
 115         private boolean isPrevisitCalled = false;
 116 
 117         @Override
 118         public ResourcePool transform(ResourcePool inResources, ResourcePoolBuilder outResources) {
 119             if (!isPrevisitCalled) {
 120                 throw new AssertionError("Previsit was not called");
 121             }
 122             CustomStringTable table = (CustomStringTable)((ResourcePoolImpl)inResources).getStringTable();
 123             if (table.size() == 0) {
 124                 throw new AssertionError("Table is empty");
 125             }
 126             Map<String, Integer> count = new HashMap<>();
 127             for (int i = 0; i < table.size(); ++i) {
 128                 String s = table.getString(i);
 129                 Optional<ResourcePoolEntry> e = inResources.findEntry(s);
 130                 if (e.isPresent()) {
 131                     throw new AssertionError();
 132                 }
 133                 count.compute(s, (k, c) -> 1 + (c == null ? 0 : c));
 134             }
 135             count.forEach((k, v) -> {
 136                 if (v != 1) {
 137                     throw new AssertionError("Expected one entry in the table, got: " + v + " for " + k);
 138                 }
 139             });
 140             inResources.entries().forEach(r -> {
 141                 outResources.add(r);
 142             });
 143 
 144             return outResources.build();
 145         }
 146 
 147         @Override
 148         public String getName() {
 149             return NAME;
 150         }
 151 
 152         @Override
 153         public void previsit(ResourcePool resources, StringTable strings) {
 154             isPrevisitCalled = true;
 155             resources.entries().forEach(r -> {
 156                 String s = r.path();
 157                 int lastIndexOf = s.lastIndexOf('/');
 158                 if (lastIndexOf >= 0) {
 159                     strings.addString(s.substring(0, lastIndexOf));
 160                 }
 161             });
 162         }
 163     }
 164 }