-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow specifying Java with --java-bin-dirs or PATH
Most of the action happens in: * The new `SAWScript.JavaTools` module, which exports functionality for locating a Java executable and finding its system properties. * `SAWScript.Options`, which now exposes a new `--java-bin-dirs` flag. (Alternatively, one can use the `PATH`.) The `processEnv` function now performs additional post-processing based on whether `--java-bin-dirs`/`PATH` are set. Fixes #1022, and paves the way to a better user experience for #861.
- Loading branch information
1 parent
c507413
commit d8f6c25
Showing
11 changed files
with
182 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
{- | | ||
Module : SAWScript.JavaTools | ||
Description : Functionality for finding a Java executable and its properties. | ||
License : BSD3 | ||
Maintainer : atomb | ||
Stability : provisional | ||
-} | ||
|
||
module SAWScript.JavaTools | ||
( findJavaIn | ||
, findJavaProperty | ||
, findJavaMajorVersion | ||
) where | ||
|
||
import Control.Monad | ||
import Data.List.Extra (dropPrefix, firstJust, stripInfix) | ||
import Data.Maybe | ||
import System.Directory | ||
import System.Exit | ||
import System.Process | ||
|
||
-- | @'findJavaIn' javaBinDirs@ searches for an executable named @java@ in the | ||
-- directories in @javaBinDirs@. If @javaBinDirs@ is empty, then the @PATH@ is | ||
-- searched. | ||
-- | ||
-- If the search finds at least one executable, then @Just@ the first result is | ||
-- returned. If no executables are found, then @Nothing@ is returned. | ||
findJavaIn :: [FilePath] -> IO (Maybe FilePath) | ||
findJavaIn javaBinDirs | ||
| null javaBinDirs = findExecutable "java" | ||
| otherwise = listToMaybe <$> findExecutablesInDirectories javaBinDirs "java" | ||
|
||
-- | @'findJavaProperty' javaPath prop@ invokes @javaPath@ to dump its system | ||
-- properties (see <https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html>) | ||
-- and attempts to find the value associated with the property named @prop@. | ||
-- If such a value is found, then @Just@ that value is returned. | ||
-- If no property named @prop@ exists, then @Nothing@ is returned. | ||
-- | ||
-- This will throw an exception if @javaPath@'s system properties cannot be | ||
-- determined. | ||
findJavaProperty :: FilePath -> String -> IO (Maybe String) | ||
findJavaProperty javaPath propertyNeedle = do | ||
-- TODO RGS: Is it worth factoring this process-related code out? We do basically the same thing elsewhere in | ||
-- https://github.com/GaloisInc/saw-script/blob/a52e408da234f24dbc9847231efe04ab34c185b9/src/SAWScript/Builtins.hs#L968-L975 | ||
(ec, stdOut, stdErr) <- readProcessWithExitCode javaPath ["-XshowSettings:properties", "-version"] "" | ||
when (ec /= ExitSuccess) $ | ||
fail $ unlines | ||
[ javaPath ++ " returned non-zero exit code: " ++ show ec | ||
, "Standard output:" | ||
, stdOut | ||
, "Standard error:" | ||
, stdErr | ||
] | ||
let propertyHaystacks = lines stdErr | ||
pure $ firstJust getProperty_maybe propertyHaystacks | ||
where | ||
-- Each Java system property, as reported by | ||
-- @java -XshowSettings:properties@, adheres to this template: | ||
-- | ||
-- " <prop> = <value>" | ||
-- | ||
-- Note the leading whitespace. As a result, stripInfix is used to detect | ||
-- "<prop> = " in the middle of the string and obtain the <value> after it. | ||
getProperty_maybe :: String -> Maybe String | ||
getProperty_maybe propertyHaystack = | ||
snd <$> stripInfix (propertyNeedle ++ " = ") propertyHaystack | ||
|
||
-- | @'findJavaMajorVersion' javaPath@ will consult @javaPath@ to find the | ||
-- major version number corresponding to that Java release. | ||
findJavaMajorVersion :: FilePath -> IO Int | ||
findJavaMajorVersion javaPath = do | ||
mbVersionStr <- findJavaProperty javaPath "java.version" | ||
case mbVersionStr of | ||
Nothing -> fail $ "Could not detect the version of Java at " ++ javaPath | ||
Just versionStr -> pure $ read $ takeMajorVersionStr $ dropOldJavaVersionPrefix versionStr | ||
where | ||
-- e.g., if the version number is "11.0.9.1", then just take the "11" part. | ||
takeMajorVersionStr :: String -> String | ||
takeMajorVersionStr = takeWhile (/= '.') | ||
|
||
-- Prior to Java 9, the leading version number was always 1. For example, | ||
-- Java 8 would use 1.8.<...>. We only care about the 8 part, so drop the | ||
-- leading 1. bit. | ||
dropOldJavaVersionPrefix :: String -> String | ||
dropOldJavaVersionPrefix = dropPrefix "1." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters