8156121: "Fail forward" fails for GTK3 if no GTK2 available
authorssadetsky
Tue, 07 Jun 2016 11:40:28 +0300
changeset 39033 d61135c3795c
parent 39032 0df349c99122
child 39034 f2abf228ebe5
8156121: "Fail forward" fails for GTK3 if no GTK2 available Reviewed-by: prr
jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c
jdk/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c	Tue Jun 07 11:29:42 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c	Tue Jun 07 11:40:28 2016 +0300
@@ -43,7 +43,7 @@
     gboolean (*check)(const char* lib_name, gboolean load);
 } GtkLib;
 
-static GtkLib libs[] = {
+static GtkLib gtk_libs[] = {
     {
         GTK_2,
         JNI_LIB_NAME("gtk-x11-2.0"),
@@ -57,26 +57,42 @@
         VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
         &gtk3_load,
         &gtk3_check
-    },
-    {
-        0,
-        NULL,
-        NULL,
-        NULL,
-        NULL
     }
 };
 
+static GtkLib** get_libs_order(GtkVersion version) {
+    static GtkLib** load_order;
+    static int n_libs = 0;
+    if (!n_libs) {
+        n_libs = sizeof(gtk_libs) / sizeof(GtkLib);
+        load_order = calloc(n_libs + 1, sizeof(GtkLib *));
+    }
+    int i, first = 0;
+    for (i = 0; i < n_libs; i++) {
+        load_order[i] = &gtk_libs[i];
+        if (load_order[i]->version == version) {
+            first = i;
+        }
+    }
+    if (first) {
+        for (i = first; i > 0; i--) {
+            load_order[i] = load_order[i - 1];
+        }
+        load_order[0] = &gtk_libs[first];
+    }
+    return load_order;
+}
+
 static GtkLib* get_loaded() {
-    GtkLib* lib = libs;
-    while(!gtk && lib->version) {
+    GtkLib** libs = get_libs_order(GTK_ANY);
+    while(!gtk && *libs) {
+        GtkLib* lib = *libs++;
         if (lib->check(lib->vname, /* load = */FALSE)) {
             return lib;
         }
         if (lib->check(lib->name, /* load = */FALSE)) {
             return lib;
         }
-        lib++;
     }
     return NULL;
 }
@@ -85,23 +101,18 @@
     if (gtk == NULL) {
         GtkLib* lib = get_loaded();
         if (lib) {
-            if (version != GTK_ANY && lib->version != version) {
-                if (verbose) {
-                    fprintf(stderr, "WARNING: Cannot load GTK%d library: \
-                         GTK%d has already been loaded\n", version, lib->version);
-                }
-                return FALSE;
-            }
             if (verbose) {
-                fprintf(stderr, "Looking for GTK%d library...\n", version);
+                fprintf(stderr, "Looking for GTK%d library...\n",
+                                                                 lib->version);
             }
             gtk = lib->load(env, lib->vname);
             if (!gtk) {
                 gtk = lib->load(env, lib->name);
             }
         } else {
-            lib = libs;
-            while (!gtk && lib->version) {
+            GtkLib** libs = get_libs_order(version);
+            while (!gtk && *libs) {
+                lib = *libs++;
                 if (version == GTK_ANY || lib->version == version) {
                     if (verbose) {
                         fprintf(stderr, "Looking for GTK%d library...\n",
@@ -115,9 +126,7 @@
                         fprintf(stderr, "Not found.\n");
                     }
                 }
-                lib++;
             }
-            lib--;
         }
         if (verbose) {
             if (gtk) {
@@ -131,23 +140,21 @@
 }
 
 static gboolean check_version(GtkVersion version) {
-    GtkLib* lib = libs;
-    while (lib->version) {
-        if (version == GTK_ANY || lib->version == version) {
-            if (lib->check(lib->vname, /* load = */TRUE)) {
-                return TRUE;
-            }
-            if (lib->check(lib->name, /* load = */TRUE)) {
-                return TRUE;
-            }
+    GtkLib** libs = get_libs_order(version);
+    while (*libs) {
+        GtkLib* lib = *libs++;
+        if (lib->check(lib->vname, /* load = */TRUE)) {
+            return TRUE;
         }
-        lib++;
+        if (lib->check(lib->name, /* load = */TRUE)) {
+            return TRUE;
+        }
     }
     return FALSE;
 }
 
 gboolean gtk_check_version(GtkVersion version) {
-    if (gtk) {
+    if (gtk || get_loaded()) {
         return TRUE;
     }
     return check_version(version);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java	Tue Jun 07 11:40:28 2016 +0300
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8156121
+ * @summary "Fail forward" fails for GTK3 if no GTK2 available
+ * @modules java.desktop/sun.awt
+ * @requires (os.family == "linux")
+ * @run main GtkVersionTest
+ */
+
+import sun.awt.UNIXToolkit;
+
+import java.awt.*;
+import java.io.*;
+
+public class GtkVersionTest {
+    public static class LoadGtk {
+        public static void main(String[] args) {
+            ((UNIXToolkit)Toolkit.getDefaultToolkit()).loadGTK();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        test(null, "2");
+        test("2", "2");
+        test("2.2", "2");
+        test("3", "3");
+    }
+
+    private static void test(String version, String expect) throws Exception {
+        System.out.println( "Test " +
+                (version == null ? "no" : " GTK" + version) + " preference.");
+        Process p = Runtime.getRuntime().exec(System.getProperty("java.home") +
+                "/bin/java " +
+                (version == null ? "" : "-Djdk.gtk.version=" + version) +
+                " -Djdk.gtk.verbose=true " +
+                "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED " +
+                "-cp " + System.getProperty("java.class.path", ".") +
+                " GtkVersionTest$LoadGtk");
+        p.waitFor();
+
+        try (BufferedReader br = new BufferedReader(
+                new InputStreamReader(p.getErrorStream()))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                System.out.println(line);
+                if (line.contains("Looking for GTK" + expect + " library")) {
+                    return;
+                } else if (line.contains("Looking for GTK")) {
+                    break;
+                }
+            }
+            throw new RuntimeException("Wrong GTK library version: \n" + line);
+        }
+    }
+
+}