From 53cf1d371efa4db4284acda00e51e4ea85e359c9 Mon Sep 17 00:00:00 2001 From: Clint Valentine Date: Mon, 7 Oct 2019 22:39:49 -0700 Subject: [PATCH 1/5] Add SystemUtil for querying common system properties --- .../commons/util/SystemUtil.scala | 79 +++++++++++++++++++ .../commons/util/SystemUtilTest.scala | 73 +++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala create mode 100644 src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala diff --git a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala new file mode 100644 index 0000000..7b0c489 --- /dev/null +++ b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala @@ -0,0 +1,79 @@ +/* + * The MIT License + * + * Copyright (c) 2019 Fulcrum Genomics + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.fulcrumgenomics.commons.util +import scala.util.matching.Regex + + +/** System utility defaults and methods. Many methods mock functions in `org.apache.commons:commons-lang3`. */ +object SystemUtil { + + /** The operating system name prefixes for Linux */ + private val LinuxNamePrefixes: Seq[String] = Seq("Linux", "LINUX") + + /** The operating system name prefixes for Mac */ + private val MacNamePrefixes: Seq[String] = Seq("Mac") + + /** The current operating system name. */ + lazy val OsName: Option[String] = getSystemProperty(property = "os.name") + + /** The current operating system architecture */ + lazy val OsArch: Option[String] = getSystemProperty(property = "os.arch") + + /** The current operating system version */ + lazy val OsVersion: Option[String] = getSystemProperty(property = "os.version") + + /** Gets a system property. Returns None if not found or we are not allowed to retrieve the property. */ + def getSystemProperty(property: String): Option[String] = { + try { Option(System.getProperty(property)) } + catch { case _: SecurityException => None } // not allowed to look at this property + } + + /** True if this operating system is Linux, false otherwise. */ + lazy val IsOsLinux: Boolean = LinuxNamePrefixes.exists(prefix => OsName.exists(_.startsWith(prefix))) + + /** True if this operating system is Mac, false otherwise. */ + lazy val IsOsMac: Boolean = MacNamePrefixes.exists(prefix => OsName.exists(_.startsWith(prefix))) + + /** Returns true if the architecture is the given name, false otherwise. */ + def isOsArch(name: String): Boolean = OsArch.contains(name) + + /** Returns true if the architecture matches the given regular expression, false otherwise. */ + def isOsArch(regex: Regex): Boolean = OsArch.exists(regex.matches) + + /** Returns true if the operating system version is the given name, false otherwise. */ + def isOsVersion(name: String): Boolean = OsVersion.contains(name) + + /** Returns true if the operating system version matches the given regular expression, false otherwise. */ + def isOsVersion(regex: Regex): Boolean = OsVersion.exists(regex.matches) + + /** True if the current system could support the Intel Inflater and Deflater, false otherwise. */ + lazy val IntelCompressionLibrarySupported: Boolean = { + if (!SystemUtil.IsOsLinux && !SystemUtil.IsOsMac) false + else if (SystemUtil.isOsArch(name = "ppc64le")) false + else if (SystemUtil.IsOsMac && SystemUtil.isOsVersion("10\\.14\\.".r)) false // FIXME: https://github.com/Intel-HLS/GKL/issues/101 + else true + } +} diff --git a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala new file mode 100644 index 0000000..7d1223c --- /dev/null +++ b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala @@ -0,0 +1,73 @@ +/* + * The MIT License + * + * Copyright (c) 2019 Fulcrum Genomics + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.fulcrumgenomics.commons.util + +import org.scalatest.OptionValues + +import scala.util.matching.Regex + +class SystemUtilTest extends UnitSpec with OptionValues { + + "SystemUtil" should "determine the OS name" in { + (SystemUtil.IsOsLinux, SystemUtil.IsOsMac) match { + case (true, false) => () + case (false, true) => () + case (true, true) => throw new IllegalStateException(s"System cannot both be Linux and Mac: ${SystemUtil.OsName}") + case (false, false) => throw new IllegalStateException(s"Cannot determine the OS: ${SystemUtil.OsName}") + } + } + + private def matches(original: String, exact: String => Boolean, regex: Regex => Boolean): Unit = { + original.length should be > 1 + + val prefix = original.dropRight(1) + val suffix = original.drop(1) + + exact(original) shouldBe true + exact(prefix) shouldBe false + exact(suffix) shouldBe false + + regex(s"$original*".r) shouldBe true + regex(s"$original.*".r) shouldBe true + regex(s"$original.+".r) shouldBe false + + regex(s"$prefix.*".r) shouldBe true + regex(s"$prefix.".r) shouldBe true + regex(prefix.r) shouldBe false + + regex(s".*$suffix".r) shouldBe true + regex(s".$suffix".r) shouldBe true + regex(suffix.r) shouldBe false + } + + it should "match the OS version exactly and with a regex" in { + matches(SystemUtil.OsVersion.value, s => SystemUtil.isOsVersion(s), r => SystemUtil.isOsVersion(r)) + } + + it should "match the OS architecture exactly and with a regex" in { + matches(SystemUtil.OsArch.value, s => SystemUtil.isOsArch(s), r => SystemUtil.isOsArch(r)) + } +} From d03119d5ef8e6fd9f83c8f0077b05da360b94d4e Mon Sep 17 00:00:00 2001 From: Clint Valentine Date: Tue, 8 Oct 2019 10:33:01 -0700 Subject: [PATCH 2/5] Fix cross-Scala compatibility with Regex.matches() --- .../scala/com/fulcrumgenomics/commons/util/SystemUtil.scala | 4 ++-- .../com/fulcrumgenomics/commons/util/SystemUtilTest.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala index 7b0c489..db547ad 100644 --- a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala +++ b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala @@ -61,13 +61,13 @@ object SystemUtil { def isOsArch(name: String): Boolean = OsArch.contains(name) /** Returns true if the architecture matches the given regular expression, false otherwise. */ - def isOsArch(regex: Regex): Boolean = OsArch.exists(regex.matches) + def isOsArch(regex: Regex): Boolean = OsArch.exists(v => regex.findFirstMatchIn(v).isDefined) /** Returns true if the operating system version is the given name, false otherwise. */ def isOsVersion(name: String): Boolean = OsVersion.contains(name) /** Returns true if the operating system version matches the given regular expression, false otherwise. */ - def isOsVersion(regex: Regex): Boolean = OsVersion.exists(regex.matches) + def isOsVersion(regex: Regex): Boolean = OsVersion.exists(v => regex.findFirstMatchIn(v).isDefined) /** True if the current system could support the Intel Inflater and Deflater, false otherwise. */ lazy val IntelCompressionLibrarySupported: Boolean = { diff --git a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala index 7d1223c..5660d2d 100644 --- a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala +++ b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala @@ -56,11 +56,11 @@ class SystemUtilTest extends UnitSpec with OptionValues { regex(s"$prefix.*".r) shouldBe true regex(s"$prefix.".r) shouldBe true - regex(prefix.r) shouldBe false + regex(prefix.r) shouldBe true regex(s".*$suffix".r) shouldBe true regex(s".$suffix".r) shouldBe true - regex(suffix.r) shouldBe false + regex(suffix.r) shouldBe true } it should "match the OS version exactly and with a regex" in { From acba7f2d36cbb8e2993eb8c4b5f79560240e63ef Mon Sep 17 00:00:00 2001 From: Clint Valentine Date: Tue, 8 Oct 2019 22:48:38 -0700 Subject: [PATCH 3/5] Use 2.12 and 2.13 compatible regex anchor matching --- .../scala/com/fulcrumgenomics/commons/util/SystemUtil.scala | 4 ++-- .../com/fulcrumgenomics/commons/util/SystemUtilTest.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala index db547ad..d84249e 100644 --- a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala +++ b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala @@ -61,13 +61,13 @@ object SystemUtil { def isOsArch(name: String): Boolean = OsArch.contains(name) /** Returns true if the architecture matches the given regular expression, false otherwise. */ - def isOsArch(regex: Regex): Boolean = OsArch.exists(v => regex.findFirstMatchIn(v).isDefined) + def isOsArch(regex: Regex): Boolean = OsArch.exists(a => regex.pattern.matcher(a).matches) /** Returns true if the operating system version is the given name, false otherwise. */ def isOsVersion(name: String): Boolean = OsVersion.contains(name) /** Returns true if the operating system version matches the given regular expression, false otherwise. */ - def isOsVersion(regex: Regex): Boolean = OsVersion.exists(v => regex.findFirstMatchIn(v).isDefined) + def isOsVersion(regex: Regex): Boolean = OsVersion.exists(v => regex.pattern.matcher(v).matches) /** True if the current system could support the Intel Inflater and Deflater, false otherwise. */ lazy val IntelCompressionLibrarySupported: Boolean = { diff --git a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala index 5660d2d..7d1223c 100644 --- a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala +++ b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala @@ -56,11 +56,11 @@ class SystemUtilTest extends UnitSpec with OptionValues { regex(s"$prefix.*".r) shouldBe true regex(s"$prefix.".r) shouldBe true - regex(prefix.r) shouldBe true + regex(prefix.r) shouldBe false regex(s".*$suffix".r) shouldBe true regex(s".$suffix".r) shouldBe true - regex(suffix.r) shouldBe true + regex(suffix.r) shouldBe false } it should "match the OS version exactly and with a regex" in { From 6c2acbcac0c7b67a831133f36256da6813814a6a Mon Sep 17 00:00:00 2001 From: Clint Valentine Date: Tue, 8 Oct 2019 23:18:22 -0700 Subject: [PATCH 4/5] Fix regex to respect an anchored match --- .../scala/com/fulcrumgenomics/commons/util/SystemUtil.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala index d84249e..f2d437b 100644 --- a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala +++ b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala @@ -73,7 +73,7 @@ object SystemUtil { lazy val IntelCompressionLibrarySupported: Boolean = { if (!SystemUtil.IsOsLinux && !SystemUtil.IsOsMac) false else if (SystemUtil.isOsArch(name = "ppc64le")) false - else if (SystemUtil.IsOsMac && SystemUtil.isOsVersion("10\\.14\\.".r)) false // FIXME: https://github.com/Intel-HLS/GKL/issues/101 + else if (SystemUtil.IsOsMac && SystemUtil.isOsVersion("10\\.14\\..+".r)) false // FIXME: https://github.com/Intel-HLS/GKL/issues/101 else true } } From 9c0ad0b90057412d5b18c5886bbf19330d5acf79 Mon Sep 17 00:00:00 2001 From: Clint Valentine Date: Mon, 13 Jan 2020 09:25:47 -0800 Subject: [PATCH 5/5] Fallback to implementations in scala.util.Properties --- .../commons/util/SystemUtil.scala | 38 ++++++------------- .../commons/util/SystemUtilTest.scala | 13 +------ 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala index f2d437b..d0211aa 100644 --- a/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala +++ b/src/main/scala/com/fulcrumgenomics/commons/util/SystemUtil.scala @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2019 Fulcrum Genomics + * Copyright (c) 2020 Fulcrum Genomics * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,39 +24,25 @@ */ package com.fulcrumgenomics.commons.util -import scala.util.matching.Regex +import scala.util.Properties.{isLinux, isMac, propOrNone} +import scala.util.matching.Regex /** System utility defaults and methods. Many methods mock functions in `org.apache.commons:commons-lang3`. */ object SystemUtil { - /** The operating system name prefixes for Linux */ - private val LinuxNamePrefixes: Seq[String] = Seq("Linux", "LINUX") - - /** The operating system name prefixes for Mac */ - private val MacNamePrefixes: Seq[String] = Seq("Mac") - - /** The current operating system name. */ - lazy val OsName: Option[String] = getSystemProperty(property = "os.name") - /** The current operating system architecture */ - lazy val OsArch: Option[String] = getSystemProperty(property = "os.arch") + lazy val OsArch: Option[String] = safePropOrNone(property = "os.arch") /** The current operating system version */ - lazy val OsVersion: Option[String] = getSystemProperty(property = "os.version") + lazy val OsVersion: Option[String] = safePropOrNone(property = "os.version") - /** Gets a system property. Returns None if not found or we are not allowed to retrieve the property. */ - def getSystemProperty(property: String): Option[String] = { - try { Option(System.getProperty(property)) } + /** Gets a system property. Returns None if not found, or if a security manager does not allow us to retrieve the property. */ + def safePropOrNone(property: String): Option[String] = { + try { propOrNone(property) } catch { case _: SecurityException => None } // not allowed to look at this property } - /** True if this operating system is Linux, false otherwise. */ - lazy val IsOsLinux: Boolean = LinuxNamePrefixes.exists(prefix => OsName.exists(_.startsWith(prefix))) - - /** True if this operating system is Mac, false otherwise. */ - lazy val IsOsMac: Boolean = MacNamePrefixes.exists(prefix => OsName.exists(_.startsWith(prefix))) - /** Returns true if the architecture is the given name, false otherwise. */ def isOsArch(name: String): Boolean = OsArch.contains(name) @@ -69,11 +55,11 @@ object SystemUtil { /** Returns true if the operating system version matches the given regular expression, false otherwise. */ def isOsVersion(regex: Regex): Boolean = OsVersion.exists(v => regex.pattern.matcher(v).matches) - /** True if the current system could support the Intel Inflater and Deflater, false otherwise. */ + /** True if the current system might support the Intel Inflater and Deflater, false otherwise. */ lazy val IntelCompressionLibrarySupported: Boolean = { - if (!SystemUtil.IsOsLinux && !SystemUtil.IsOsMac) false - else if (SystemUtil.isOsArch(name = "ppc64le")) false - else if (SystemUtil.IsOsMac && SystemUtil.isOsVersion("10\\.14\\..+".r)) false // FIXME: https://github.com/Intel-HLS/GKL/issues/101 + if (!isLinux && !isMac) false + else if (isOsArch(name = "ppc64le")) false + else if (isMac && isOsVersion("10\\.14\\..+".r)) false // FIXME: https://github.com/Intel-HLS/GKL/issues/101 else true } } diff --git a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala index 7d1223c..c2faecc 100644 --- a/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala +++ b/src/test/scala/com/fulcrumgenomics/commons/util/SystemUtilTest.scala @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2019 Fulcrum Genomics + * Copyright (c) 2020 Fulcrum Genomics * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,15 +31,6 @@ import scala.util.matching.Regex class SystemUtilTest extends UnitSpec with OptionValues { - "SystemUtil" should "determine the OS name" in { - (SystemUtil.IsOsLinux, SystemUtil.IsOsMac) match { - case (true, false) => () - case (false, true) => () - case (true, true) => throw new IllegalStateException(s"System cannot both be Linux and Mac: ${SystemUtil.OsName}") - case (false, false) => throw new IllegalStateException(s"Cannot determine the OS: ${SystemUtil.OsName}") - } - } - private def matches(original: String, exact: String => Boolean, regex: Regex => Boolean): Unit = { original.length should be > 1 @@ -63,7 +54,7 @@ class SystemUtilTest extends UnitSpec with OptionValues { regex(suffix.r) shouldBe false } - it should "match the OS version exactly and with a regex" in { + "SystemUtil" should "match the OS version exactly and with a regex" in { matches(SystemUtil.OsVersion.value, s => SystemUtil.isOsVersion(s), r => SystemUtil.isOsVersion(r)) }