/* * Based on Steven Spencer's Java Tip in JavaWorld: * http://www.javaworld.com/javaworld/javatips/jw-javatip66.html */ package net.sourceforge.ganttproject.util; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; /** * <p> * A simple, static class to display an URL in the system browser. * </p> * <p> * Under Windows, this will bring up the default browser, usually either * Netscape or Microsoft IE. The default browser is determined by the OS. This * has been tested under: Windows 95/98/NT/2000. * </p> * <p> * Under MacOS, this will bring up the default browser. The default browser is * determined by the OS. This has been tested under: n/a * </p> * <p> * Under (K)Ubuntu, Debian and other *nix platforms, try sensible-browser. It * checks $BROWSER and the variable is not available <a * href="http://wiki.debian.org/DebianAlternatives">Debian Alternatives</a>. If * that fails, fallback on the '<em>other platforms</em>' methods. This has been * tested under: Kubuntu 11.10 * </p> * <p> * In other platforms, a range of known browsers is invoked. * </p> * <p> * Examples: * <ul> * <li>BrowserControl.displayURL("http://www.javaworld.com")</li> * <li>BrowserControl.displayURL("file://c:\\docs\\index.html")</li> * <li>BrowserContorl.displayURL("file:///user/joe/index.html")</li> * </p> * <p> * Note - you must include the url type -- either "http://" or "file://". * </p> */ public class BrowserControl { private static boolean displayUrlWithDesktopApi(String url) { if (!java.awt.Desktop.isDesktopSupported()) { return false; } java.awt.Desktop desktop = java.awt.Desktop.getDesktop(); if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) { return false; } try { desktop.browse(new URI(url)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } return true; } private static boolean displayUrlWithJnlpApi(String url) { // Opening a browser, even when running sandbox-restricted // in JavaWebStart. try { Class<?> serManClass = Class.forName("javax.jnlp.ServiceManager"); Class<?> basSerClass = Class.forName("javax.jnlp.BasicService"); Class<?>[] stringParam = { String.class }; Class<?>[] urlParam = { URL.class }; Object basicService = serManClass.getMethod("lookup", stringParam).invoke(serManClass, new Object[] { "javax.jnlp.BasicService" }); basSerClass.getMethod("showDocument", urlParam).invoke(basicService, new Object[] { new URL(url) }); return true; } catch (Exception e) { return false; // Not running in JavaWebStart or service is not supported. // We continue with the methods below ... } } /** * Display an URL in the system browser. If you want to display a file, you * must include the absolute path name. * * @param url * the document's url (the url must start with either "http://" or * "file://"). * @return true when the method succeeded in displaying the URL in the system * browser */ public static boolean displayURL(String url) { if (displayUrlWithDesktopApi(url)) { return true; } if (displayUrlWithJnlpApi(url)) { return true; } Platforms platform = getPlatform(); switch (platform) { case WINDOWS: return runCmdLine(replaceToken(WIN_CMDLINE, URLTOKEN, url)); case MAC: return runCmdLine(replaceToken(MAC_CMDLINE, URLTOKEN, url)); case LINUX: if (runCmdLine(replaceToken(LINUX_CMDLINE, URLTOKEN, url))) { // Succeeded return true; } // Fallback on 'brute-force' method } // Try out a series of commands and hope one is recognized... assert OTHER_CMDLINES.length == OTHER_FALLBACKS.length; for (int i = 0; i < OTHER_CMDLINES.length; i++) { if (runCmdLine(replaceToken(OTHER_CMDLINES[i], URLTOKEN, url), replaceToken(OTHER_FALLBACKS[i], URLTOKEN, url))) { return true; } } return false; } /** * Try to determine whether this application is running under Windows or some * other platform by examining the "os.name" property. * * @return the ID of the platform */ private static Platforms getPlatform() { String os = System.getProperty("os.name"); if (os != null && os.startsWith(WIN_PREFIX)) { return Platforms.WINDOWS; } if (os != null && os.startsWith(MAC_PREFIX)) { return Platforms.MAC; } if (os != null && os.startsWith(LINUX_PREFIX)) { return Platforms.LINUX; } return Platforms.OTHER; } private static String connectStringArray(String[] a) { if (a == null) return null; String s = ""; for (int i = 0; i < a.length; i++) { if (i > 0) s += " "; s += a[i]; } return s; } private static String[] replaceToken(String[] target, String token, String replacement) { if (null == target) return null; String[] result = new String[target.length]; for (int i = 0; i < target.length; i++) result[i] = target[i].replaceAll(token, replacement); return result; } private static boolean runCmdLine(String[] cmdLine) { return runCmdLine(cmdLine, null); } // TODO Maybe make method a little less chatty... private static boolean runCmdLine(String[] cmdLine, String[] fallBackCmdLine) { try { System.err.println("Trying to invoke browser, cmd='" + connectStringArray(cmdLine) + "' ... "); Process p = Runtime.getRuntime().exec(cmdLine); int exitCode = p.waitFor(); if (exitCode == 0) { // Succeeded! System.err.println(); return true; } System.err.println(exitCode); System.err.println(); } catch (InterruptedException e) { System.err.println("Caught: " + e); } catch (IOException e) { System.err.println("Caught: " + e); } // Failed, caught exception or exitCode indicated an error if (null != fallBackCmdLine) { // Start fallBackCmdLine try { System.err.println("Trying to invoke browser, cmd='" + connectStringArray(fallBackCmdLine) + "' ..."); Process p = Runtime.getRuntime().exec(fallBackCmdLine); int exitCode = p.waitFor(); if (exitCode == 0) { // Succeeded! System.err.println(); return true; } } catch (InterruptedException e) { System.err.println("Caught: " + e); } catch (IOException e) { System.err.println("Caught: " + e); } } System.err.println(); return false; } /** Available/Supported platforms for opening URLs in browsers */ private enum Platforms { /** Used to identify the Windows platform. */ WINDOWS, /** Used to identify the <ac platform. */ MAC, /** Used to identify the (generic) Linux platform. */ LINUX, /** Unable to identify the platform */ OTHER }; // This token is a place holder for the actual URL private static final String URLTOKEN = "%URLTOKEN%"; // Used to discover the windows platform. private static final String WIN_PREFIX = "Windows"; // The default system browser under windows. // Once upon a time: // for 'Windows 9' and 'Windows M': start // for 'Windows': cmd /c start private static final String[] WIN_CMDLINE = { "rundll32", "url.dll,FileProtocolHandler", URLTOKEN }; // Used to discover the mac platform. private static final String MAC_PREFIX = "Mac"; // The default system browser under mac. private static final String[] MAC_CMDLINE = { "open", URLTOKEN }; // Used to discover the Linux platform. private static final String LINUX_PREFIX = "Linux"; // The default definition for the preferred browser under Linux private static final String[] LINUX_CMDLINE = { "sensible-browser", URLTOKEN }; private static final String[][] OTHER_CMDLINES = { // Try to invoke the browser specified in the BROWSER environment // variable // Comment because this method, because it use a deprecated method // and cause exception // GetEnv.GetEnvironement(URLTOKEN), // The first guess for a browser under other systems (and unix): // Remote controlling mozilla // (http://www.mozilla.org/unix/remote.html) { "mozilla", "-remote", "openURL(" + URLTOKEN + ",new-window)" }, // Next guess for a browser under other systems (and unix): // The RedHat script htmlview { "htmlview", URLTOKEN }, // Next guess, try Opera (if a user installed it, it is probably // 'more-wanted' than the default browser) // See /usr/share/applications/opera-browser.desktop { "opera", "-remote", "openURL(" + URLTOKEN + ")" }, // Next guess for a browser under Gnome: try FireFox ( // See /usr/share/applications/firefox.desktop { "firefox", URLTOKEN }, // Next guess for a browser under KDE4: rekonq // See /usr/share/applications/kde4/rekonq.desktop { "rekonq", URLTOKEN }, // Next guess for a browser under other systems (and unix): // Remote controlling netscape // (http://wp.netscape.com/newsref/std/x-remote.html) { "netscape", "-remote", "openURL(" + URLTOKEN + ")" } }; private static final String[][] OTHER_FALLBACKS = { // Fallback for remote controlling mozilla: // Starting up a new mozilla { "mozilla", URLTOKEN }, // No fallback for htmlview null, // Fallback for Opera: Opera-Next (alpha/development version // of Opera, can be separately used next to Opera) // See /usr/share/applications/opera-next-browser.desktop { "opera-next", "-remote", "openURL(" + URLTOKEN + ")" }, // No fallback for FireFox null, // Fallback for rekonq: old KDE browser is konqueror { "konqueror", URLTOKEN }, // Fallback for remote controlling netscape: // Starting up a new netscape { "netscape", URLTOKEN } }; }