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 exclude VM plugin
  27  * @author Jean-Francois Denise
  28  * @modules jdk.jlink/jdk.tools.jlink.internal
  29  *          jdk.jlink/jdk.tools.jlink.internal.plugins
  30  *          jdk.jlink/jdk.tools.jlink.plugin
  31  * @run main ExcludeVMPluginTest
  32  */
  33 import java.io.ByteArrayInputStream;
  34 import java.net.URI;
  35 import java.nio.file.Path;
  36 import java.nio.file.Paths;
  37 import java.util.HashMap;
  38 import java.util.Map;
  39 import jdk.tools.jlink.internal.ResourcePoolManager;
  40 
  41 import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
  42 import jdk.tools.jlink.plugin.Plugin;
  43 import jdk.tools.jlink.plugin.ResourcePool;
  44 import jdk.tools.jlink.plugin.ResourcePoolEntry;
  45 
  46 public class ExcludeVMPluginTest {
  47 
  48     private static final String TAG = "# orig in test\n";
  49 
  50     private static final String[] ARCHITECTURES = {"/", "/amd64/", "/i386/", "/arm/",
  51         "/aarch64/", "/toto/"};
  52 
  53     private static final String[] CLIENT = {"client/" + jvmlib(),};
  54     private static final String[] SERVER = {"server/" + jvmlib()};
  55     private static final String[] MINIMAL = {"minimal/" + jvmlib()};
  56     private static final String[] ALL = {CLIENT[0], SERVER[0], MINIMAL[0]};
  57     private static final String JVM_CFG_ALL = TAG + "-server KNOWN\n-client KNOWN\n-minimal KNOWN\n";
  58     private static final String JVM_CFG_CLIENT = TAG + "-client KNOWN\n";
  59     private static final String JVM_CFG_SERVER = TAG + "-server KNOWN\n";
  60     private static final String JVM_CFG_SERVER_ALIAS_OTHERS = TAG + "-server KNOWN\n-client ALIASED_TO -server\n-minimal ALIASED_TO -server\n";
  61     private static final String JVM_CFG_CLIENT_ALIAS_OTHERS = TAG + "-client KNOWN\n-server ALIASED_TO -client\n-minimal ALIASED_TO -client\n";
  62     private static final String JVM_CFG_MINIMAL_ALIAS_OTHERS = TAG + "-minimal KNOWN\n-server ALIASED_TO -minimal\n-client ALIASED_TO -minimal\n";
  63     private static final String JVM_CFG_MINIMAL = TAG + "-minimal KNOWN\n";
  64 
  65     public static void main(String[] args) throws Exception {
  66         new ExcludeVMPluginTest().test();
  67     }
  68 
  69     public void test() throws Exception {
  70         boolean failed = false;
  71 
  72         try {
  73             checkVM("toto", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
  74             failed = true;
  75             throw new Exception("Should have failed");
  76         } catch (Exception ex) {
  77             if (failed) {
  78                 throw ex;
  79             }
  80         }
  81 
  82         checkVM("all", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
  83         checkVM("all", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
  84         checkVM("all", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
  85         checkVM("all", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
  86 
  87         checkVM("server", ALL, JVM_CFG_ALL, SERVER, JVM_CFG_SERVER_ALIAS_OTHERS);
  88         checkVM("server", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
  89         try {
  90             checkVM("server", CLIENT, JVM_CFG_CLIENT, SERVER, JVM_CFG_SERVER);
  91             failed = true;
  92             throw new Exception("Should have failed");
  93         } catch (Exception ex) {
  94             if (failed) {
  95                 throw ex;
  96             }
  97         }
  98         try {
  99             checkVM("server", MINIMAL, JVM_CFG_MINIMAL, SERVER, JVM_CFG_SERVER);
 100             failed = true;
 101             throw new Exception("Should have failed");
 102         } catch (Exception ex) {
 103             if (failed) {
 104                 throw ex;
 105             }
 106         }
 107 
 108         checkVM("client", ALL, JVM_CFG_ALL, CLIENT, JVM_CFG_CLIENT_ALIAS_OTHERS);
 109         checkVM("client", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
 110         try {
 111             checkVM("client", SERVER, JVM_CFG_SERVER, CLIENT, JVM_CFG_CLIENT);
 112             failed = true;
 113             throw new Exception("Should have failed");
 114         } catch (Exception ex) {
 115             if (failed) {
 116                 throw ex;
 117             }
 118         }
 119         try {
 120             checkVM("client", MINIMAL, JVM_CFG_MINIMAL, CLIENT, JVM_CFG_CLIENT);
 121             failed = true;
 122             throw new Exception("Should have failed");
 123         } catch (Exception ex) {
 124             if (failed) {
 125                 throw ex;
 126             }
 127         }
 128 
 129         checkVM("minimal", ALL, JVM_CFG_ALL, MINIMAL, JVM_CFG_MINIMAL_ALIAS_OTHERS);
 130         checkVM("minimal", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
 131         try {
 132             checkVM("minimal", SERVER, JVM_CFG_SERVER, MINIMAL, JVM_CFG_MINIMAL);
 133             failed = true;
 134             throw new Exception("Should have failed");
 135         } catch (Exception ex) {
 136             if (failed) {
 137                 throw ex;
 138             }
 139         }
 140         try {
 141             checkVM("minimal", CLIENT, JVM_CFG_CLIENT, MINIMAL, JVM_CFG_MINIMAL);
 142             failed = true;
 143             throw new Exception("Should have failed");
 144         } catch (Exception ex) {
 145             if (failed) {
 146                 throw ex;
 147             }
 148         }
 149 
 150     }
 151 
 152     public void checkVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
 153 
 154         for (String arch : ARCHITECTURES) {
 155             String[] winput = new String[input.length];
 156             String[] woutput = new String[expectedOutput.length];
 157             for (int i = 0; i < input.length; i++) {
 158                 winput[i] = "/java.base/native" + arch + input[i];
 159             }
 160             for (int i = 0; i < expectedOutput.length; i++) {
 161                 woutput[i] = "/java.base/native" + arch + expectedOutput[i];
 162             }
 163             doCheckVM(vm, winput, jvmcfg, woutput, expectdJvmCfg);
 164         }
 165     }
 166 
 167     private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
 168         // Create a pool with jvm.cfg and the input paths.
 169         byte[] jvmcfgContent = jvmcfg.getBytes();
 170         ResourcePoolManager poolMgr = new ResourcePoolManager();
 171         poolMgr.add(
 172             ResourcePoolEntry.create("/java.base/native/jvm.cfg",
 173                 ResourcePoolEntry.Type.NATIVE_LIB, jvmcfgContent));
 174 
 175         // java.base/module-info.class is used by exclude vm plugin
 176         // to get current osName(). We read it from jrt-fs and add a
 177         // ResourcePoolEntry
 178         poolMgr.add(
 179             ResourcePoolEntry.create("/java.base/module-info.class",
 180                 ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
 181         for (String in : input) {
 182             poolMgr.add(ResourcePoolEntry.create(in,
 183                     ResourcePoolEntry.Type.NATIVE_LIB, new byte[0]));
 184         }
 185         ResourcePoolManager outMgr = new ResourcePoolManager();
 186 
 187         Plugin p = new ExcludeVMPlugin();
 188         Map<String, String> config = new HashMap<>();
 189         if (vm != null) {
 190             config.put(ExcludeVMPlugin.NAME, vm);
 191         }
 192         p.configure(config);
 193         ResourcePool out = p.transform(poolMgr.resourcePool(), outMgr.resourcePoolBuilder());
 194 
 195         String newContent = new String(out.findEntry("/java.base/native/jvm.cfg").get().contentBytes());
 196 
 197         if (!expectdJvmCfg.equals(newContent)) {
 198             throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
 199         }
 200 
 201         // Apart from native resources, we should find jvm.cfg and
 202         // java.base/module-info.class. So, we add 2 here to the
 203         // expected count!
 204         if (out.entryCount() != (expectedOutput.length + 2)) {
 205             out.entries().forEach(m -> {
 206                 System.err.println(m.path());
 207             });
 208             throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 2));
 209         }
 210 
 211         out.entries().forEach(md -> {
 212             if (md.path().equals("/java.base/native/jvm.cfg") ||
 213                 md.path().equals("/java.base/module-info.class")) {
 214                 return;
 215             }
 216             boolean contained = false;
 217             for (String o : expectedOutput) {
 218                 if (md.path().equals(o)) {
 219                     contained = true;
 220                     break;
 221                 }
 222             }
 223             if (!contained) {
 224                 throw new RuntimeException(md.path() + " not expected");
 225             }
 226         });
 227     }
 228 
 229     // read java.base/module-info.class from jrt-fs
 230     private static Path getJavaBaseModuleInfo() {
 231         return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
 232     }
 233 
 234     private static boolean isWindows() {
 235         return System.getProperty("os.name").startsWith("Windows");
 236     }
 237 
 238     private static boolean isMac() {
 239         return System.getProperty("os.name").startsWith("Mac OS");
 240     }
 241 
 242     private static String jvmlib() {
 243         String lib = "libjvm.so";
 244         if (isWindows()) {
 245             lib = "jvm.dll";
 246         } else if (isMac()) {
 247             lib = "libjvm.dylib";
 248         }
 249         return lib;
 250     }
 251 }