All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dorkbox.util.Desktop Maven / Gradle / Ivy

/*
 * Copyright 2017 dorkbox, llc
 *
 * Copyright (C) 2016 Tres Finocchiaro, QZ Industries, LLC
 * Derivative code has been released as Apache 2.0, used with permission.
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dorkbox.util;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import dorkbox.executor.ShellExecutor;
import dorkbox.util.jna.linux.GnomeVFS;
import dorkbox.util.jna.linux.GtkCheck;
import dorkbox.util.jna.linux.GtkEventDispatch;

@SuppressWarnings({"WeakerAccess", "Convert2Lambda", "Duplicates"})
public
class Desktop {
    // used for any linux system that has it...
    private static final String GVFS = "/usr/bin/gvfs-open";
    private static final boolean GVFS_VALID = new File(GVFS).canExecute();

    /**
     * Launches the default browser to display the specified HTTP address.
     * 

* If the default browser is not able to handle the specified address, the application registered for handling * HTTP requests of the specified type is invoked. * * @param address the URL to browse/open */ public static void browseURL(String address) throws IOException { if (address == null || address.isEmpty()) { throw new IOException("Address must not be null or empty."); } URI uri; try { uri = new URI(address); browseURL(uri); } catch (URISyntaxException e) { throw new IOException("Invalid URI " + address); } } /** * Launches the default browser to display a {@code URI}. *

* If the default browser is not able to handle the specified {@code URI}, the application registered for handling * {@code URIs} of the specified type is invoked. The application is determined from the protocol and path of the {@code URI}, as * defined by the {@code URI} class. * * @param uri the URL to browse/open */ public static void browseURL(final URI uri) throws IOException { if (uri == null) { throw new IOException("URI must not be null."); } // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT) // Prefer JNA method over AWT, since there are fewer chances for JNA to fail (even though they call the same method) if ((OS.isUnix() || OS.isLinux()) && GtkCheck.isGtkLoaded) { launchNix(uri.toString()); } else if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop() .isSupported(java.awt.Desktop.Action.BROWSE)) { // make sure this doesn't block the current UI SwingUtil.invokeLater(new Runnable() { @Override public void run() { try { java.awt.Desktop.getDesktop() .browse(uri); } catch (IOException e) { e.printStackTrace(); } } }); } else { throw new IOException("Current OS and desktop configuration does not support browsing for a URL"); } } /** * Launches the mail composing window of the user default mail client for the specified address. * * @param address who the email goes to */ public static void launchEmail(String address) throws IOException { if (address == null || address.isEmpty()) { throw new IOException("Address must not be null or empty."); } URI uri; try { if (!address.startsWith("mailto:")) { address = "mailto:" + address; } uri = new URI(address); launchEmail(uri); } catch (URISyntaxException e) { throw new IOException("Invalid URI " + address); } } /** * Launches the mail composing window of the user default mail client, filling the message fields specified by a {@code mailto:} URI. *

* A mailto: URI can specify message fields including "to", "cc", "subject", "body", etc. * See The mailto URL scheme (RFC 2368) for the {@code mailto:} URI specification * details. * * @param uri the specified {@code mailto:} URI */ public static void launchEmail(final URI uri) throws IOException { if (uri == null) { throw new IOException("URI must not be null."); } // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT) // Prefer JNA method over AWT, since there are fewer chances for JNA to fail (even though they call the same method) if ((OS.isUnix() || OS.isLinux()) && GtkCheck.isGtkLoaded) { launchNix(uri.toString()); } else if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop() .isSupported(java.awt.Desktop.Action.MAIL)) { // make sure this doesn't block the current UI SwingUtil.invokeLater(new Runnable() { @Override public void run() { try { java.awt.Desktop.getDesktop() .mail(uri); } catch (IOException e) { e.printStackTrace(); } } }); } else { throw new IOException("Current OS and desktop configuration does not support launching an email client"); } } /** * Opens the specified path in the system-default file browser. *

* Works around several OS limitations: * - Apple tries to launch .app bundle directories as applications rather than browsing contents * - Linux has mixed support for Desktop.getDesktop(). Uses JNA instead. * * @param path The directory to browse */ public static void browseDirectory(String path) throws IOException { if (path == null || path.isEmpty()) { throw new IOException("Path must not be null or empty."); } if (OS.isMacOsX()) { File directory = new File(path); // Mac tries to open the .app rather than browsing it. Instead, pass a child with -R to select it in finder File[] files = directory.listFiles(); if (files != null && files.length > 0) { // Get first child File child = files[0]; if (!ShellExecutor.run("open", "-R", child.getCanonicalPath())) { throw new IOException("Error opening the directory for " + path); } } } // Prevent GTK2/3 conflict caused by Desktop.getDesktop(), which is GTK2 only (via AWT) // Prefer JNA method over AWT, since there are fewer chances for JNA to fail (even though they call the same method) else if ((OS.isUnix() || OS.isLinux()) && GtkCheck.isGtkLoaded) { // it can actually be MORE that just "file://" (ie, "ftp://" is legit as well) if (!path.contains("://")) { path = "file://" + path; } launchNix(path); } else if (java.awt.Desktop.isDesktopSupported() && java.awt.Desktop.getDesktop() .isSupported(java.awt.Desktop.Action.OPEN)) { final String finalPath = path; // make sure this doesn't block the current UI SwingUtil.invokeLater(new Runnable() { @Override public void run() { try { java.awt.Desktop.getDesktop() .open(new File(finalPath)); } catch (IOException e) { e.printStackTrace(); } } }); } else { throw new IOException("Current OS and desktop configuration does not support opening a directory to browse"); } } /** * Only called when (OS.isUnix() || OS.isLinux()) && GtkCheck.isGtkLoaded * * Of important note, xdg-open can cause problems in Linux with Chrome installed but not the default browser. It will crash Chrome * if Chrome was open before this app opened a URL * * There are a number of strange bugs with `xdg-open` and `gnome_vfs_url_show_with_env`, ubuntu, once again takes the cake for stupidity. * * @param path the path to open */ private static void launchNix(final String path) { if (GVFS_VALID) { // ubuntu, fedora, etc MIGHT have access to gvfs-open. Ubuntu is also VERY buggy with xdg-open!! ShellExecutor.run(GVFS, path); } else if (OSUtil.DesktopEnv.isGnome() && GnomeVFS.isInited) { GtkEventDispatch.dispatch(new Runnable() { @Override public void run() { // try to open the URL via gnome. This is exactly how (ultimately) java natively does this, but we do it via our own // loaded version of GTK via JNA int errorCode = GnomeVFS.gnome_vfs_url_show_with_env(path, null); if (errorCode != 0) { // if there are problems, use xdg-open // // there are problems with ubuntu and practically everything. Errors galore, and sometimes things don't even work. // see: https://bugzilla.mozilla.org/show_bug.cgi?id=672671 // this can be really buggy ... you have been warned ShellExecutor.run("xdg-open", path); } } }); } else { // just use xdg-open, since it's not gnome. // this can be really buggy ... you have been warned ShellExecutor.run("xdg-open", path); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy