8163116: jlink exclude VM plugin does not fully support cross platform image creation
authorsundar
Fri, 05 Aug 2016 09:42:05 +0530
changeset 40124 01f8745abd3c
parent 40123 673d89604418
child 40125 6a9dea571042
8163116: jlink exclude VM plugin does not fully support cross platform image creation Reviewed-by: redestad, alanb, mchung
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Fri Aug 05 09:42:05 2016 +0530
@@ -38,6 +38,7 @@
 import jdk.tools.jlink.plugin.Plugin;
 import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
 import jdk.tools.jlink.plugin.ResourcePoolEntry;
 import jdk.tools.jlink.plugin.PluginException;
 
@@ -98,9 +99,8 @@
      * e.g.: /java.base/native/amd64/server/libjvm.so
      * /java.base/native/server/libjvm.dylib
      */
-    private List<ResourcePoolEntry> getVMs(ResourcePool in) {
-        String jvmlib = jvmlib();
-        List<ResourcePoolEntry> ret = in.moduleView().findModule("java.base").get().entries().filter((t) -> {
+    private List<ResourcePoolEntry> getVMs(ResourcePoolModule javaBase, String jvmlib) {
+        List<ResourcePoolEntry> ret = javaBase.entries().filter((t) -> {
             return t.path().endsWith("/" + jvmlib);
         }).collect(Collectors.toList());
         return ret;
@@ -108,12 +108,13 @@
 
     @Override
     public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
-        String jvmlib = jvmlib();
+        ResourcePoolModule javaBase = in.moduleView().findModule("java.base").get();
+        String jvmlib = jvmlib(javaBase.descriptor().osName().get());
         TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
         TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
         if (!keepAll) {
             // First retrieve all available VM names and removed VM
-            List<ResourcePoolEntry> jvms = getVMs(in);
+            List<ResourcePoolEntry> jvms = getVMs(javaBase, jvmlib);
             for (Jvm jvm : Jvm.values()) {
                 for (ResourcePoolEntry md : jvms) {
                     if (md.path().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
@@ -247,21 +248,21 @@
         return orig.copyWithContent(content);
     }
 
-    private static String jvmlib() {
+    private static String jvmlib(String osName) {
         String lib = "libjvm.so";
-        if (isWindows()) {
+        if (isWindows(osName)) {
             lib = "jvm.dll";
-        } else if (isMac()) {
+        } else if (isMac(osName)) {
             lib = "libjvm.dylib";
         }
         return lib;
     }
 
-    private static boolean isWindows() {
-        return System.getProperty("os.name").startsWith("Windows");
+    private static boolean isWindows(String osName) {
+        return osName.startsWith("Windows");
     }
 
-    private static boolean isMac() {
-        return System.getProperty("os.name").startsWith("Mac OS");
+    private static boolean isMac(String osName) {
+        return osName.startsWith("Mac OS");
     }
 }
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Fri Aug 05 09:42:05 2016 +0530
@@ -30,6 +30,9 @@
  * @run main ExcludeVMPluginTest
  */
 import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
 import jdk.tools.jlink.internal.ResourcePoolManager;
@@ -167,6 +170,13 @@
         poolMgr.add(
             ResourcePoolEntry.create("/java.base/native/jvm.cfg",
                 ResourcePoolEntry.Type.NATIVE_LIB, jvmcfgContent));
+
+        // java.base/module-info.class is used by exclude vm plugin
+        // to get current osName(). We read it from jrt-fs and add a
+        // ResourcePoolEntry
+        poolMgr.add(
+            ResourcePoolEntry.create("/java.base/module-info.class",
+                ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
         for (String in : input) {
             poolMgr.add(ResourcePoolEntry.create(in,
                     ResourcePoolEntry.Type.NATIVE_LIB, new byte[0]));
@@ -187,15 +197,19 @@
             throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
         }
 
-        if (out.entryCount() != (expectedOutput.length + 1)) {
+        // Apart from native resources, we should find jvm.cfg and
+        // java.base/module-info.class. So, we add 2 here to the
+        // expected count!
+        if (out.entryCount() != (expectedOutput.length + 2)) {
             out.entries().forEach(m -> {
                 System.err.println(m.path());
             });
-            throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 1));
+            throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 2));
         }
 
         out.entries().forEach(md -> {
-            if (md.path().equals("/java.base/native/jvm.cfg")) {
+            if (md.path().equals("/java.base/native/jvm.cfg") ||
+                md.path().equals("/java.base/module-info.class")) {
                 return;
             }
             boolean contained = false;
@@ -209,7 +223,11 @@
                 throw new RuntimeException(md.path() + " not expected");
             }
         });
+    }
 
+    // read java.base/module-info.class from jrt-fs
+    private static Path getJavaBaseModuleInfo() {
+        return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
     }
 
     private static boolean isWindows() {
--- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java	Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java	Fri Aug 05 09:42:05 2016 +0530
@@ -32,8 +32,10 @@
  */
 
 import java.io.File;
+import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -87,6 +89,12 @@
         conf.put(FileCopierPlugin.NAME, builder.toString());
         plug.configure(conf);
         ResourcePoolManager poolMgr = new ResourcePoolManager();
+        // java.base/module-info.class is used to add "release" file
+        // We read it from jrt-fs and add a ResourcePoolEntry
+        poolMgr.add(
+            ResourcePoolEntry.create("/java.base/module-info.class",
+                ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
+        expected++;
         ResourcePool pool = plug.transform(
                 new ResourcePoolManager().resourcePool(),
                 poolMgr.resourcePoolBuilder());
@@ -94,7 +102,8 @@
             throw new AssertionError("Wrong number of added files");
         }
         pool.entries().forEach(f -> {
-            if (!f.type().equals(ResourcePoolEntry.Type.OTHER)) {
+            if (!f.type().equals(ResourcePoolEntry.Type.OTHER) &&
+                !f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
                 throw new AssertionError("Invalid type " + f.type()
                         + " for file " + f.path());
             }
@@ -104,18 +113,7 @@
         });
         Path root = new File(".").toPath();
         DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root);
-        try {
-            imgbuilder.storeFiles(pool);
-        } catch (PluginException e) {
-            // We didn't add any .class resource of the java.base module!
-            // This cannot happen in non-testing scenario as java.base module
-            // is minimum mandatory module in a .jimage. jlink depends on java.base
-            // to generate 'release' file. If the current exception came from that
-            // part of the code, then it is okay.
-            if (!e.getMessage().contains("No module-info for java.base module")) {
-                throw e;
-            }
-        }
+        imgbuilder.storeFiles(pool);
 
         if (lic.exists()) {
             File license = new File(root.toFile(), "LICENSE");
@@ -157,4 +155,9 @@
             throw new AssertionError("Invalid Content in src2 dir");
         }
     }
+
+    // read java.base/module-info.class from jrt-fs
+    private static Path getJavaBaseModuleInfo() {
+        return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
+    }
 }