001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.tools;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Desktop;
007import java.io.IOException;
008import java.net.URI;
009
010import org.openstreetmap.josm.Main;
011
012/**
013 * Helper to open platform web browser on different platforms
014 *
015 * This now delegates the real work to a platform specific class.
016 *
017 * @author Imi
018 */
019public final class OpenBrowser {
020
021    private OpenBrowser() {
022        // Hide default constructor for utils classes
023    }
024
025    private static void displayUrlFallback(URI uri) throws IOException {
026        if (Main.platform == null)
027            throw new IllegalStateException(tr("Failed to open URL. There is currently no platform set. Please set a platform first."));
028        Main.platform.openUrl(uri.toString());
029    }
030
031    /**
032     * Displays an external URI using platform associated software.
033     * A web resource will launch platform's browser, an audio file URI will launch audio player, etc.
034     * @param uri The URI to display
035     * @return <code>null</code> for success or a string in case of an error.
036     * @throws IllegalStateException if no platform is set to which opening the URL can be dispatched,
037     * {@link Main#platform}
038     */
039    public static String displayUrl(URI uri) {
040        CheckParameterUtil.ensureParameterNotNull(uri, "uri");
041
042        Main.info(tr("Opening URL: {0}", uri));
043
044        if (Desktop.isDesktopSupported()) {
045            try {
046                if (Main.isPlatformWindows()) {
047                    // Desktop API works fine under Windows, so we don't try any fallback in case of I/O exceptions because it's not API's fault
048                    Desktop.getDesktop().browse(uri);
049                } else if (Main.platform instanceof PlatformHookUnixoid) {
050                    // see #5629 #5108 #9568
051                    Main.platform.openUrl(uri.toString());
052                } else {
053                    // This is not the case with some Linux environments (see below),
054                    // and not sure about Mac OS X, so we need to handle API failure
055                    try {
056                        Desktop.getDesktop().browse(uri);
057                    } catch (IOException e) {
058                        // Workaround for KDE (Desktop API is severely flawed)
059                        // see https://bugs.openjdk.java.net/browse/JDK-6486393
060                        Main.warn("Desktop class failed. Platform dependent fall back for open url in browser.");
061                        displayUrlFallback(uri);
062                    }
063                }
064            } catch (Exception e) {
065                Main.warn(e);
066                return e.getMessage();
067            }
068        } else {
069            try {
070                Main.warn("Desktop class is not supported. Platform dependent fall back for open url in browser.");
071                displayUrlFallback(uri);
072            } catch (IOException e) {
073                return e.getMessage();
074            }
075        }
076        return null;
077    }
078
079    /**
080     * Displays an external URL using platform associated software.
081     * A web resource will launch platform's browser, an audio file URL will launch audio player, etc.
082     * @param url The URL to display
083     * @return <code>null</code> for success or a string in case of an error.
084     * @throws IllegalStateException if no platform is set to which opening the URL can be dispatched,
085     * {@link Main#platform}
086     */
087    public static String displayUrl(String url) {
088        try {
089            return displayUrl(new URI(url));
090        } catch (Exception e) {
091            return e.getMessage();
092        }
093    }
094}