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