Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read java props from env vars #2356

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,11 @@ trait Cli extends SbtModule with ProtoBuildModule with CliLaunchers
def runClasspath = T {
super.runClasspath() ++ Seq(localRepoJar())
}

// Required by the reflection usage in modules/cli/src/test/scala/cli/tests/SetupScalaCLITests.scala
override def forkArgs: T[Seq[String]] = T {
super.forkArgs() ++ Seq("--add-opens=java.base/java.util=ALL-UNNAMED")
MaciejG604 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

Expand Down
16 changes: 14 additions & 2 deletions modules/cli/src/main/scala/scala/cli/ScalaCli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ object ScalaCli {
val jvmoptsLines = jvmoptsContent.linesIterator.toSeq
val (javaOpts, otherOpts) = jvmoptsLines.partition(_.startsWith("-D"))
javaOpts.foreach { opt =>
opt.stripPrefix("-D").split("=", 2).match {
opt.stripPrefix("-D").split("=", 2) match {
case Array(key, value) => System.setProperty(key, value)
case _ => System.err.println(s"Warning: Invalid java property: $opt")
}
Expand All @@ -192,11 +192,23 @@ object ScalaCli {
properties <- configDb.get(Keys.javaProperties).getOrElse(Nil)
}
properties.foreach { opt =>
opt.stripPrefix("-D").split("=", 2).match {
opt.stripPrefix("-D").split("=", 2) match {
case Array(key, value) => System.setProperty(key, value)
case _ => System.err.println(s"Warning: Invalid java property in config: $opt")
}
}

// load java properties from JAVA_OPTS and JDK_JAVA_OPTIONS environment variables
val javaOpts = sys.env.get("JAVA_OPTS").toSeq ++ sys.env.get("JDK_JAVA_OPTIONS").toSeq

javaOpts
.flatMap(_.split("\\s+"))
.foreach { opt =>
opt.stripPrefix("-D").split("=", 2) match {
case Array(key, value) => System.setProperty(key, value)
case _ => // Ignore if not a Java property
}
}
}

private def main0(args: Array[String]): Unit = {
Expand Down
50 changes: 45 additions & 5 deletions modules/cli/src/test/scala/cli/tests/SetupScalaCLITests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package cli.tests

import com.eed3si9n.expecty.Expecty.expect

import java.util.Properties
import java.util.{Collections, Properties}

import scala.build.internal.Constants
import scala.build.tests.TestInputs
import scala.cli.ScalaCli
import scala.util.Properties
import scala.jdk.CollectionConverters.{MapHasAsJava, MapHasAsScala}

class SetupScalaCLITests extends munit.FunSuite {

Expand All @@ -16,9 +16,9 @@ class SetupScalaCLITests extends munit.FunSuite {
val value = "true"
val inputs = TestInputs(
os.rel / Constants.jvmPropertiesFileName ->
s"""-Xmx2048m
|-Xms128m
|-Xss8m
s"""-Xignored_1
|-Xignored_2
|-Xignored_3
|-D$key=$value
|""".stripMargin
)
Expand All @@ -28,8 +28,48 @@ class SetupScalaCLITests extends munit.FunSuite {
ScalaCli.loadJavaProperties(root)
expect(sys.props.get(key).contains(value))

expect(sys.props.get("ignored_1").isEmpty)
expect(sys.props.get("ignored_2").isEmpty)
expect(sys.props.get("ignored_3").isEmpty)
// restore original props
System.setProperties(currentProps)
)
}

test(s"should read java properties from JAVA_OPTS and JDK_JAVA_OPTIONS") {
// Adapted from https://stackoverflow.com/a/496849
def setEnvVars(newEnv: Map[String, String]): Unit = {
val classes = classOf[Collections].getDeclaredClasses
val env = System.getenv()
for (cl <- classes)
if (cl.getName.equals("java.util.Collections$UnmodifiableMap")) {
val field = cl.getDeclaredField("m")
field.setAccessible(true)
val obj = field.get(env)
val map = obj.asInstanceOf[java.util.Map[String, String]]
map.clear()
map.putAll(newEnv.asJava)
}
}

val javaOptsValues = " -Xignored_1 -Dhttp.proxy=4.4.4.4 -Xignored_2"
val jdkJavaOptionsValues = " -Xignored_3 -Dscala-cli=true -Xignored_4"

TestInputs().fromRoot(root =>
//
val currentEnv = System.getenv().asScala.toMap
// modify environment variable of this process
setEnvVars(Map("JAVA_OPTS" -> javaOptsValues, "JDK_JAVA_OPTIONS" -> jdkJavaOptionsValues))
ScalaCli.loadJavaProperties(root)
expect(sys.props.get("http.proxy").contains("4.4.4.4"))
expect(sys.props.get("scala-cli").contains("true"))

expect(sys.props.get("ignored_1").isEmpty)
expect(sys.props.get("ignored_2").isEmpty)
expect(sys.props.get("ignored_3").isEmpty)
expect(sys.props.get("ignored_4").isEmpty)
// reset the env
setEnvVars(currentEnv)
)
}
}