changeset 10172:b548989d62ca jdk-9+148

8160464: Application.getHostServices throws ClassNotFoundException Reviewed-by: kcr
author ckyang
date Fri, 02 Dec 2016 09:13:19 -0800
parents ea3b5eecfcb8
children b99680ef4c6d a64f5403de11
files apps/toys/Hello/src/main/java/hello/HelloHostServices.java modules/javafx.graphics/src/main/java/com/sun/javafx/application/HostServicesDelegate.java tests/system/src/test/java/test/com/sun/javafx/application/HostServicesTest.java
diffstat 3 files changed, 348 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/toys/Hello/src/main/java/hello/HelloHostServices.java	Fri Dec 02 09:13:19 2016 -0800
@@ -0,0 +1,108 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package hello;
+
+import javafx.application.Application;
+import javafx.application.HostServices;
+import javafx.geometry.Insets;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.stage.Stage;
+
+public class HelloHostServices extends Application {
+
+    @Override
+    public void start(Stage stage) {
+        final HostServices hs = getHostServices();
+        final Label codeBaseText = new Label();
+        final Label documentBaseText = new Label();
+        final Label webContextText = new Label();
+        final Label showDocumentText = new Label();
+
+        stage.setTitle("Hello HostServices");
+
+        String userDir = System.getProperty("user.dir");
+        userDir = userDir.replace("\\", "/");
+        System.err.println("userDir = " + userDir);
+        if (!userDir.startsWith("/")) {
+            userDir = "/" + userDir;
+        }
+        String testDocBase = "file:" + userDir + "/";
+        System.err.println("testDocBase = " + testDocBase);
+        System.err.println("DocumentBase = " + hs.getDocumentBase());
+        System.err.println("testDocBase.equals(hs.getDocumentBase()) = "
+                + testDocBase.equals(hs.getDocumentBase()));
+
+        Button getCodeBaseBtn = new Button("Get CodeBase");
+        getCodeBaseBtn.setOnAction(event -> codeBaseText.setText(
+                hs.getCodeBase().isEmpty() ? "EMPTY" : hs.getCodeBase()));
+
+        documentBaseText.setPrefWidth(400);
+        Button getDocumentBaseBtn = new Button("Get DocumentBase");
+        getDocumentBaseBtn.setOnAction(event -> documentBaseText.setText(hs.getDocumentBase()));
+
+        // getWebContext() in HostServices has been deprecated and marked for removal
+        Button getWebContextBtn = new Button("Get WebContext");
+        getWebContextBtn.setOnAction(event -> webContextText.setText(
+                (hs.getWebContext() != null) ? hs.getWebContext().toString() : "NULL"));
+
+        Button showDocmentBtn = new Button("Show Document");
+        showDocmentBtn.setOnAction(event
+                -> showDocument(hs, showDocumentText, "http://www.oracle.com/java/"));
+
+        VBox textBox = new VBox(15);
+        textBox.setFillWidth(false);
+        textBox.getChildren().addAll(codeBaseText, documentBaseText, webContextText, showDocumentText);
+
+        VBox buttonBox = new VBox(5);
+        buttonBox.getChildren().addAll(
+                getCodeBaseBtn,
+                getDocumentBaseBtn,
+                getWebContextBtn,
+                showDocmentBtn);
+
+        HBox root = new HBox(7);
+        root.setPadding(new Insets(11, 12, 12, 11));
+        root.getChildren().addAll(buttonBox, textBox);
+        stage.setScene(new Scene(root, 600, 150));
+        stage.show();
+    }
+
+    private void showDocument(HostServices hs, Label showDocumentText, String urlStr) {
+        showDocumentText.setText(urlStr + " will be shown in the browser.");
+        hs.showDocument(urlStr);
+    }
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+        Application.launch(args);
+    }
+}
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/application/HostServicesDelegate.java	Thu Dec 01 15:51:16 2016 -0800
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/application/HostServicesDelegate.java	Fri Dec 02 09:13:19 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -25,8 +25,9 @@
 
 package com.sun.javafx.application;
 
-import java.lang.reflect.InvocationTargetException;
+import java.io.File;
 import java.lang.reflect.Method;
+import java.net.URI;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
@@ -55,7 +56,6 @@
                                 getInstanceMeth = factoryClass.getMethod(
                                         "getInstance", Application.class);
                             } catch (Exception ex) {
-                                ex.printStackTrace();
                                 return null;
                             }
                         }
@@ -67,7 +67,10 @@
             System.err.println(pae.getException().toString());
             return null;
         }
-
+        if (instance == null) {
+            // in this case we are in standalone mode
+            instance = StandaloneHostService.getInstance(app);
+        }
         return instance;
     }
 
@@ -81,4 +84,119 @@
     public abstract void showDocument(String uri);
 
     public abstract JSObject getWebContext();
+
+    // StandaloneHostService implementation
+    private static class StandaloneHostService extends HostServicesDelegate {
+
+        private static HostServicesDelegate instance = null;
+
+        private Class appClass = null;
+
+        public static HostServicesDelegate getInstance(Application app) {
+            synchronized (StandaloneHostService.class) {
+                if (instance == null) {
+                    instance = new StandaloneHostService(app);
+                }
+                return instance;
+            }
+        }
+
+        private StandaloneHostService(Application app) {
+             appClass = app.getClass();
+        }
+
+        @Override
+        public String getCodeBase() {
+            // If the application was launched in standalone mode, this method
+            // returns the directory containing the application jar file.
+            // If the application is not packaged in a jar file, this method
+            // returns the empty string.
+            String theClassFile = appClass.getName();
+            int idx = theClassFile.lastIndexOf(".");
+            if (idx >= 0) {
+                // Strip off package name prefix in class name if exists
+                // getResoruce will automatically add in package name during
+                // lookup; see Class.getResource javadoc for more details
+                theClassFile = theClassFile.substring(idx + 1);
+            }
+            theClassFile = theClassFile + ".class";
+
+            String classUrlString = appClass.getResource(theClassFile).toString();
+            if (!classUrlString.startsWith("jar:file:") ||
+                    classUrlString.indexOf("!") == -1) {
+                return "";
+            }
+            // Strip out the "jar:" and everything after and including the "!"
+            String urlString = classUrlString.substring(4,
+                    classUrlString.lastIndexOf("!"));
+            File jarFile = null;
+            try {
+                jarFile = new File(new URI(urlString).getPath());
+            } catch (Exception e) {
+                // should not happen
+            }
+            if (jarFile != null) {
+                String codebase = jarFile.getParent();
+                if (codebase != null) {
+                    return toURIString(codebase);
+                }
+            }
+
+            return "";
+        }
+
+        private String toURIString(String filePath) {
+            try {
+                return new File(filePath).toURI().toString();
+            } catch (Exception e) {
+                // should not happen
+                // dump stack for debug purpose
+                e.printStackTrace();
+            }
+            return "";
+        }
+
+        @Override public String getDocumentBase() {
+            // If the application was launched in standalone mode,
+            // this method returns the URI of the current directory.
+            return toURIString(System.getProperty("user.dir"));
+        }
+
+        static final String[] browsers = {"google-chrome", "firefox", "opera",
+            "konqueror", "mozilla"};
+
+        @Override
+        public void showDocument(final String uri) {
+            String osName = System.getProperty("os.name");
+            try {
+                if (osName.startsWith("Mac OS")) {
+                    Class.forName("com.apple.eio.FileManager").getDeclaredMethod(
+                            "openURL", new Class[]{String.class}).invoke(null,
+                            new Object[]{uri});
+                } else if (osName.startsWith("Windows")) {
+                    Runtime.getRuntime().exec(
+                            "rundll32 url.dll,FileProtocolHandler " + uri);
+                } else { //assume Unix or Linux
+                    String browser = null;
+                    for (String b : browsers) {
+                        if (browser == null && Runtime.getRuntime().exec(
+                                new String[]{"which", b}).getInputStream().read() != -1) {
+                            Runtime.getRuntime().exec(new String[]{browser = b, uri});
+                        }
+                    }
+                    if (browser == null) {
+                        throw new Exception("No web browser found");
+                    }
+                }
+            } catch (Exception e) {
+                // should not happen
+                // dump stack for debug purpose
+                e.printStackTrace();
+            }
+        }
+
+        @Override public JSObject getWebContext() {
+            return null;
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/test/com/sun/javafx/application/HostServicesTest.java	Fri Dec 02 09:13:19 2016 -0800
@@ -0,0 +1,118 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package test.com.sun.javafx.application;
+
+import com.sun.javafx.PlatformUtil;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javafx.application.Application;
+import javafx.application.HostServices;
+import javafx.application.Platform;
+import javafx.stage.Stage;
+import junit.framework.AssertionFailedError;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static test.util.Util.TIMEOUT;
+
+/**
+ * Unit tests for Platform runLater.
+ */
+public class HostServicesTest {
+
+    // Used to launch the application before running any test
+    private static final CountDownLatch launchLatch = new CountDownLatch(1);
+
+    // Singleton Application instance
+    private static MyApp myApp;
+
+    // Application class. An instance is created and initialized before running
+    // the first test, and it lives through the execution of all tests.
+    public static class MyApp extends Application {
+
+        @Override
+        public void start(Stage primaryStage) throws Exception {
+            HostServicesTest.myApp = this;
+            Platform.setImplicitExit(false);
+            launchLatch.countDown();
+        }
+    }
+
+    @BeforeClass
+    public static void setupOnce() {
+        // Start the Application
+        new Thread(() -> Application.launch(MyApp.class, (String[]) null)).start();
+
+        try {
+            if (!launchLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
+                throw new AssertionFailedError("Timeout waiting for Application to launch");
+            }
+        } catch (InterruptedException ex) {
+            AssertionFailedError err = new AssertionFailedError("Unexpected exception");
+            err.initCause(ex);
+            throw err;
+        }
+    }
+
+    @AfterClass
+    public static void teardownOnce() {
+        Platform.exit();
+    }
+
+    @Test
+    public void testCodeBase() {
+        final HostServices hs = myApp.getHostServices();
+        assertNotNull(hs);
+        String cbStr = hs.getCodeBase();
+        assertNotNull(cbStr);
+        assertTrue(cbStr.isEmpty());
+    }
+
+    @Test
+    public void testDocumentBase() {
+        final HostServices hs = myApp.getHostServices();
+        assertNotNull(hs);
+        String dbStr = hs.getDocumentBase();
+        assertNotNull(dbStr);
+        String userDir = System.getProperty("user.dir");
+        userDir = userDir.replace("\\", "/");
+        System.err.println("userDir = " + userDir);
+        if (!userDir.startsWith("/")) {
+            userDir = "/" + userDir;
+        }
+        String testDocBase = "file:" + userDir + "/";
+        assertTrue(dbStr.equals(testDocBase));
+    }
+
+    @Test
+    public void testWebContext() {
+        final HostServices hs = myApp.getHostServices();
+        assertNotNull(hs);
+        assertNull(hs.getWebContext());
+    }
+}