Compare commits

...

32 Commits

Author SHA1 Message Date
Robinson b2926a4693
updated build deps 2023-11-27 17:14:38 +01:00
Robinson 0598176fe0
version 1.11 2023-11-20 21:02:43 +01:00
Robinson b9f921bf06
Added absolute paths for commands 2023-11-20 21:02:00 +01:00
Robinson cd2d50d5d8
version 1.10 2023-11-19 22:28:46 +01:00
Robinson e0b4eded81
Fixed issues with different encodings on windows wrt getting version information. 2023-11-19 22:28:09 +01:00
Robinson 0c1f718f49
Version 1.9 2023-11-19 21:47:05 +01:00
Robinson 4b90e718ca
Merge pull request #2 from Nohus/remove_plasmaVersion
Removed plasmaVersion incorrectly interpreting version as a double
2023-11-19 21:39:53 +01:00
Robinson da300e87dc
Merge pull request #1 from Nohus/execute_hang
Fixed hang in execute() call
2023-11-19 21:01:29 +01:00
Nohus 111d48db7c Fixed hang in execute() call 2023-11-18 19:29:44 +00:00
Nohus 6a37f3e652 Removed plasmaVersion incorrectly interpreting version as a double 2023-11-18 19:28:12 +00:00
Robinson 509e4c8e0a
Updated build deps 2023-10-09 12:25:40 +02:00
Robinson 614baf966f
updated build deps, kotlin 1.9.0 2023-10-02 16:15:05 +02:00
Robinson e204a8f781
updated gradle 2023-10-02 16:12:51 +02:00
Robinson 244ac97eab
version 1.8 2023-08-19 12:55:07 +02:00
Robinson db41a118a4
Fixed 64bit on M1 macos 2023-08-19 12:54:56 +02:00
Robinson d6544fa6ca
version 1.7 2023-08-16 19:35:09 -05:00
Robinson 6322092ecb
Removed AccessController/Privilege (it will be removed from java) 2023-08-16 19:34:49 -05:00
Robinson b69dcdbba4
Hardcoded project name 2023-08-05 12:26:34 -06:00
Robinson 4b48e12894
Updated build dependencies 2023-06-07 20:02:18 +02:00
Robinson d2aacbdc2e
removed sorting 2023-01-22 20:47:03 +01:00
Robinson 99714cbc2e
updated to utils 3.9 (adds more full java plugins) 2023-01-22 20:22:16 +01:00
Robinson 3275224b1d
Updated build deps
Sort via the number of other dorkbox dependencies
2023-01-22 16:58:23 +01:00
Robinson a70f3d2bb0
Updated version 2023-01-10 01:29:09 +01:00
Robinson 44c26cacf0
Added support for updates + kotlin 2023-01-10 01:28:50 +01:00
Robinson f1f3b83681
Updated version 2023-01-05 22:43:16 +01:00
Robinson 027150f109
Fixed issue getting windows build number (for more detailed windows version info) 2023-01-05 22:43:03 +01:00
Robinson 13d4fb000a
updated version 2023-01-03 22:53:43 +01:00
Robinson d3a1ba30fe
v1.4 2023-01-03 22:23:00 +01:00
Robinson d2f72ecd1d
Fixed issues with split regex 2023-01-03 22:14:12 +01:00
Robinson 278ec16646
v1.3 2023-01-03 21:51:18 +01:00
Robinson 6774c901b2
Fixed initialization order of lazy initialization for DesktopEnv. 2023-01-03 21:50:38 +01:00
Robinson a7afb15412
Updated build dep 2023-01-03 17:19:54 +01:00
7 changed files with 314 additions and 324 deletions

View File

@ -20,7 +20,7 @@ Maven Info
<dependency>
<groupId>com.dorkbox</groupId>
<artifactId>OS</artifactId>
<version>1.2</version>
<version>1.11</version>
</dependency>
</dependencies>
```
@ -30,7 +30,7 @@ Gradle Info
```
dependencies {
...
implementation("com.dorkbox:OS:1.2")
implementation("com.dorkbox:OS:1.11")
}
```

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020 dorkbox, llc
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,8 +14,6 @@
* limitations under the License.
*/
import java.time.Instant
///////////////////////////////
////// PUBLISH TO SONATYPE / MAVEN CENTRAL
////// TESTING : (to local maven repo) <'publish and release' - 'publishToMavenLocal'>
@ -26,19 +24,19 @@ gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS // always show th
plugins {
id("com.dorkbox.GradleUtils") version "3.4.6"
id("com.dorkbox.Licensing") version "2.17"
id("com.dorkbox.VersionUpdate") version "2.5"
id("com.dorkbox.GradlePublish") version "1.13"
id("com.dorkbox.GradleUtils") version "3.18"
id("com.dorkbox.Licensing") version "2.22"
id("com.dorkbox.VersionUpdate") version "2.8"
id("com.dorkbox.GradlePublish") version "1.22"
kotlin("jvm") version "1.6.10"
kotlin("jvm") version "1.9.0"
}
object Extras {
// set for the project
const val description = "Information about the system, Java runtime, OS, Window Manager, and Desktop Environment."
const val group = "com.dorkbox"
const val version = "1.2"
const val version = "1.11"
// set as project.ext
const val name = "OS"
@ -46,8 +44,6 @@ object Extras {
const val vendor = "Dorkbox LLC"
const val vendorUrl = "https://dorkbox.com"
const val url = "https://git.dorkbox.com/dorkbox/OS"
val buildDate = Instant.now().toString()
}
///////////////////////////////
@ -77,7 +73,7 @@ tasks.jar.get().apply {
attributes["Specification-Vendor"] = Extras.vendor
attributes["Implementation-Title"] = "${Extras.group}.${Extras.id}"
attributes["Implementation-Version"] = Extras.buildDate
attributes["Implementation-Version"] = GradleUtils.now()
attributes["Implementation-Vendor"] = Extras.vendor
}
}

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 dorkbox, llc
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,3 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
rootProject.name = "OS"

View File

@ -1,5 +1,5 @@
/*
* Copyright 2022 dorkbox, llc
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,8 +20,6 @@ package dorkbox.os
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
import java.security.AccessController
import java.security.PrivilegedAction
import java.util.*
import java.util.concurrent.*
@ -29,7 +27,7 @@ object OS {
/**
* Gets the version number.
*/
const val version = "1.2"
const val version = "1.11"
init {
// Add this project to the updates system, which verifies this class + UUID + version information
@ -243,19 +241,32 @@ object OS {
}
}
/**
* Clears/removes the property from the system properties.
*/
fun clearProperty(property: String) {
System.clearProperty(property)
}
/**
* @return the previous value of the system property, or 'null' if it did not have one.
*/
fun setProperty(property: String, value: String): String? {
return System.setProperty(property, value)
}
/**
* @return the previous value of the system property, or the [defaultValue] if it did not have one.
*/
fun setProperty(property: String, value: String, defaultValue: String): String {
return System.setProperty(property, value) ?: defaultValue
}
/**
* @return the value of the Java system property with the specified `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 System.getProperty(property, null)
}
/**
@ -263,45 +274,29 @@ object OS {
* 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 System.getProperty(property, defaultValue)
}
/**
* @return the Java system properties in a safe way.
*/
fun getProperties(): Map<String, String> {
@Suppress("UNCHECKED_CAST")
return System.getProperties().toMap() as Map<String, String>
}
/**
* @return the System Environment property in a safe way for a given property, or null if it does not exist.
*/
fun getEnv(): Map<String, String> {
return try {
if (System.getSecurityManager() == null) {
System.getenv()
} else {
AccessController.doPrivileged(PrivilegedAction { System.getenv() })
}
} catch (ignored: Exception) {
mapOf()
}
return System.getenv()
}
/**
* @return the System Environment property in a safe way for a given property, or null if it does not exist.
*/
fun getEnv(property: String): String? {
return try {
if (System.getSecurityManager() == null) {
System.getenv(property)
} else {
AccessController.doPrivileged(PrivilegedAction { System.getenv(property) })
}
} catch (ignored: Exception) {
null
}
return System.getenv(property)
}
/**
@ -309,7 +304,7 @@ object OS {
* specified default value if the property access fails.
*/
fun getEnv(property: String, defaultValue: String): String {
return getEnv(property) ?: defaultValue
return getEnv(property, defaultValue)
}
@ -319,7 +314,7 @@ object OS {
*/
fun getBoolean(property: String, defaultValue: Boolean): Boolean {
var value = getProperty(property) ?: return defaultValue
value = value.trim { it <= ' ' }.lowercase(Locale.getDefault())
value = value.trim().lowercase(Locale.getDefault())
if (value.isEmpty()) {
return defaultValue
}
@ -339,7 +334,7 @@ object OS {
*/
fun getInt(property: String, defaultValue: Int): Int {
var value = getProperty(property) ?: return defaultValue
value = value.trim { it <= ' ' }
value = value.trim()
try {
return value.toInt()
@ -354,7 +349,7 @@ object OS {
*/
fun getLong(property: String, defaultValue: Long): Long {
var value = getProperty(property) ?: return defaultValue
value = value.trim { it <= ' ' }
value = value.trim()
try {
return value.toLong()
@ -369,7 +364,7 @@ object OS {
*/
fun getFloat(property: String, defaultValue: Float): Float {
var value = getProperty(property) ?: return defaultValue
value = value.trim { it <= ' ' }
value = value.trim()
try {
return value.toFloat()
@ -384,7 +379,7 @@ object OS {
*/
fun getDouble(property: String, defaultValue: Double): Double {
var value = getProperty(property) ?: return defaultValue
value = value.trim { it <= ' ' }
value = value.trim()
try {
return value.toDouble()
@ -443,12 +438,13 @@ object OS {
* This is based on an aggregate of the answers provided here: [https://stackoverflow.com/questions/35421699/how-to-invoke-external-command-from-within-kotlin-code]
*/
private fun execute(vararg args: String, timeout: Long = 60): String {
return ProcessBuilder(args.toList())
val process = ProcessBuilder(args.toList())
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
.apply { waitFor(timeout, TimeUnit.SECONDS) }
.inputStream.bufferedReader().readText().trim()
val text = process.inputStream.bufferedReader().readText().trim()
process.waitFor(timeout, TimeUnit.SECONDS)
return text
}
// true if the exit code is 0 (meaning standard exit)
@ -513,18 +509,29 @@ object OS {
*/
val version: IntArray by lazy {
if (!isWindows) {
intArrayOf(0, 0)
intArrayOf(0, 0, 0)
} else {
val version = IntArray(2)
val version = IntArray(3)
try {
val output = getProperty("os.version")
if (output != null) {
val split = output.split("\\.").dropLastWhile { it.isEmpty() }.toTypedArray()
if (split.size <= 2) {
for (i in split.indices) {
version[i] = split[i].toInt()
}
val output = execute("cmd.exe", "/c", "ver")
if (output.isNotEmpty()) {
// OF NOTE: It is possible to have a different encoding of windows, where the word "Version" doesn't exist.
// in this case, we'll just take the next set of numbers available
// Microsoft Windows [Version 10.0.22000.2600]
// Microsoft Windows [??? 10.0.22621.2283] (different encoding)
// slice out the [] because we don't want to include windows product names! (like Windows 2012) in the name!
// I don't specifically have this version to test, however it is easy enough to guard against.
val shortenedOutput = output.substring(output.indexOf("[") + 1, output.indexOf("]"))
val index = shortenedOutput.indexOfFirst { it.isDigit() }
val versionInfoOnly = shortenedOutput.substring(index, shortenedOutput.length)
val split = versionInfoOnly.split(".").toTypedArray()
if (split.size == 4) {
version[0] = split[0].toInt()
version[1] = split[1].toInt()
version[2] = split[2].toInt()
}
}
} catch (ignored: Throwable) {
@ -746,7 +753,7 @@ object OS {
if (!isUbuntu) {
intArrayOf(0, 0)
} else if (distribReleaseInfo != null) {
val split = distribReleaseInfo!!.split("\\.").toTypedArray()
val split = distribReleaseInfo!!.split(".").toTypedArray()
intArrayOf(split[0].toInt(), split[1].toInt())
} else {
intArrayOf(0, 0)
@ -764,7 +771,7 @@ object OS {
if (!isElementaryOS) {
intArrayOf(0, 0)
} else if (distribReleaseInfo != null) {
val split = distribReleaseInfo!!.split("\\.").toTypedArray()
val split = distribReleaseInfo!!.split(".").toTypedArray()
intArrayOf(split[0].toInt(), split[1].toInt())
} else {
intArrayOf(0, 0)
@ -827,7 +834,7 @@ object OS {
if (data == null) {
// reading the file didn't work for whatever reason...
// uname -v
data = execute("uname", "-v").contains("-Microsoft")
data = execute("/usr/bin/uname", "-v").contains("-Microsoft")
}
if (data == true) {
@ -848,7 +855,7 @@ object OS {
// 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" == execute("id", "-u")
isSudoOrRoot = "0" == execute("/usr/bin/id", "-u")
} catch (ignored: Throwable) {
}
}
@ -888,7 +895,7 @@ object OS {
// dpkg-query: package 'libappindicator3' is not installed
val is_dpkg = File("/usr/bin/dpkg").canExecute()
if (is_dpkg) {
return !execute("dpkg", "-L", packageName).contains("is not installed")
return !execute("/usr/bin/dpkg", "-L", packageName).contains("is not installed")
}
// rpm
@ -896,7 +903,7 @@ object OS {
// package libappindicator234 is not installed
val is_rpm = File("/usr/bin/rpm").canExecute()
if (is_rpm) {
return !execute("rpm", "-q", packageName).contains("is not installed")
return !execute("/usr/bin/rpm", "-q", packageName).contains("is not installed")
}
@ -907,7 +914,7 @@ object OS {
try {
// use the exit code to determine if the packages exists on the system
// 0 the package exists, 1 it doesn't
return executeStatus("pacman", "-Qi", packageName)
return executeStatus("/usr/bin/pacman", "-Qi", packageName)
//return start == 0
} catch (ignored: Exception) {
@ -928,6 +935,229 @@ object OS {
X11, WAYLAND, Unknown
}
private fun isValidCommand(partialExpectationInOutput: String, commandOutput: String): Boolean {
return (commandOutput.contains(partialExpectationInOutput) &&
!commandOutput.contains("not installed") &&
!commandOutput.contains("No such file or directory"))
}
// have no idea how this can happen....
val type: EnvType by lazy {
when (getEnv("XDG_SESSION_TYPE")) {
"x11" -> {
EnvType.X11
}
"wayland" -> {
EnvType.WAYLAND
}
else -> {
EnvType.Unknown
}
}
}
val isX11 = type == EnvType.X11
val isWayland = type == EnvType.WAYLAND
val isMATE: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
try {
File("/usr/bin/mate-about").exists()
} catch (ignored: Throwable) {
false
}
}
}
val isGnome: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
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
var contains = execute("/usr/bin/ps", "x").contains("gnome-shell")
if (!contains && isLinux) {
// only try again if we are linux
// ps a | grep gnome-shell
contains = execute("/usr/bin/ps", "a").contains("gnome-shell")
}
contains
} catch (ignored: Throwable) {
false
}
}
}
/**
* @return a string representing the current gnome-shell version, or NULL if it could not be found
*/
val gnomeVersion: String? by lazy {
if (!isLinux && !isUnix) {
null
} else {
try {
// gnome-shell --version
val versionString = execute("/usr/bin/gnome-shell", "--version")
if (versionString.isNotEmpty()) {
// GNOME Shell 3.14.1
val version = versionString.replace("[^\\d.]".toRegex(), "")
if (version.isNotEmpty() && version.indexOf('.') > 0) {
// should just be 3.14.1 or 3.20 or similar
version
} else {
null
}
} else {
null
}
} catch (ignored: Throwable) {
null
}
}
}
// Check if plasmashell is running, if it is -- then we are most likely KDE
val isKDE: Boolean by lazy {
val XDG = getEnv("XDG_CURRENT_DESKTOP")
if (XDG == null) {
// Check if plasmashell is running, if it is -- then we are most likely KDE
plasmaVersionFull != null && !plasmaVersionFull!!.startsWith("0")
} else {
"kde".equals(XDG, ignoreCase = true)
}
}
/**
* 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
*/
val plasmaVersionFull: String? by lazy {
if (!isLinux && !isUnix) {
null
} else {
try {
// plasma-desktop -v
// plasmashell --version
val output = execute("/usr/bin/plasmashell", "--version")
if (output.isNotEmpty()) {
// DEFAULT icon size is 16. KDE is bananas on what they did with tray icon scale
// should be: plasmashell 5.6.5 or something
val s = "plasmashell "
if (isValidCommand(s, output)) {
output.substring(output.indexOf(s) + s.length)
} else {
null
}
} else {
null
}
} catch (ignored: Throwable) {
null
}
}
}
val isXfce: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
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
var contains = execute("/usr/bin/ps", "x").contains("xfce")
if (!contains && isLinux) {
// only try again if we are linux
// ps a | grep gnome-shell
contains = execute("/usr/bin/ps", "a").contains("xfce")
}
contains
} catch (ignored: Throwable) {
false
}
}
}
/**
* 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
*/
val isNautilus: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
try {
// nautilus --version
val output = execute("/usr/bin/nautilus", "--version")
if (output.isNotEmpty()) {
// should be: GNOME nautilus 3.14.3 or something
val s = "GNOME nautilus "
isValidCommand(s, output)
} else {
false
}
} catch (ignored: Throwable) {
false
}
}
}
val isChromeOS: Boolean by lazy {
if (!isLinux) {
false
} else {
try {
// ps aux | grep chromeos
execute("/usr/bin/ps", "aux").contains("chromeos")
} catch (ignored: Throwable) {
false
}
}
}
/**
* @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 "".
*/
fun queryXfce(channel: String, property: String?): String {
if (!isLinux && !isUnix) {
return ""
}
try {
// xfconf-query -c xfce4-panel -l
val commands: MutableList<String> = ArrayList()
commands.add("/usr/bin/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 execute(*commands.toTypedArray())
} catch (ignored: Throwable) {
return ""
}
}
val env: Env by lazy {
// 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
@ -981,251 +1211,10 @@ object OS {
}
}
private fun isValidCommand(partialExpectationInOutput: String, commandOutput: String): Boolean {
return (commandOutput.contains(partialExpectationInOutput) &&
!commandOutput.contains("not installed") &&
!commandOutput.contains("No such file or directory"))
}
// have no idea how this can happen....
val type: EnvType by lazy {
when (getEnv("XDG_SESSION_TYPE")) {
"x11" -> {
EnvType.X11
}
"wayland" -> {
EnvType.WAYLAND
}
else -> {
EnvType.Unknown
}
}
}
val isX11 = type == EnvType.X11
val isWayland = type == EnvType.WAYLAND
val isUnity = isUnity(env)
fun isUnity(env: Env): Boolean {
return env == Env.Unity || env == Env.Unity7
}
val isMATE: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
try {
File("/usr/bin/mate-about").exists()
} catch (ignored: Throwable) {
false
}
}
}
val isGnome: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
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
var contains = execute("ps", "x").contains("gnome-shell")
if (!contains && isLinux) {
// only try again if we are linux
// ps a | grep gnome-shell
contains = execute("ps", "a").contains("gnome-shell")
}
contains
} catch (ignored: Throwable) {
false
}
}
}
/**
* @return a string representing the current gnome-shell version, or NULL if it could not be found
*/
val gnomeVersion: String? by lazy {
if (!isLinux && !isUnix) {
null
} else {
try {
// gnome-shell --version
val versionString = execute("gnome-shell", "--version")
if (versionString.isNotEmpty()) {
// GNOME Shell 3.14.1
val version = versionString.replace("[^\\d.]".toRegex(), "")
if (version.isNotEmpty() && version.indexOf('.') > 0) {
// should just be 3.14.1 or 3.20 or similar
version
} else {
null
}
} else {
null
}
} catch (ignored: Throwable) {
null
}
}
}
// Check if plasmashell is running, if it is -- then we are most likely KDE
val isKDE: Boolean by lazy {
val XDG = getEnv("XDG_CURRENT_DESKTOP")
if (XDG == null) {
// Check if plasmashell is running, if it is -- then we are most likely KDE
val plasmaVersion = plasmaVersion
plasmaVersion > 0
} else {
"kde".equals(XDG, ignoreCase = true)
}
}
/**
* 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
*/
val plasmaVersionFull: String? by lazy {
if (!isLinux && !isUnix) {
null
} else {
try {
// plasma-desktop -v
// plasmashell --version
val output = execute("plasmashell", "--version")
if (output.isNotEmpty()) {
// DEFAULT icon size is 16. KDE is bananas on what they did with tray icon scale
// should be: plasmashell 5.6.5 or something
val s = "plasmashell "
if (isValidCommand(s, output)) {
output.substring(output.indexOf(s) + s.length)
} else {
null
}
} else {
null
}
} catch (ignored: Throwable) {
null
}
}
}
/**
* 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
*/
val plasmaVersion: Double by lazy {
if (plasmaVersionFull == null || plasmaVersionFull!!.startsWith("0")) {
0.0
} else {
// this isn't the BEST way to do this, but it's simple and easy to understand
val split = plasmaVersionFull!!.split("\\.", limit = 3).toTypedArray()
if (split.size > 2) {
(split[0] + "." + split[1]).toDouble()
} else {
split[0].toDouble()
}
}
}
val isXfce: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
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
var contains = execute("ps", "x").contains("xfce")
if (!contains && isLinux) {
// only try again if we are linux
// ps a | grep gnome-shell
contains = execute("ps", "a").contains("xfce")
}
contains
} catch (ignored: Throwable) {
false
}
}
}
/**
* 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
*/
val isNautilus: Boolean by lazy {
if (!isLinux && !isUnix) {
false
} else {
try {
// nautilus --version
val output = execute("nautilus", "--version")
if (output.isNotEmpty()) {
// should be: GNOME nautilus 3.14.3 or something
val s = "GNOME nautilus "
isValidCommand(s, output)
} else {
false
}
} catch (ignored: Throwable) {
false
}
}
}
val isChromeOS: Boolean by lazy {
if (!isLinux) {
false
} else {
try {
// ps aux | grep chromeos
execute("ps", "aux").contains("chromeos")
} catch (ignored: Throwable) {
false
}
}
}
/**
* @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 "".
*/
fun queryXfce(channel: String, property: String?): String {
if (!isLinux && !isUnix) {
return ""
}
try {
// xfconf-query -c xfce4-panel -l
val commands: MutableList<String> = 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 execute(*commands.toTypedArray())
} catch (ignored: Throwable) {
return ""
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2010 dorkbox, llc
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -55,7 +55,7 @@ enum class OSType(name: String, vararg libraryNames: String) {
val is64bit: Boolean
get() {
return this == Linux64 || this == LinuxArm64 || this == Windows64 || this == MacOsX64 || this == AndroidArm8 || this == AndroidX86_64 || this == AndroidMips64 || this == Unix64
return this == Linux64 || this == LinuxArm64 || this == Windows64 || this == MacOsX64 || this == MacOsArm || this == AndroidArm8 || this == AndroidX86_64 || this == AndroidMips64 || this == Unix64
}
val is32bit: Boolean

View File

@ -1,5 +1,9 @@
module dorkbox.os {
exports dorkbox.os;
requires transitive dorkbox.updates;
requires transitive kotlin.stdlib;
requires java.base;
}