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