From 9819da58924adfe09930195746f56331fa64788c Mon Sep 17 00:00:00 2001 From: Robinson Date: Sat, 5 Mar 2022 21:46:19 +0100 Subject: [PATCH] Split OS into it's own project --- build.gradle.kts | 2 +- src/dorkbox/jna/linux/AppIndicator.java | 13 +- src/dorkbox/jna/linux/GtkTheme.java | 15 +- src/dorkbox/jna/windows/ShCore.java | 4 +- src/dorkbox/os/OS.kt | 395 --------- src/dorkbox/os/OSType.kt | 87 -- src/dorkbox/os/OSUtil.java | 1071 ----------------------- src/dorkbox/os/package-info.java | 17 - src/dorkbox/util/Desktop.java | 3 +- 9 files changed, 17 insertions(+), 1590 deletions(-) delete mode 100644 src/dorkbox/os/OS.kt delete mode 100644 src/dorkbox/os/OSType.kt delete mode 100644 src/dorkbox/os/OSUtil.java delete mode 100644 src/dorkbox/os/package-info.java diff --git a/build.gradle.kts b/build.gradle.kts index 037dcab..98db579 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -212,7 +212,7 @@ dependencies { api("com.dorkbox:Executor:3.9") api("com.dorkbox:Updates:1.1") - + api("com.dorkbox:OS:1.0") val jnaVersion = "5.10.0" diff --git a/src/dorkbox/jna/linux/AppIndicator.java b/src/dorkbox/jna/linux/AppIndicator.java index 6eec9b5..0a43125 100644 --- a/src/dorkbox/jna/linux/AppIndicator.java +++ b/src/dorkbox/jna/linux/AppIndicator.java @@ -22,7 +22,6 @@ import com.sun.jna.Pointer; import dorkbox.jna.JnaHelper; import dorkbox.jna.linux.structs.AppIndicatorInstanceStruct; import dorkbox.os.OS; -import dorkbox.os.OSUtil; /** * bindings for libappindicator @@ -137,28 +136,28 @@ class AppIndicator { if (isGtk2) { - if (OSUtil.Linux.isDebian()) { + if (OS.Linux.INSTANCE.isDebian()) { // debian is slightly different return "libappindicator1"; } - else if (OSUtil.Linux.isFedora()) { + else if (OS.Linux.INSTANCE.isFedora()) { return "libappindicator-gtk"; } - else if (OSUtil.Linux.isArch()) { + else if (OS.Linux.INSTANCE.isArch()) { return "libappindicator-gtk2"; } else { return "libappindicator"; } } else { - if (OSUtil.Linux.isDebian()) { + if (OS.Linux.INSTANCE.isDebian()) { // debian is slightly different return "libappindicator3-1"; } - else if (OSUtil.Linux.isFedora()) { + else if (OS.Linux.INSTANCE.isFedora()) { return "libappindicator-gtk3"; } - else if (OSUtil.Linux.isArch()) { + else if (OS.Linux.INSTANCE.isArch()) { return "libappindicator-gtk3"; } else { diff --git a/src/dorkbox/jna/linux/GtkTheme.java b/src/dorkbox/jna/linux/GtkTheme.java index 91632ec..d227200 100644 --- a/src/dorkbox/jna/linux/GtkTheme.java +++ b/src/dorkbox/jna/linux/GtkTheme.java @@ -37,7 +37,6 @@ import dorkbox.jna.linux.structs.GtkRequisition; import dorkbox.jna.linux.structs.GtkStyle; import dorkbox.jna.linux.structs.PangoRectangle; import dorkbox.os.OS; -import dorkbox.os.OSUtil; import dorkbox.util.FileUtil; import dorkbox.util.MathUtil; @@ -242,7 +241,7 @@ class GtkTheme { - OSUtil.DesktopEnv.Env env = OSUtil.DesktopEnv.get(); + OS.DesktopEnv.Env env = OS.DesktopEnv.INSTANCE.getEnv(); // sometimes the scaling-factor is set. If we have gsettings, great! otherwise try KDE try { @@ -274,7 +273,7 @@ class GtkTheme { } catch (Throwable ignore) { } - if (OSUtil.DesktopEnv.isKDE()) { + if (OS.DesktopEnv.INSTANCE.isKDE()) { // check the custom KDE override file try { File customSettings = new File("/usr/bin/startkde-custom"); @@ -382,7 +381,7 @@ class GtkTheme { } } - if (OSUtil.Linux.isUbuntu() && OSUtil.DesktopEnv.isUnity(env)) { + if (OS.Linux.INSTANCE.isUbuntu() && OS.DesktopEnv.INSTANCE.isUnity(env)) { // if we measure on ubuntu unity using a screen shot (using swing, so....) , the max size was 24, HOWEVER this goes from // the top->bottom of the indicator bar -- and since it was swing, it uses a different rendering method and it (honestly) // looks weird, because there is no padding for the icon. The official AppIndicator size is hardcoded... @@ -391,9 +390,9 @@ class GtkTheme { return 22; } - if (env == OSUtil.DesktopEnv.Env.XFCE) { + if (env == OS.DesktopEnv.Env.XFCE) { // xfce is easy, because it's not a GTK setting for the size (xfce notification area maximum icon size) - String properties = OSUtil.DesktopEnv.queryXfce("xfce4-panel", null); + String properties = OS.DesktopEnv.INSTANCE.queryXfce("xfce4-panel", null); String[] propertiesAsList = properties.split(OS.INSTANCE.getLINE_SEPARATOR()); for (String prop : propertiesAsList) { if (prop.startsWith("/plugins/") && prop.endsWith("/size-max")) { @@ -403,9 +402,9 @@ class GtkTheme { // xfconf-query -c xfce4-panel -p /plugins/plugin-14 (this will say 'systray' or 'tasklist' or whatever) // find the 'systray' plugin String panelString = prop.substring(0, prop.indexOf("/size-max")); - String panelName = OSUtil.DesktopEnv.queryXfce("xfce4-panel", panelString).trim(); + String panelName = OS.DesktopEnv.INSTANCE.queryXfce("xfce4-panel", panelString).trim(); if (panelName.equals("systray")) { - String size = OSUtil.DesktopEnv.queryXfce("xfce4-panel", prop).trim(); + String size = OS.DesktopEnv.INSTANCE.queryXfce("xfce4-panel", prop).trim(); try { return Integer.parseInt(size); } catch (Exception e) { diff --git a/src/dorkbox/jna/windows/ShCore.java b/src/dorkbox/jna/windows/ShCore.java index 3930492..76da71a 100644 --- a/src/dorkbox/jna/windows/ShCore.java +++ b/src/dorkbox/jna/windows/ShCore.java @@ -22,7 +22,7 @@ import com.sun.jna.platform.win32.WinUser; import com.sun.jna.ptr.IntByReference; import dorkbox.jna.JnaHelper; -import dorkbox.os.OSUtil; +import dorkbox.os.OS; /** * bindings for ShCore.dll @@ -41,7 +41,7 @@ class ShCore { private static Function GetDpiForMonitor = null; static { - if (OSUtil.Windows.isWindows8_1_plus()) { + if (OS.Windows.INSTANCE.isWindows8_1_plus()) { NativeLibrary library = JnaHelper.register("shcore", ShCore.class); // Abusing static fields this way is not proper, but it gets the job done nicely. diff --git a/src/dorkbox/os/OS.kt b/src/dorkbox/os/OS.kt deleted file mode 100644 index 70fa905..0000000 --- a/src/dorkbox/os/OS.kt +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright 2010 dorkbox, llc - * - * 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. - */ -@file:Suppress("unused") - -package dorkbox.os - -import java.awt.Color -import java.io.File -import java.security.AccessController -import java.security.PrivilegedAction -import java.util.* - -object OS { - // make the default unix - val LINE_SEPARATOR = getProperty("line.separator", "\n") - - const val LINE_SEPARATOR_UNIX = "\n" - const val LINE_SEPARATOR_MACOS = "\r" - const val LINE_SEPARATOR_WINDOWS = "\r\n" - - val TEMP_DIR = File(getProperty("java.io.tmpdir", "temp")).absoluteFile - - /** - * The currently running MAJOR java version as a NUMBER. For example, "Java version 1.7u45", and converts it into 7, uses JEP 223 for java > 9 - */ - val javaVersion: Int by lazy { - // this should never be a problem, but just in case - var fullJavaVersion = getProperty("java.version", "8") - if (fullJavaVersion.startsWith("1.")) { - when (fullJavaVersion[2]) { - '4' -> 4 - '5' -> 5 - '6' -> 6 - '7' -> 7 - '8' -> 8 - '9' -> 9 - else -> { - 8 - } - } - } else { - // We are >= java 10, use JEP 223 to get the version (early releases of 9 might not have JEP 223, so 10 is guaranteed to have it) - fullJavaVersion = getProperty("java.specification.version", "10") - - try { - // it will ALWAYS be the major release version as an integer. See http://openjdk.java.net/jeps/223 - fullJavaVersion.toInt() - } catch (ignored: Exception) { - } - } - - // the last valid guess we have, since the current Java implementation, whatever it is, decided not to cooperate with JEP 223. - 8 - } - - /** - * Returns the *ORIGINAL* system time zone, before (*IF*) it was changed to UTC - */ - val originalTimeZone = TimeZone.getDefault().id - - /** - * JVM reported osName, the default (if there is none detected) is 'linux' - */ - val osName = getProperty("os.name", "linux").lowercase() - - /** - * JVM reported osArch, the default (if there is none detected) is 'amd64' - */ - val osArch = getProperty("os.arch", "amd64").lowercase() - - /** - * @return the optimum number of threads for a given task. Makes certain not to take ALL the threads, always returns at least one - * thread. - */ - val optimumNumberOfThreads = (Runtime.getRuntime().availableProcessors() - 2).coerceAtLeast(1) - - /** - * The determined OS type - */ - val type: OSType by lazy { - if (osName.startsWith("linux")) { - // best way to determine if it's android. - // Sometimes java binaries include Android classes on the classpath, even if it isn't actually Android, so we check the VM - val isAndroid = "Dalvik" == getProperty("java.vm.name", "") - if (isAndroid) { - // android check from https://stackoverflow.com/questions/14859954/android-os-arch-output-for-arm-mips-x86 - when (osArch) { - "armeabi" -> { - OSType.AndroidArm56 // really old/low-end non-hf 32bit cpu - } - "armeabi-v7a" -> { - OSType.AndroidArm7 // 32bit hf cpu - } - "arm64-v8a" -> { - OSType.AndroidArm8 // 64bit hf cpu - } - "x86" -> { - OSType.AndroidX86 // 32bit x86 (usually emulator) - } - "x86_64" -> { - OSType.AndroidX86_64 // 64bit x86 (usually emulator) - } - "mips" -> { - OSType.AndroidMips // 32bit mips - } - "mips64" -> { - OSType.AndroidMips64 // 64bit mips - } - else -> { - throw java.lang.RuntimeException("Unable to determine OS type for $osName $osArch") - } - } - } else { - // http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-April/012107.html - when(osArch) { - "i386", "x86" -> { - OSType.Linux32 - } - "arm" -> { - OSType.LinuxArm32 - } - - "x86_64", "amd64" -> { - OSType.Linux64 - } - "aarch64" -> { - OSType.LinuxArm64 - } - else -> { - when { - // oddballs (android usually) - osArch.startsWith("arm64") -> { - OSType.LinuxArm64 - } - osArch.startsWith("arm") -> { - if (osArch.contains("v8")) { - OSType.LinuxArm64 - } else { - OSType.LinuxArm32 - } - } - else -> { - throw java.lang.RuntimeException("Unable to determine OS type for $osName $osArch") - } - } - } - } - } - } else if (osName.startsWith("windows")) { - if ("amd64" == osArch) { - OSType.Windows64 - } else { - OSType.Windows32 - } - } else if (osName.startsWith("mac") || osName.startsWith("darwin")) { - when (osArch) { - "x86_64", "aarch64" -> { - OSType.MacOsX64 - } - else -> { - OSType.MacOsX32 // new macosx is no longer 32 bit, but just in case. - } - } - } else if (osName.startsWith("freebsd") || - osName.contains("nix") || - osName.contains("nux") || - osName.startsWith("aix")) { - when (osArch) { - "x86", "i386" -> { - OSType.Unix32 - } - "arm" -> { - OSType.UnixArm - } - else -> { - OSType.Unix64 - } - } - } else if (osName.startsWith("solaris") || - osName.startsWith("sunos")) { - OSType.Solaris - } else { - throw java.lang.RuntimeException("Unable to determine OS type for $osName $osArch") - } - } - - init { - if (!TEMP_DIR.isDirectory) { - // create the temp dir if necessary because the TEMP dir doesn't exist. - TEMP_DIR.mkdirs() - } - - /* - * By default, the timer resolution on Windows ARE NOT high-resolution (16ms vs 1ms) - * - * 'Thread.sleep(1)' will not really sleep for 1ms, but will really sleep for ~16ms. This long-running sleep will trick Windows - * into using higher resolution timers. - * - * See: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6435126 - */ - if (type.isWindows) { - // only necessary on windows - val timerAccuracyThread = Thread( - { - while (true) { - try { - Thread.sleep(Long.MAX_VALUE) - } catch (ignored: Exception) { - } - } - }, "FixWindowsHighResTimer") - timerAccuracyThread.isDaemon = true - timerAccuracyThread.start() - } - } - - /** - * @return the System Property in a safe way for a given property, or null if it does not exist. - */ - fun getProperty(property: String): String? { - return try { - if (System.getSecurityManager() == null) { - System.getProperty(property, null) - } else { - AccessController.doPrivileged(PrivilegedAction { System.getProperty(property, null) }) - } - } catch (ignored: Exception) { - null - } - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getProperty(property: String, defaultValue: String): String { - return try { - if (System.getSecurityManager() == null) { - System.getProperty(property, defaultValue) - } else { - AccessController.doPrivileged(PrivilegedAction { System.getProperty(property, defaultValue) }) - } - } catch (ignored: Exception) { - defaultValue - } - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getBoolean(property: String, defaultValue: Boolean): Boolean { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' }.lowercase(Locale.getDefault()) - if (value.isEmpty()) { - return defaultValue - } - - if ("false" == value || "no" == value || "0" == value) { - return false - } - - return if ("true" == value || "yes" == value || "1" == value) { - true - } else defaultValue - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getInt(property: String, defaultValue: Int): Int { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' } - - try { - return value.toInt() - } catch (ignored: Exception) { - } - return defaultValue - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getLong(property: String, defaultValue: Long): Long { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' } - - try { - return value.toLong() - } catch (ignored: Exception) { - } - return defaultValue - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getFloat(property: String, defaultValue: Float): Float { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' } - - try { - return value.toFloat() - } catch (ignored: Exception) { - } - return defaultValue - } - - /** - * @return the value of the Java system property with the specified `property`, while falling back to the - * specified default value if the property access fails. - */ - fun getDouble(property: String, defaultValue: Double): Double { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' } - - try { - return value.toDouble() - } catch (ignored: Exception) { - } - return defaultValue - } - - fun getColor(property: String, defaultValue: Color): Color { - var value = getProperty(property) ?: return defaultValue - value = value.trim { it <= ' ' } - - try { - return Color.decode(value) - } catch (ignored: Exception) { - } - return defaultValue - } - - - - val is32bit = type.is32bit - val is64bit = type.is64bit - - /** - * @return true if this is a x86/x64/arm architecture (intel/amd/etc) processor. - */ - val isX86 = type.isX86 - val isMips = type.isMips - val isArm = type.isArm - - - val isLinux = type.isLinux - val isUnix = type.isUnix - val isSolaris = type.isSolaris - val isWindows = type.isWindows - val isMacOsX = type.isMacOsX - val isAndroid = type.isAndroid - - /** - * Set our system to UTC time zone. Retrieve the **original** time zone via [.getOriginalTimeZone] - */ - fun setUTC() { - // have to set our default timezone to UTC. EVERYTHING will be UTC, and if we want local, we must explicitly ask for it. - TimeZone.setDefault(TimeZone.getTimeZone("UTC")) - } - - /** - * @return the first line of the exception message from 'throwable', or the type if there was no message. - */ - fun getExceptionMessage(throwable: Throwable): String? { - var message = throwable.message - if (message != null) { - val index = message.indexOf(LINE_SEPARATOR) - if (index > -1) { - message = message.substring(0, index) - } - } else { - message = throwable.javaClass.simpleName - } - return message - } -} diff --git a/src/dorkbox/os/OSType.kt b/src/dorkbox/os/OSType.kt deleted file mode 100644 index 86f62a8..0000000 --- a/src/dorkbox/os/OSType.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2010 dorkbox, llc - * - * 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.os - -enum class OSType(name: String, vararg libraryNames: String) { - Windows32("windows_32", ".dll"), - Windows64("windows_64", ".dll"), - Linux32("linux_32", ".so"), - Linux64("linux_64", ".so"), - - MacOsX32("macosx_32", ".jnilib", ".dylib"), - MacOsX64("macosx_64", ".jnilib", ".dylib"), - UnixArm("unix_arm", ".so"), - Unix32("unix_32",".so"), - - Unix64("unix_64", ".so"), - Solaris("solaris", ".so"), - AndroidArm56("android_arm56", ".so"), // 32bit no hardware float support - AndroidArm7("android_arm7", ".so"), // 32bit hardware float support - AndroidArm8("android_arm8", ".so"), // 64bit (w/ hardware float. everything now has hard float) - AndroidMips("android_mips", ".so"), // 32bit mips - AndroidX86("android_x86", ".so"), // 32bit x86 (usually emulator) - AndroidMips64("android_mips64", ".so"), // 64bit mips - AndroidX86_64("android_x86_64", ".so"), // 64bit x86 (usually emulator) - - /* - * Linux OS, Hard float, meaning floats are handled in hardware. WE ONLY SUPPORT HARD FLOATS for linux ARM!. - * For Raspberry-PI, Beaglebone, Odroid, etc PCs - */ - LinuxArm32("linux_arm7_hf", ".so"), - LinuxArm64("linux_arm8_hf", ".so"); - - - val standardName: String - val libraryNames: Array - - init { - this.standardName = name - this.libraryNames = libraryNames - } - - val is64bit: Boolean - get() { - return this == Linux64 || this == LinuxArm64 || this == Windows64 || this == MacOsX64 || this == AndroidArm8 || this == AndroidX86_64 || this == AndroidMips64 || this == Unix64 - } - - val is32bit: Boolean - get() { - return this == Linux32 || this == LinuxArm32 || this == Windows32 || this == MacOsX32 || this == AndroidArm56 || this == AndroidArm7 || this == AndroidX86 || this == AndroidMips || this == UnixArm || this == Unix32 - } - - val isMips: Boolean - get() = this == AndroidMips || this == AndroidMips64 - - /** - * @return true if this is a "standard" x86/x64 architecture (intel/amd/etc) processor. - */ - val isX86: Boolean - get() = this == Linux64 || this == LinuxArm64 || this == Windows64 || this == MacOsX64 || this == Linux32 || this == LinuxArm32 || this == Windows32 || this == MacOsX32 || this == Unix32 || this == Unix64 || this == AndroidX86 || this == AndroidX86_64 - val isArm: Boolean - get() = this == LinuxArm32 || this == LinuxArm64 || this == AndroidArm56 || this == AndroidArm7 || this == AndroidArm8 - val isLinux: Boolean - get() = this == Linux32 || this == Linux64 || this == LinuxArm64 || this == LinuxArm32 - val isUnix: Boolean - get() = this == Unix32 || this == Unix64 || this == UnixArm - val isSolaris: Boolean - get() = this == Solaris - val isWindows: Boolean - get() = this == Windows64 || this == Windows32 - val isMacOsX: Boolean - get() = this == MacOsX64 || this == MacOsX32 - val isAndroid: Boolean - get() = this == AndroidArm56 || this == AndroidArm7 || this == AndroidX86 || this == AndroidMips || this == AndroidArm8 || this == AndroidX86_64 || this == AndroidMips64 -} diff --git a/src/dorkbox/os/OSUtil.java b/src/dorkbox/os/OSUtil.java deleted file mode 100644 index 869b5aa..0000000 --- a/src/dorkbox/os/OSUtil.java +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * Copyright 2015 dorkbox, llc - * - * 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.os; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import dorkbox.executor.Executor; - -/** - * Container for all OS specific tests and methods. These do not exist in OS.java, because of dependency issues (OS.java should not - * depend on any native libraries) - */ -@SuppressWarnings("unused") -public -class OSUtil { - public static - class Windows { - /** - * Version info at release. - * - * https://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions - * - * Windows XP 5.1.2600 (2001-10-25) - * Windows Server 2003 5.2.3790 (2003-04-24) - * - * Windows Home Server 5.2.3790 (2007-06-16) - * - * ------------------------------------------------- - * - * Windows Vista 6.0.6000 (2006-11-08) - * Windows Server 2008 SP1 6.0.6001 (2008-02-27) - * Windows Server 2008 SP2 6.0.6002 (2009-04-28) - * - * ------------------------------------------------- - * - * Windows 7 6.1.7600 (2009-10-22) - * Windows Server 2008 R2 6.1.7600 (2009-10-22) - * Windows Server 2008 R2 SP1 6.1.7601 (?) - * - * Windows Home Server 2011 6.1.8400 (2011-04-05) - * - * ------------------------------------------------- - * - * Windows 8 6.2.9200 (2012-10-26) - * Windows Server 2012 6.2.9200 (2012-09-04) - * - * ------------------------------------------------- - * - * Windows 8.1 6.3.9600 (2013-10-18) - * Windows Server 2012 R2 6.3.9600 (2013-10-18) - * - * ------------------------------------------------- - * - * Windows 10 10.0.10240 (2015-07-29) - * Windows 10 10.0.10586 (2015-11-12) - * Windows 10 10.0.14393 (2016-07-18) - * - * Windows Server 2016 10.0.14393 (2016-10-12) - * - * @return the [major][minor] version of windows, ie: Windows Version 10.0.10586 -> [10][0] - */ - public static - int[] getVersion() { - int[] version = new int[2]; - - if (!OS.INSTANCE.isWindows()) { - return version; - } - - try { - String output = System.getProperty("os.version"); - String[] split = output.split("\\.",-1); - - if (split.length <= 2) { - for (int i = 0; i < split.length; i++) { - version[i] = Integer.parseInt(split[i]); - } - } - } catch (Throwable ignored) { - } - - return version; - } - - /** - * @return is windows XP or equivalent - */ - public static - boolean isWindowsXP() { - return getVersion()[0] == 5; - } - - /** - * @return is windows Vista or equivalent - */ - public static - boolean isWindowsVista() { - int[] version = getVersion(); - return version[0] == 6 && version[1] == 0; - } - - /** - * @return is windows 7 or equivalent - */ - public static - boolean isWindows7() { - int[] version = getVersion(); - return version[0] == 6 && version[1] == 1; - } - - /** - * @return is windows 8 or equivalent - */ - public static - boolean isWindows8() { - int[] version = getVersion(); - return version[0] == 6 && version[1] == 2; - } - - /** - * @return is windows 8.1 or equivalent - */ - public static - boolean isWindows8_1() { - int[] version = getVersion(); - return version[0] == 6 && version[1] == 3; - } - - /** - * @return is greater than or equal to windows 8.1 or equivalent - */ - public static - boolean isWindows8_1_plus() { - int[] version = getVersion(); - if (version[0] == 6 && version[1] >= 3) { - return true; - } - else { - return version[0] > 6; - } - } - - /** - * @return is windows 10 or equivalent - */ - public static - boolean isWindows10() { - return getVersion()[0] == 10; - } - - /** - * @return is windows 10 or greater - */ - public static - boolean isWindows10_plus() { - return getVersion()[0] >= 10; - } - } - - public static - class Unix { - public static - boolean isFreeBSD() { - if (!OS.INSTANCE.isUnix()) { - return false; - } - - try { - // uname - return Executor.Companion.run("uname").startsWith("FreeBSD"); - } catch (Throwable ignored) { - } - - return false; - } - } - - @SuppressWarnings("WeakerAccess") - public static - class Linux { - private static String info = null; - - /** - * @return os release info or "" - */ - public static - String getInfo() { - if (info != null) { - return info; - } - - if (!OS.INSTANCE.isLinux()) { - info = ""; - return info; - } - - try { - List releaseFiles = new LinkedList<>(); - int totalLength = 0; - - // looking for files like /etc/os-release - File file = new File("/etc"); - if (file.isDirectory()) { - File[] list = file.listFiles(); - if (list != null) { - for (File f : list) { - if (f.isFile() && f.getName().contains("release")) { - // this is likely a file we are interested in. - releaseFiles.add(f); - totalLength += (int) file.length(); - } - } - } - } - - if (totalLength > 0) { - StringBuilder fileContents = new StringBuilder(totalLength); - - for (File releaseFile : releaseFiles) { - try (BufferedReader reader = new BufferedReader(new FileReader(releaseFile))) { - String currentLine; - - // NAME="Arch Linux" - // PRETTY_NAME="Arch Linux" - // ID=arch - // ID_LIKE=archlinux - // ANSI_COLOR="0;36" - // HOME_URL="https://www.archlinux.org/" - // SUPPORT_URL="https://bbs.archlinux.org/" - // BUG_REPORT_URL="https://bugs.archlinux.org/" - - // similar on other distro's. ID is always the "key" to the distro - - while ((currentLine = reader.readLine()) != null) { - fileContents.append(currentLine) - .append(OS.LINE_SEPARATOR_UNIX); - } - } - } - - info = fileContents.toString(); - return info; - } - } catch (Throwable ignored) { - } - - info = ""; - return info; - } - - /** - * @param id the info ID to check, ie: ubuntu, arch, debian, etc... This is what the OS vendor uses to ID their OS. - * @return true if this OS is identified as the specified ID. - */ - public static - boolean getInfo(String id) { - // also matches on 'DISTRIB_ID' and 'VERSION_ID' - // ID=linuxmint/fedora/arch/ubuntu/etc - return getInfo().contains("ID=" + id + "\n"); - } - - private static volatile Boolean isArch = null; - public static - boolean isArch() { - if (isArch == null) { - isArch = getInfo("arch"); - } - return isArch; - } - - private static volatile Boolean isDebian = null; - public static - boolean isDebian() { - if (isDebian == null) { - isDebian = getInfo("debian"); - } - return isDebian; - } - - private static volatile Boolean isElementaryOS = null; - public static - boolean isElementaryOS() { - if (isElementaryOS == null) { - try { - String output = getInfo(); - // ID="elementary" (notice the extra quotes) - isElementaryOS = output.contains("ID=\"elementary\"\n") || output.contains("ID=elementary\n") || - - // this is specific to eOS < 0.3.2 - output.contains("ID=\"elementary OS\"\n"); - } catch (Throwable ignored) { - isElementaryOS = false; - } - } - return isElementaryOS; - } - - private static volatile Boolean isFedora = null; - public static - boolean isFedora() { - if (isFedora == null) { - isFedora = getInfo("fedora"); - } - return isFedora; - } - - private static volatile Integer fedoraVersion = null; - public static - int getFedoraVersion() { - if (fedoraVersion != null) { - return fedoraVersion; - } - - if (!isFedora()) { - fedoraVersion = 0; - return fedoraVersion; - } - - try { - String output = getInfo(); - - // ID=fedora - if (output.contains("ID=fedora\n")) { - // should be: VERSION_ID=23\n or something - int beginIndex = output.indexOf("VERSION_ID=") + 11; - String fedoraVersion_ = output.substring(beginIndex, output.indexOf(OS.LINE_SEPARATOR_UNIX, beginIndex)); - - fedoraVersion = Integer.parseInt(fedoraVersion_); - return fedoraVersion; - } - } catch (Throwable ignored) { - } - - fedoraVersion = 0; - return fedoraVersion; - } - - private static volatile Boolean isLinuxMint = null; - public static - boolean isLinuxMint() { - if (isLinuxMint == null) { - isLinuxMint = getInfo("linuxmint"); - } - return isLinuxMint; - } - - private static volatile Boolean isUbuntu = null; - public static - boolean isUbuntu() { - if (isUbuntu == null) { - isUbuntu = getInfo("ubuntu"); - } - return isUbuntu; - } - - private static volatile int[] ubuntuVersion = null; - public static - int[] getUbuntuVersion() { - if (ubuntuVersion != null) { - return ubuntuVersion; - } - - if (!isUbuntu()) { - ubuntuVersion = new int[]{0,0}; - return ubuntuVersion; - } - - String distribReleaseInfo = getDistribReleaseInfo(); - if (distribReleaseInfo != null) { - String[] split = distribReleaseInfo.split("\\."); - - ubuntuVersion = new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1])}; - return ubuntuVersion; - } - - - ubuntuVersion = new int[]{0,0}; - return ubuntuVersion; - } - - private static volatile int[] elementaryOSVersion = null; - public static - int[] getElementaryOSVersion() { - // 0.1 Jupiter. The first stable version of elementary OS was Jupiter, published on 31 March 2011 and based on Ubuntu 10.10. ... - // 0.2 Luna. elementary OS 0.2 "Luna" ... - // 0.3 Freya. elementary OS 0.3 "Freya" ... - // 0.4 Loki. elementary OS 0.4, known by its codename, "Loki", was released on 9 September 2016. ... - // 5.0 Juno - - if (elementaryOSVersion != null) { - return elementaryOSVersion; - } - - if (!isElementaryOS()) { - elementaryOSVersion = new int[]{0,0}; - return elementaryOSVersion; - } - - String distribReleaseInfo = getDistribReleaseInfo(); - if (distribReleaseInfo != null) { - String[] split = distribReleaseInfo.split("\\."); - - elementaryOSVersion = new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1])}; - return elementaryOSVersion; - } - - elementaryOSVersion = new int[]{0,0}; - return elementaryOSVersion; - } - - - private static Boolean isKali = null; - public static - boolean isKali() { - if (isKali == null) { - isKali = getInfo("kali"); - } - return isKali; - } - - private static Boolean isPop = null; - public static - boolean isPop() { - if (isPop == null) { - isPop = getInfo("pop"); - } - return isPop; - } - - private static Boolean isIgel = null; - public static - boolean isIgel() { - if (isIgel == null) { - isIgel = getInfo("IGEL"); - } - return isIgel; - } - - /** - * @return the `DISTRIB_RELEASE` info as a String, if possible. Otherwise NULL - */ - public static - String getDistribReleaseInfo() { - String info = getInfo(); - String releaseString = "DISTRIB_RELEASE="; - int index = info.indexOf(releaseString); - try { - if (index > -1) { - index += releaseString.length(); - int newLine = info.indexOf(OS.LINE_SEPARATOR_UNIX, index); - if (newLine > index) { - return info.substring(index, newLine); - } - } - } catch (Throwable ignored) { - } - - return null; - } - - private static volatile Boolean isWSL = null; - public static - boolean isWSL() { - if (isWSL == null) { - try { - // looking for /proc/version - File file = new File("/proc/version"); - if (file.canRead()) { - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - // Linux version 4.4.0-19041-Microsoft (Microsoft@Microsoft.com) (gcc version 5.4.0 (GCC) ) #488-Microsoft Mon Sep 01 13:43:00 PST 2020 - - String currentLine = reader.readLine(); - isWSL = currentLine.contains("-Microsoft"); - } catch (Throwable ignored) { - } - } - - if (isWSL == null) { - // reading the file didn't work for whatever reason... - // uname -v - isWSL = Executor.Companion.run("uname", "-v").contains("-Microsoft"); - } - } catch (Throwable ignored) { - isWSL = false; - } - } - return isWSL; - } - - public static - boolean isRoot() { - // this means we are running as sudo - boolean isSudoOrRoot = System.getenv("SUDO_USER") != null; - - if (!isSudoOrRoot) { - // running as root (also can be "sudo" user). A lot slower that checking a sys env, but this is guaranteed to work - try { - // id -u - isSudoOrRoot = "0".equals(Executor.Companion.run("id", "-u")); - } catch (Throwable ignored) { - } - } - - return isSudoOrRoot; - } - - - - - - public static - class PackageManager { - public enum Type { - APT("apt install"), - APTGET("apt-get install"), - YUM("yum install"), - PACMAN("pacman -S "), - ; - - private final String installString; - - Type(final String installString) { - this.installString = installString; - } - - public - String installString() { - return installString; - } - } - - public static - Type get() { - if (new File("/usr/bin/apt").canExecute()) { - return Type.APT; - } - - if (new File("/usr/bin/apt-get").canExecute()) { - return Type.APTGET; - } - - if (new File("/usr/bin/yum").canExecute()) { - return Type.YUM; - } - - if (new File("/usr/bin/pacman").canExecute()) { - return Type.PACMAN; - } - - // default is apt-get, even if it isn't correct - return Type.APTGET; - } - - - /** - * @return true if the package is installed - */ - public static - boolean isPackageInstalled(final String packageName) { - // dpkg - // dpkg -L libappindicator3 - // dpkg-query: package 'libappindicator3' is not installed - boolean is_dpkg = new File("/usr/bin/dpkg").canExecute(); - if (is_dpkg) { - return !Executor.Companion.run("dpkg", "-L", packageName).contains("is not installed"); - } - - // rpm - // rpm -q libappindicator234 - // package libappindicator234 is not installed - boolean is_rpm = new File("/usr/bin/rpm").canExecute(); - if (is_rpm) { - return !Executor.Companion.run("rpm", "-q", packageName).contains("is not installed"); - } - - - // pacman - // pacman -Qi - // use the exit code to determine if the packages exists on the system or not (0 the package exists, 1 it doesn't) - boolean is_pacmac = new File("/usr/bin/pacman").canExecute(); - try { - int start = new Executor().command("pacman", "-Qi", packageName) - .startBlocking() - .getExitValue(); - - // 0 the package exists, 1 it doesn't - return start == 0; - } catch (Exception ignored) { - } - - return false; - } - } - } - - @SuppressWarnings("WeakerAccess") - public static - class DesktopEnv { - public enum Env { - Gnome, - KDE, - Unity, - Unity7, - XFCE, - LXDE, - MATE, - Pantheon, - ChromeOS, - Unknown, - } - - public enum EnvType { - X11, - WAYLAND, - Unknown, - } - - public static - Env get() { - // if we are running as ROOT, we *** WILL NOT *** have access to 'XDG_CURRENT_DESKTOP' - // *unless env's are preserved, but they are not guaranteed to be - // see: http://askubuntu.com/questions/72549/how-to-determine-which-window-manager-is-running - String XDG = System.getenv("XDG_CURRENT_DESKTOP"); - if (XDG == null) { - // maybe we are running as root??? - XDG = "unknown"; // try to autodetect if we should use app indicator or gtkstatusicon - } - - // Ubuntu 17.10+ is special ... this is ubuntu:GNOME (it now uses wayland instead of x11, so many things have changed...) - // So it's gnome, and gnome-shell, but with some caveats - // see: https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1700465 - - // BLEH. if gnome-shell is running, IT'S REALLY GNOME! - // we must ALWAYS do this check!! - if (OSUtil.DesktopEnv.isGnome()) { - XDG = "gnome"; - } - else if (OSUtil.DesktopEnv.isKDE()) { - // same thing with plasmashell! - XDG = "kde"; - } - else if (DesktopEnv.isXfce()) { - // https://github.com/dorkbox/SystemTray/issues/100 - // IGEL linux doesn't say what it is... but we know it's XFCE ... EVEN THOUGH it reports X11!! - XDG = "xfce"; - } - - // Ubuntu Unity is a weird combination. It's "Gnome", but it's not "Gnome Shell". - if ("unity".equalsIgnoreCase(XDG)) { - return Env.Unity; - } - // Ubuntu Unity7 is a weird combination. It's "Gnome", but it's not "Gnome Shell". - if ("unity:unity7".equalsIgnoreCase(XDG)) { - return Env.Unity7; - } - if ("xfce".equalsIgnoreCase(XDG)) { - return Env.XFCE; - } - if ("lxde".equalsIgnoreCase(XDG)) { - return Env.LXDE; - } - if ("kde".equalsIgnoreCase(XDG)) { - return Env.KDE; - } - if ("pantheon".equalsIgnoreCase(XDG)) { - return Env.Pantheon; - } - if ("gnome".equalsIgnoreCase(XDG)) { - return Env.Gnome; - } - - // maybe it's chromeOS? - if (isChromeOS()) { - return Env.ChromeOS; - } - - if (isMATE()) { - return Env.MATE; - } - - return Env.Unknown; - } - - private static - boolean isValidCommand(final String partialExpectationInOutput, final String commandOutput) { - return commandOutput.contains(partialExpectationInOutput) - && !commandOutput.contains("not installed") - && !commandOutput.contains ("No such file or directory"); - } - - - public static EnvType getType() { - String XDG = System.getenv("XDG_SESSION_TYPE"); - if (XDG == null) { - XDG = "unknown"; // have no idea how this can happen.... - } - - if ("x11".equals(XDG)) { - return EnvType.X11; - } - - if ("wayland".equals(XDG)) { - return EnvType.WAYLAND; - } - - return EnvType.Unknown; - } - - public static - boolean isX11() { - EnvType env = getType(); - return env == EnvType.X11; - } - - public static - boolean isWayland() { - EnvType env = getType(); - return env == EnvType.WAYLAND; - } - - public static - boolean isUnity() { - Env env = get(); - return isUnity(env); - } - - public static - boolean isUnity(final Env env) { - return env == OSUtil.DesktopEnv.Env.Unity || env == OSUtil.DesktopEnv.Env.Unity7; - } - - - private static volatile Boolean isMATE = null; - public static - boolean isMATE() { - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return false; - } - - if (isMATE != null) { - return isMATE; - } - - try { - isMATE = new File("/usr/bin/mate-about").exists(); - return isMATE; - } catch (Throwable ignored) { - } - - isMATE = false; - return isMATE; - } - - private static volatile Boolean isGnome = null; - public static - boolean isGnome() { - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return false; - } - - if (isGnome != null) { - return isGnome; - } - - try { - // note: some versions of linux can ONLY access "ps a"; FreeBSD and most linux is "ps x" - // we try "x" first - - // ps x | grep gnome-shell - boolean contains = Executor.Companion.run("ps", "x").contains("gnome-shell"); - - if (!contains && OS.INSTANCE.isLinux()) { - // only try again if we are linux - - // ps a | grep gnome-shell - contains = Executor.Companion.run("ps", "a").contains("gnome-shell"); - } - - isGnome = contains; - return isGnome; - } catch (Throwable ignored) { - } - - isGnome = false; - return isGnome; - } - - private static volatile boolean hasGnomeVersion = false; - private static volatile String gnomeVersion = null; - /** - * @return a string representing the current gnome-shell version, or NULL if it could not be found - */ - public static - String getGnomeVersion() { - if (hasGnomeVersion) { - return gnomeVersion; - } - - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return null; - } - - hasGnomeVersion = true; - - try { - // gnome-shell --version - String versionString = Executor.Companion.run("gnome-shell", "--version"); - - if (!versionString.isEmpty()) { - // GNOME Shell 3.14.1 - String version = versionString.replaceAll("[^\\d.]", ""); - if (version.length() > 0 && version.indexOf('.') > 0) { - // should just be 3.14.1 or 3.20 or similar - gnomeVersion = version; - return gnomeVersion; - } - } - } catch (Throwable ignored) { - } - - gnomeVersion = null; - return gnomeVersion; - } - - private static volatile Boolean isKDE = null; - public static - boolean isKDE() { - if (isKDE != null) { - return isKDE; - } - - String XDG = System.getenv("XDG_CURRENT_DESKTOP"); - if (XDG == null) { - // Check if plasmashell is running, if it is -- then we are most likely KDE - double plasmaVersion = OSUtil.DesktopEnv.getPlasmaVersion(); - - isKDE = plasmaVersion > 0; - return isKDE; - } else if ("kde".equalsIgnoreCase(XDG)) { - isKDE = true; - return false; - } - - isKDE = false; - return false; - } - - /** - * The first two decimal places of the version number of plasma shell (if running) as a double. - * - * @return cannot represent '5.6.5' as a number, so we return just the first two decimal places instead - */ - public static - double getPlasmaVersion() { - String versionAsString = getPlasmaVersionFull(); - - if (versionAsString == null) { - return 0; - } - - if (versionAsString.startsWith("0")) { - return 0; - } - - // this isn't the BEST way to do this, but it's simple and easy to understand - String[] split = versionAsString.split("\\.",3); - if (split.length > 2) { - return Double.parseDouble(split[0] + "." + split[1]); - } else { - return Double.parseDouble(split[0]); - } - } - - - private static volatile boolean hasPlasmaVersion = false; - private static volatile String getPlasmaVersionFull = null; - /** - * The full version number of plasma shell (if running) as a String. - * - * @return cannot represent '5.6.5' as a number, so we return a String instead or NULL if unknown - */ - public static - String getPlasmaVersionFull() { - if (hasPlasmaVersion) { - return getPlasmaVersionFull; - } - - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return null; - } - - hasPlasmaVersion = true; - - try { - // plasma-desktop -v - // plasmashell --version - String output = Executor.Companion.run("plasmashell", "--version"); - - if (!output.isEmpty()) { - // DEFAULT icon size is 16. KDE is bananas on what they did with tray icon scale - // should be: plasmashell 5.6.5 or something - String s = "plasmashell "; - if (isValidCommand(s, output)) { - getPlasmaVersionFull = output.substring(output.indexOf(s) + s.length()); - return getPlasmaVersionFull; - } - } - } catch (Throwable ignored) { - } - - return null; - } - - private static volatile Boolean isXfce = null; - public static - boolean isXfce() { - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return false; - } - - if (isXfce != null) { - return isXfce; - } - - try { - // note: some versions of linux can ONLY access "ps a"; FreeBSD and most linux is "ps x" - // we try "x" first - - // ps x | grep xfce - boolean contains = Executor.Companion.run("ps", "x").contains("xfce"); - - if (!contains && OS.INSTANCE.isLinux()) { - // only try again if we are linux - - // ps a | grep gnome-shell - contains = Executor.Companion.run("ps", "a").contains("xfce"); - } - - isXfce = contains; - return isXfce; - } catch (Throwable ignored) { - } - - isXfce = false; - return isXfce; - } - - - private static volatile Boolean isNautilus = null; - /** - * There are sometimes problems with nautilus (the file browser) and some GTK methods. It is ridiculous for me to have to - * work around their bugs like this. - *

- * see: https://askubuntu.com/questions/788182/nautilus-not-opening-up-showing-glib-error - */ - public static - boolean isNautilus() { - if (isNautilus != null) { - return isNautilus; - } - - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - isNautilus = false; - return false; - } - - try { - // nautilus --version - String output = Executor.Companion.run("nautilus", "--version"); - - if (!output.isEmpty()) { - // should be: GNOME nautilus 3.14.3 or something - String s = "GNOME nautilus "; - if (isValidCommand(s, output)) { - isNautilus = true; - return true; - } - } - } catch (Throwable ignored) { - } - - isNautilus = false; - return false; - } - - - private static volatile Boolean isChromeOS = null; - public static - boolean isChromeOS() { - if (isChromeOS == null) { - if (!OS.INSTANCE.isLinux()) { - isChromeOS = false; - return false; - } - - isChromeOS = false; - try { - // ps aux | grep chromeos - String output = Executor.Companion.run("ps", "aux"); - - if (!output.isEmpty()) { - if (output.contains("chromeos")) { - isChromeOS = true; - return true; - } - } - } catch (Throwable ignored) { - } - } - - return isChromeOS; - } - - /** - * @param channel which XFCE channel to query. Cannot be null - * @param property which property (in the channel) to query. Null will list all properties in the channel - * - * @return the property value or "". - */ - public static - String queryXfce(String channel, String property) { - if (!OS.INSTANCE.isLinux() && !OS.INSTANCE.isUnix()) { - return ""; - } - - if (channel == null) { - return ""; - } - - try { - // xfconf-query -c xfce4-panel -l - List commands = new ArrayList<>(); - commands.add("xfconf-query"); - commands.add("-c"); - commands.add(channel); - - if (property != null) { - // get property for channel - commands.add("-p"); - commands.add(property); - } else { - // list all properties for the channel - commands.add("-l"); - } - - return Executor.Companion.run(commands); - } catch (Throwable ignored) { - } - - return ""; - } - } -} diff --git a/src/dorkbox/os/package-info.java b/src/dorkbox/os/package-info.java deleted file mode 100644 index 860f889..0000000 --- a/src/dorkbox/os/package-info.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021 dorkbox, llc - * - * 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.os; diff --git a/src/dorkbox/util/Desktop.java b/src/dorkbox/util/Desktop.java index 490c3af..5be92cc 100644 --- a/src/dorkbox/util/Desktop.java +++ b/src/dorkbox/util/Desktop.java @@ -29,7 +29,6 @@ import dorkbox.jna.linux.GnomeVFS; import dorkbox.jna.linux.GtkCheck; import dorkbox.jna.linux.GtkEventDispatch; import dorkbox.os.OS; -import dorkbox.os.OSUtil; @SuppressWarnings({"WeakerAccess", "Convert2Lambda", "Duplicates"}) public @@ -311,7 +310,7 @@ class Desktop { // ubuntu, fedora, etc MIGHT have access to gvfs-open. Ubuntu is also VERY buggy with xdg-open!! new Executor().command(GVFS, path).startAsync(); } - else if (OSUtil.DesktopEnv.isGnome() && GnomeVFS.isInited) { + else if (OS.DesktopEnv.INSTANCE.isGnome() && GnomeVFS.isInited) { GtkEventDispatch.dispatch(new Runnable() { @Override public