diff --git a/Cargo.lock b/Cargo.lock index 97805c6..abf2154 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,11 +43,12 @@ dependencies = [ [[package]] name = "buildj" -version = "0.1.9" +version = "0.1.10" dependencies = [ "dirs", "json", "lazy_static", + "plist", "reqwest", "rust-crypto", "rust_util", @@ -79,6 +80,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -443,6 +454,15 @@ version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + [[package]] name = "log" version = "0.4.14" @@ -520,6 +540,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.0" @@ -633,6 +672,20 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +[[package]] +name = "plist" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679104537029ed2287c216bfb942bbf723f48ee98f0aef15611634173a74ef21" +dependencies = [ + "base64", + "chrono", + "indexmap", + "line-wrap", + "serde", + "xml-rs", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -878,6 +931,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "schannel" version = "0.1.19" @@ -1287,3 +1346,9 @@ checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ "winapi", ] + +[[package]] +name = "xml-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" diff --git a/Cargo.toml b/Cargo.toml index ac97e9a..2d9cf8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "buildj" -version = "0.1.9" +version = "0.1.10" authors = ["Hatter Jiang "] edition = "2018" homepage = "https://buildj.ruststack.org/" @@ -16,3 +16,4 @@ dirs = "3.0" rust-crypto = "0.2" lazy_static = "1.4" rust_util = "0.6" +plist = "1.1" diff --git a/src/jdk.rs b/src/jdk.rs index cdd25a1..4f435fc 100644 --- a/src/jdk.rs +++ b/src/jdk.rs @@ -1,6 +1,8 @@ use std::{collections::HashMap, env, fs, str, path::Path, process::Command}; use rust_util::util_os; +use rust_util::util_env; use crate::{local_util, tool, misc::VERBOSE}; +use plist::Value; const PATH: &str = "PATH"; const JAVA_HOME: &str = "JAVA_HOME"; @@ -19,7 +21,8 @@ lazy_static! { pub fn get_java_home(version: &str) -> Option { match get_macos_java_home(version) { - Some(j) => Some(j), None => match get_local_java_home(version) { + Some(j) => Some(j), + None => match get_local_java_home(version) { Some(j) => Some(j), None => iff!(get_cloud_java(version), get_local_java_home(version), None), }, @@ -27,7 +30,7 @@ pub fn get_java_home(version: &str) -> Option { } pub fn get_cloud_java(version: &str) -> bool { - if ! util_os::is_macos_or_linux() { + if !util_os::is_macos_or_linux() { return false; } let cloud_java_names = match &*BUILDJ_JAVA_NAME { @@ -41,7 +44,8 @@ pub fn get_cloud_java(version: &str) -> bool { Some(buildj_java_name) => vec![buildj_java_name.as_str()], }; let local_java_home_base_dir = match local_util::get_user_home_dir(LOCAL_JAVA_HOME_BASE_DIR) { - Ok(o) => o, Err(_) => return false, + Ok(o) => o, + Err(_) => return false, }; for cloud_java_name in cloud_java_names { if tool::get_and_extract_tool_package(&local_java_home_base_dir, false, cloud_java_name, version, false).is_ok() { @@ -53,19 +57,39 @@ pub fn get_cloud_java(version: &str) -> bool { } pub fn get_macos_java_home(version: &str) -> Option { - if ! util_os::is_macos() { + if !util_os::is_macos() || util_env::is_env_on("SKIP_CHECK_JAVA_HOME") { return None; } - let output = Command::new(MACOS_LIBEXEC_JAVAHOME).arg("-version").arg(version).output().ok()?; - let output_in_utf8 = str::from_utf8(&output.stderr).ok()?; - if *VERBOSE { - debugging!("java_home outputs: {}", output_in_utf8); - } - if output_in_utf8.contains("Unable to find any JVMs") { - None - } else { - Some(str::from_utf8(&output.stdout).ok()?.trim().to_string()) + let java_home_x = Command::new(MACOS_LIBEXEC_JAVAHOME).arg("-x").output().ok()?; + let java_home_plist_value = match Value::from_reader_xml(&*java_home_x.stdout) { + Err(e) => { + debugging!("Parse java_home outputs failed: {}", e); + return None; + } + Ok(val) => val, + }; + let java_home_plist_value_array = match java_home_plist_value.as_array() { + None => { + debugging!("Covert java_home plist output to array failed: {:?}", java_home_plist_value); + return None; + } + Some(val) => val, + }; + for java_home_plist_item in java_home_plist_value_array { + debugging!("Checking: {:?}", java_home_plist_item); + if let Some(jvm_item) = java_home_plist_item.as_dictionary() { + let jvm_version_value = jvm_item.get("JVMVersion"); + let jvm_home_path_value = jvm_item.get("JVMHomePath"); + if let (Some(Value::String(jvm_version)), Some(Value::String(jvm_path))) = (jvm_version_value, jvm_home_path_value) { + debugging!("Check version: {} vs {}", jvm_version, version); + if jvm_version.starts_with(version) { + debugging!("Check version success: {} -> {}", jvm_version, jvm_path); + return Some(jvm_path.into()); + } + } + } } + None } pub fn get_local_java_home(version: &str) -> Option { @@ -73,7 +97,7 @@ pub fn get_local_java_home(version: &str) -> Option { let paths = fs::read_dir(Path::new(&local_java_home_base_dir)).ok()?; for path in paths { if let Ok(dir_entry) = path { - if let Some(p)= dir_entry.path().to_str() { + if let Some(p) = dir_entry.path().to_str() { if *VERBOSE { debugging!("Try match path: {}", p); } @@ -82,7 +106,7 @@ pub fn get_local_java_home(version: &str) -> Option { path_name = &path_name[..path_name.len() - 1] } if let Some(i) = path_name.rfind('/') { - path_name = &path_name[i+1..]; + path_name = &path_name[i + 1..]; } let matched_path_opt = if (path_name.starts_with("jdk-") && (&path_name[4..]).starts_with(version)) || (path_name.starts_with("jdk") && (&path_name[3..]).starts_with(version)) { @@ -98,7 +122,7 @@ pub fn get_local_java_home(version: &str) -> Option { Some(format!("{}/{}", matched_path, "Contents/Home")) } else { Some(matched_path.to_string()) - } + }; } } }