Mercurial > hg > release > icedtea-web-1.8
changeset 1528:e44b9395ae5b
Rust properties parser generalized to be reusable
* rust-launcher/src/dirs_paths_helper.rs: new file, including get_xdg_config_dir, deployment.properties and similar originally from jvm_from_properties.rs
* rust-launcher/src/main.rs: adapted to re-factored state
* rust-launcher/src/os_access.rs: added and for Linux implemented get_system_config_javadir, get_user_config_dir
* rust-launcher/src/property_from_file.rs: renamed from jvm_from_properties_file and generalized
* rust-launcher/src/property_from_files_resolver.rs: renamed from jvm_from_files_resolver and generalized
* rust-launcher/src/utils.rs: adapted to renamed JRE_PROPERTY_NAME from PROPERTY_NAME
author | Jiri Vanek <jvanek@redhat.com> |
---|---|
date | Fri, 30 Nov 2018 19:04:42 +0100 |
parents | 612ff5eded4f |
children | 9bac379fb97e |
files | ChangeLog rust-launcher/src/dirs_paths_helper.rs rust-launcher/src/jvm_from_properties.rs rust-launcher/src/jvm_from_properties_resolver.rs rust-launcher/src/main.rs rust-launcher/src/os_access.rs rust-launcher/src/property_from_file.rs rust-launcher/src/property_from_files_resolver.rs rust-launcher/src/utils.rs |
diffstat | 9 files changed, 581 insertions(+), 536 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Nov 28 12:35:38 2018 +0100 +++ b/ChangeLog Fri Nov 30 19:04:42 2018 +0100 @@ -1,3 +1,14 @@ +2018-11-30 Jiri Vanek <jvanek@redhat.com> + + Rust properties parser generalized to be reusable + * rust-launcher/src/dirs_paths_helper.rs: new file, including get_xdg_config_dir, deployment.properties and similar + originally from jvm_from_properties.rs + * rust-launcher/src/main.rs: adapted to re-factored state + * rust-launcher/src/os_access.rs: added and for Linux implemented get_system_config_javadir, get_user_config_dir + * rust-launcher/src/property_from_file.rs: renamed from jvm_from_properties_file and generalized + * rust-launcher/src/property_from_files_resolver.rs: renamed from jvm_from_files_resolver and generalized + * rust-launcher/src/utils.rs: adapted to renamed JRE_PROPERTY_NAME from PROPERTY_NAME + 2018-11-28 Jiri Vanek <jvanek@redhat.com> deployment.config now support generic url instead just file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust-launcher/src/dirs_paths_helper.rs Fri Nov 30 19:04:42 2018 +0100 @@ -0,0 +1,95 @@ +use os_access; + +use std; +use std::env; + +pub static ICEDTEA_WEB: &'static str = "icedtea-web"; +pub static DEPLOYMENT_PROPERTIES: &'static str = "deployment.properties"; + +pub fn get_home() -> Option<std::path::PathBuf> { + match env::home_dir() { + Some(p) => Some(p), + None => None + } +} + +pub fn get_xdg_config_dir() -> Option<std::path::PathBuf> { + match env::var("XDG_CONFIG_HOME") { + Ok(war) => { + Some(std::path::PathBuf::from(war)) + } + Err(_) => { + match get_home() { + Some(mut p) => { + p.push(".config"); + Some(p) + } + None => None + } + } + } +} + +pub fn append_deployment_file(dir: Option<std::path::PathBuf>) -> Option<std::path::PathBuf> { + match dir { + Some(mut p) => { + p.push(DEPLOYMENT_PROPERTIES); + Some(p) + } + None => None + } +} + + +pub fn get_itw_config_file(os: &os_access::Os) -> Option<std::path::PathBuf> { + append_deployment_file(os.get_user_config_dir()) +} + +pub fn get_itw_legacy_config_file(os: &os_access::Os) -> Option<std::path::PathBuf> { + append_deployment_file(os.get_legacy_user_config_dir()) +} + + +pub fn get_itw_legacy_global_config_file(os: &os_access::Os) -> Option<std::path::PathBuf> { + append_deployment_file(os.get_legacy_system_config_javadir()) +} + +pub fn get_itw_global_config_file(os: &os_access::Os) -> Option<std::path::PathBuf> { + append_deployment_file(os.get_system_config_javadir()) +} + + +/*tests*/ +#[cfg(test)] +mod tests { + use os_access; + + #[test] + fn check_config_files_paths() { + let os = os_access::Linux::new(false); + let p3 = super::get_itw_config_file(&os); + let p4 = super::get_itw_legacy_config_file(&os); + let p5 = super::get_itw_legacy_global_config_file(&os); + let p6 = super::get_itw_global_config_file(&os); + assert_ne!(None, p3); + assert_ne!(None, p4); + assert_ne!(None, p5); + assert_ne!(None, p6); + println!("{}", p3.clone().expect("unwrap failed").display()); + println!("{}", p4.clone().expect("unwrap failed").display()); + println!("{}", p5.clone().expect("unwrap failed").display()); + println!("{}", p6.clone().expect("unwrap failed").display()); + assert_eq!(true, p3.clone().expect("unwrap failed").display().to_string().contains("icedtea-web")); + assert_eq!(true, p3.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); + assert_eq!(true, p4.clone().expect("unwrap failed").display().to_string().contains(".icedtea")); + assert_eq!(true, p4.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("etc")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".java")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".deploy")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("etc")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".java")); + assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("deployment")); + assert_eq!(true, p6.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); + } +}
--- a/rust-launcher/src/jvm_from_properties.rs Wed Nov 28 12:35:38 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,305 +0,0 @@ -use property; - -use std; -use std::env; -use std::string::String; -use std::fs::File; - -static ICEDTEA_WEB: &'static str = "icedtea-web"; -pub static DEPLOYMENT_PROPERTIES: &'static str = "deployment.properties"; -pub static PROPERTY_NAME: &'static str = "deployment.jre.dir"; - -fn is_file(path: &std::path::PathBuf) -> bool { - let mdr = path.metadata(); - match mdr { - Ok(md) => md.is_file(), - Err(_e) => false - } -} - -fn get_home() -> Option<std::path::PathBuf> { - match env::home_dir() { - Some(p) => Some(p), - None => None - } -} - -fn get_config_dir() -> Option<std::path::PathBuf> { - match env::var("XDG_CONFIG_HOME") { - Ok(war) => { - Some(std::path::PathBuf::from(war)) - } - Err(_e) => { - match get_home() { - Some(mut p) => { - p.push(".config"); - Some(p) - } - None => None - } - } - } -} - -pub fn get_itw_config_dir() -> Option<std::path::PathBuf> { - match get_config_dir() { - Some(mut p) => { - p.push(ICEDTEA_WEB); - Some(p) - } - None => None - } -} - - -pub fn get_itw_legacy_config_dir() -> Option<std::path::PathBuf> { - match get_home() { - Some(mut p) => { - p.push(".icedtea"); - Some(p) - } - None => None - } -} - - -pub fn get_itw_config_file() -> Option<std::path::PathBuf> { - match get_itw_config_dir() { - Some(mut p) => { - p.push(DEPLOYMENT_PROPERTIES); - Some(p) - } - None => None - } -} - -pub fn get_itw_legacy_config_file() -> Option<std::path::PathBuf> { - match get_itw_legacy_config_dir() { - Some(mut p) => { - p.push(DEPLOYMENT_PROPERTIES); - Some(p) - } - None => None - } -} - - -pub fn get_itw_legacy_global_config_file() -> Option<std::path::PathBuf> { - let mut path = std::path::PathBuf::from("/etc/.java/.deploy"); - path.push(DEPLOYMENT_PROPERTIES); - Some(path) -} - -pub fn get_itw_global_config_file() -> Option<std::path::PathBuf> { - let mut path = std::path::PathBuf::from("/etc/.java/deployment"); - path.push(DEPLOYMENT_PROPERTIES); - Some(path) -} - - -pub fn check_file_for_property_jredir(file: File) -> Option<String> { - check_file_for_property(file, PROPERTY_NAME) -} - -fn check_file_for_property(file: File, key: &str) -> Option<String> { - let p = property::Property::load(file, key); - match p { - None => { None } - Some(property) => { - Some(property.value) - } - } -} - - -pub fn get_jre_from_file(file: Option<std::path::PathBuf>) -> Option<String> { - match file { - None => None, - Some(path) => { - get_jre_from_file_direct(path) - } - } -} - -fn get_jre_from_file_direct(path: std::path::PathBuf) -> Option<String> { - if !path.exists() { - None - } else if !is_file(&path) { - return None; - } else { - let fileresult = File::open(path); - match fileresult { - Err(_fe) => None, - Ok(file) => { - let result = check_file_for_property_jredir(file); - result - } - } - } -} - -pub fn verify_jdk_string(file: &String) -> bool { - verify_jdk_path(&std::path::PathBuf::from(file)) -} - -fn verify_jdk_path(ffile: &std::path::PathBuf) -> bool { - let mut file = ffile.clone(); - file.push("bin"); - file.push("java"); - if !file.exists() { - false - } else if !is_file(&file) { - false - } else { - true - } -} - -/*tests*/ -#[cfg(test)] -mod tests { - use std; - use std::fs::File; - use utils::tests_utils as tu; - - - #[test] - fn is_not_file_() { - let r = super::is_file(&std::path::PathBuf::from("/definitely/not/existing/file")); - assert_eq!(false, r); - } - - #[test] - fn is_file_() { - let dir = tu::create_tmp_file(); - let r = super::is_file(&dir); - tu::debuggable_remove_file(&dir); - assert_eq!(true, r); - } - - #[test] - fn check_file_for_property_jredir_not_found() { - let path = tu::create_tmp_file(); - let f = File::open(&path); - let prop = super::check_file_for_property_jredir(f.expect("file was not opened")); - tu::debuggable_remove_file(&path); - assert_eq!(None, prop); - } - - #[test] - fn check_file_for_property_jredir() { - let path = tu::create_tmp_propfile_with_content(); - let f = File::open(&path); - let prop = super::check_file_for_property_jredir(f.expect("file was not opened")); - tu::debuggable_remove_file(&path); - assert_eq!("/some/jre", prop.expect("property was supposed to be loaded")); - } - - - #[test] - fn check_file_for_property_not_found() { - let path = tu::create_tmp_propfile_with_content(); - let f = File::open(&path); - let k = "not_existing_key"; - let prop = super::check_file_for_property(f.expect("file was not opened"), k); - tu::debuggable_remove_file(&path); - assert_eq!(None, prop); - } - - #[test] - fn check_file_for_property_item_exists() { - let path = tu::create_tmp_propfile_with_content(); - let f = File::open(&path); - let k = "key2"; - let prop = super::check_file_for_property(f.expect("file was not opened"), k); - tu::debuggable_remove_file(&path); - assert_eq!("val2", prop.expect("property was supposed to be loaded")); - } - - #[test] - fn get_jre_from_file_exists() { - let path = tu::create_tmp_propfile_with_content(); - let prop = super::get_jre_from_file(Some(path.clone())); - tu::debuggable_remove_file(&path); - assert_eq!("/some/jre", prop.expect("property was supposed to be loaded")); - } - - #[test] - fn get_jre_from_file_not_found() { - let path = tu::create_tmp_file(); - let prop = super::get_jre_from_file(Some(path.clone())); - tu::debuggable_remove_file(&path); - assert_eq!(None, prop); - } - - - #[test] - fn get_jre_from_file_notexists() { - let path = tu::create_tmp_file(); - tu::debuggable_remove_file(&path); - let prop = super::get_jre_from_file(Some(path)); - assert_eq!(None, prop); - } - - #[test] - fn get_jre_from_file_none() { - let prop = super::get_jre_from_file(None); - assert_eq!(None, prop); - } - - #[test] - fn verify_jdk_string_verify_jdk_path_jdk_ok() { - let master_dir = tu::fake_jre(true); - let vs = super::verify_jdk_string(&master_dir.display().to_string()); - let vp = super::verify_jdk_path(&master_dir); - tu::debuggable_remove_dir(&master_dir); - assert_eq!(true, vs); - assert_eq!(true, vp); - } - - #[test] - fn verify_jdk_string_verify_jdk_path_jdk_bad() { - let master_dir = tu::fake_jre(false); - let vs = super::verify_jdk_string(&master_dir.display().to_string()); - let vp = super::verify_jdk_path(&master_dir); - tu::debuggable_remove_dir(&master_dir); - assert_eq!(false, vs); - assert_eq!(false, vp); - } - - #[test] - fn check_config_files_paths() { - let p1 = super::get_itw_config_dir(); - let p2 = super::get_itw_legacy_config_dir(); - let p3 = super::get_itw_config_file(); - let p4 = super::get_itw_legacy_config_file(); - let p5 = super::get_itw_legacy_global_config_file(); - let p6 = super::get_itw_global_config_file(); - assert_ne!(None, p1); - assert_ne!(None, p2); - assert_ne!(None, p3); - assert_ne!(None, p4); - assert_ne!(None, p5); - assert_ne!(None, p6); - println!("{}", p1.clone().expect("unwrap failed").display()); - println!("{}", p2.clone().expect("unwrap failed").display()); - println!("{}", p3.clone().expect("unwrap failed").display()); - println!("{}", p4.clone().expect("unwrap failed").display()); - println!("{}", p5.clone().expect("unwrap failed").display()); - println!("{}", p6.clone().expect("unwrap failed").display()); - assert_eq!(true, p1.clone().expect("unwrap failed").display().to_string().contains("icedtea-web")); - assert_eq!(true, p2.clone().expect("unwrap failed").display().to_string().contains(".icedtea")); - assert_eq!(true, p3.clone().expect("unwrap failed").display().to_string().contains("icedtea-web")); - assert_eq!(true, p3.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); - assert_eq!(true, p4.clone().expect("unwrap failed").display().to_string().contains(".icedtea")); - assert_eq!(true, p4.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("etc")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".java")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".deploy")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("etc")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains(".java")); - assert_eq!(true, p5.clone().expect("unwrap failed").display().to_string().contains("deployment")); - assert_eq!(true, p6.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties")); - } -}
--- a/rust-launcher/src/jvm_from_properties_resolver.rs Wed Nov 28 12:35:38 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -use hardcoded_paths; -use jvm_from_properties; -use os_access; - -use std; -use std::string::String; -use std::fmt::Write; - -pub fn try_jdk_from_properties(logger: &os_access::Os) -> Option<String> { - let array: [Option<std::path::PathBuf>; 4] = [ - jvm_from_properties::get_itw_config_file(), - jvm_from_properties::get_itw_legacy_config_file(), - jvm_from_properties::get_itw_legacy_global_config_file(), - jvm_from_properties::get_itw_global_config_file() - ]; - try_jdk_from_properties_files(logger, &array) -} - -fn try_jdk_from_properties_files(logger: &os_access::Os, array: &[Option<std::path::PathBuf>]) -> Option<String> { - for jdk in array { - let mut info1 = String::new(); - write!(&mut info1, "{} ", "itw-rust-debug: checking jre in:").expect("unwrap failed"); - write!(&mut info1, "{}", jdk.clone().unwrap_or(std::path::PathBuf::from("None")).display()).expect("unwrap failed"); - logger.log(&info1); - match jvm_from_properties::get_jre_from_file(jdk.clone()) { - Some(path) => { - let mut info2 = String::new(); - write!(&mut info2, "{} ", "itw-rust-debug: located").expect("unwrap failed"); - write!(&mut info2, "{}", path).expect("unwrap failed"); - write!(&mut info2, " in file {}", jdk.clone().expect("file should be already verified").display()).expect("unwrap failed"); - logger.log(&info2); - if jvm_from_properties::verify_jdk_string(&path) { - return Some(path); - } else { - //the only output out of verbose mode - let mut res = String::new(); - write!(&mut res, "{}", "Your custom JRE ").expect("unwrap failed"); - write!(&mut res, "{}", path).expect("unwrap failed"); - write!(&mut res, "{}", " read from ").expect("unwrap failed"); - write!(&mut res, "{}", jdk.clone().expect("jre path should be loaded").display()).expect("unwrap failed"); - write!(&mut res, "{}", " under key ").expect("unwrap failed"); - write!(&mut res, "{}", jvm_from_properties::PROPERTY_NAME).expect("unwrap failed"); - write!(&mut res, "{}", " is not valid. Trying other config files, then using default (").expect("unwrap failed"); - write!(&mut res, "{}", hardcoded_paths::get_java()).expect("unwrap failed"); - write!(&mut res, "{}", ", ").expect("unwrap failed"); - write!(&mut res, "{}", hardcoded_paths::get_jre()).expect("unwrap failed"); - write!(&mut res, "{}", ", registry or JAVA_HOME) in attempt to start. Please fix this.").expect("unwrap failed"); - logger.info(&res); - } - } - None => { - logger.log("itw-rust-debug: property not located or file inaccessible"); - } - } - } - None -} - -/*tests*/ -/*To print the diagnostic output use `cargo test -- --nocapture -`*/ -#[cfg(test)] -mod tests { - use std; - use os_access; - use std::cell::RefCell; - use utils::tests_utils as tu; - //if you wont to investigate files used for testing - // use cargo test -- --nocapture to see files which needs delete - static DELETE_TEST_FILES: bool = true; - - pub struct TestLogger { - vec: RefCell<Vec<String>>, - } - - impl TestLogger { - fn get_log(&self) -> String { - let joined = self.vec.borrow_mut().join("; "); - joined - } - } - - impl os_access::Os for TestLogger { - fn log(&self, s: &str) { - let ss = String::from(s); - self.vec.borrow_mut().push(ss); - } - - fn info(&self, s: &str) { - let ss = String::from(s); - self.vec.borrow_mut().push(ss); - } - - fn get_registry_jdk(&self) -> Option<std::path::PathBuf> { - None - } - - fn spawn_java_process(&self, jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Child { - panic!("not implemented"); - } - } - - #[test] - fn try_jdk_from_properties_files_4nothing() { - let array: [Option<std::path::PathBuf>; 4] = [ - None, - None, - None, - None - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - assert_eq!(None, r); - } - - #[test] - fn try_jdk_from_properties_files_4nonexisting() { - let array: [Option<std::path::PathBuf>; 4] = [ - Some(std::path::PathBuf::from("Nonexisting file 1")), - Some(std::path::PathBuf::from("Nonexisting file 2")), - Some(std::path::PathBuf::from("Nonexisting file 3")), - Some(std::path::PathBuf::from("Nonexisting file 4")), - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - assert_eq!(None, r); - } - - fn clean_fake_files(array: &[Option<std::path::PathBuf>]) { - for jdk in array { - match jdk.clone() { - Some(path) => { - if DELETE_TEST_FILES { - tu::debuggable_remove_file(&path); - } else { - println!("file {} intentionally not deleted!", path.display()); - } - } - None => {} - } - } - } - - #[test] - fn try_jdk_from_properties_files_4empty() { - let array: [Option<std::path::PathBuf>; 4] = [ - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_file())), - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - clean_fake_files(&array); - assert_eq!(None, r); - } - - #[test] - fn try_jdk_from_properties_files_invalid_jdk() { - let array: [Option<std::path::PathBuf>; 4] = [ - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre1"))), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre2"))), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre3"))), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre4"))), - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - clean_fake_files(&array); - assert_eq!(None, r); - assert_eq!(true, os.get_log().contains("is not valid")); - assert_eq!(true, os.get_log().contains("non/existing/jre1")); - assert_eq!(true, os.get_log().contains("non/existing/jre2")); - assert_eq!(true, os.get_log().contains("non/existing/jre3")); - assert_eq!(true, os.get_log().contains("non/existing/jre4")); - } - - #[test] - fn try_jdk_from_properties_files_none_and_valid() { - let master_dir = tu::fake_jre(true); - let array: [Option<std::path::PathBuf>; 4] = [ - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir.display().to_string()))), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre3"))), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre4"))), - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - clean_fake_files(&array); - assert_ne!(None, r); - assert_ne!(true, os.get_log().contains("is not valid")); - assert_ne!(true, os.get_log().contains("non/existing/jre3")); - assert_ne!(true, os.get_log().contains("non/existing/jre4")); - assert_eq!(master_dir.display().to_string(), r.expect("r should be full")); - } - - #[test] - fn try_jdk_from_properties_files_none_and_more_valid() { - let master_dir1 = tu::fake_jre(true); - let master_dir2 = tu::fake_jre(true); - let array: [Option<std::path::PathBuf>; 4] = [ - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir1.display().to_string()))), - Some(std::path::PathBuf::from(tu::create_tmp_file())), - Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir2.display().to_string()))), - ]; - let os = TestLogger { vec: RefCell::new(Vec::new()) }; - let r = super::try_jdk_from_properties_files(&os, &array); - println!("{}", &os.get_log()); - clean_fake_files(&array); - assert_ne!(None, r); - assert_ne!(true, os.get_log().contains("is not valid")); - assert_eq!(master_dir1.display().to_string(), r.expect("also this r should be full")); - } -} - -
--- a/rust-launcher/src/main.rs Wed Nov 28 12:35:38 2018 +0100 +++ b/rust-launcher/src/main.rs Fri Nov 30 19:04:42 2018 +0100 @@ -1,7 +1,8 @@ mod hardcoded_paths; -mod jvm_from_properties; +mod property_from_file; mod os_access; -mod jvm_from_properties_resolver; +mod dirs_paths_helper; +mod property_from_files_resolver; mod utils; mod property; @@ -26,11 +27,9 @@ let os = os_access::Linux::new(is_debug_on()); let java_dir: std::path::PathBuf; let mut info1 = String::new(); - write!(&mut info1, "{}", "itw-rust-debug: trying jdk over properties (").expect("unwrap failed"); - write!(&mut info1, "{}", jvm_from_properties::PROPERTY_NAME).expect("unwrap failed"); - write!(&mut info1, "{}", ")").expect("unwrap failed"); + write!(&mut info1, "itw-rust-debug: trying jdk over properties ({})", property_from_file::JRE_PROPERTY_NAME).expect("unwrap failed"); os.log(&info1); - match jvm_from_properties_resolver::try_jdk_from_properties(&os) { + match property_from_files_resolver::try_jdk_from_properties(&os) { Some(path) => { java_dir = std::path::PathBuf::from(path); os.log("itw-rust-debug: found and using"); @@ -62,8 +61,7 @@ } } let mut info2 = String::new(); - write!(&mut info2, "{}", "selected jre: ").expect("unwrap failed"); - write!(&mut info2, "{}", java_dir.display()).expect("unwrap failed"); + write!(&mut info2, "selected jre: {}", java_dir.display()).expect("unwrap failed"); os.info(&info2); let mut child = os.spawn_java_process(&java_dir, &(env::args().skip(1).collect())); let ecode = child.wait().expect("failed to wait on child");
--- a/rust-launcher/src/os_access.rs Wed Nov 28 12:35:38 2018 +0100 +++ b/rust-launcher/src/os_access.rs Fri Nov 30 19:04:42 2018 +0100 @@ -1,10 +1,19 @@ use std; +use dirs_paths_helper; pub trait Os { //logging "api" can change fn log(&self, s: &str); fn info(&self, s: &str); fn get_registry_jdk(&self) -> Option<std::path::PathBuf>; + // next to system and home cfg dir, there is also by-jre config dir, but that do not need to be handled os-specific way + //https://docs.oracle.com/javase/7/docs/technotes/guides/jweb/jcp/properties.html + fn get_system_config_javadir(&self) -> Option<std::path::PathBuf>; + fn get_user_config_dir(&self) -> Option<std::path::PathBuf>; + //is valid only on linux, otherwise returns get_system_config_javadir + fn get_legacy_system_config_javadir(&self) -> Option<std::path::PathBuf>; + //is valid only on linux, otherwise returns get_user_config_dir + fn get_legacy_user_config_dir(&self) -> Option<std::path::PathBuf>; fn spawn_java_process(&self, jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Child; } @@ -33,6 +42,36 @@ None } + fn get_system_config_javadir(&self) -> Option<std::path::PathBuf> { + let path = std::path::PathBuf::from("/etc/.java/deployment"); + Some(path) + } + + fn get_user_config_dir(&self) -> Option<std::path::PathBuf> { + match dirs_paths_helper::get_xdg_config_dir() { + Some(mut p) => { + p.push(dirs_paths_helper::ICEDTEA_WEB); + Some(p) + } + None => None + } + } + + fn get_legacy_system_config_javadir(&self) -> Option<std::path::PathBuf> { + let path = std::path::PathBuf::from("/etc/.java/.deploy"); + Some(path) + } + + fn get_legacy_user_config_dir(&self) -> Option<std::path::PathBuf> { + match dirs_paths_helper::get_home() { + Some(mut p) => { + p.push(".icedtea"); + Some(p) + } + None => None + } + } + fn spawn_java_process(&self, jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Child { let mut bin_java = jre_dir.clone(); bin_java.push("bin");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust-launcher/src/property_from_file.rs Fri Nov 30 19:04:42 2018 +0100 @@ -0,0 +1,199 @@ +use property; +use hardcoded_paths; + +use std; +use std::string::String; +use std::fs::File; +use std::fmt::Write; + +pub static JRE_PROPERTY_NAME: &'static str = "deployment.jre.dir"; +pub static VERBOSE_PROPERTY_NAME: &'static str = "deployment.log"; + + +pub trait Validator { + fn validate(&self, s: &str) -> bool; + fn get_fail_message(&self, key: &str, value: &str, file: &Option<std::path::PathBuf>) -> String; +} + +pub struct JreValidator {} + + +impl Validator for JreValidator { + fn validate(&self, s: &str) -> bool { + verify_jdk_string(&s) + } + + fn get_fail_message(&self, key: &str, value: &str, file: &Option<std::path::PathBuf>) -> String { + let mut res = String::new(); + write!(&mut res, "Your custom JRE {} read from {} under key {} is not valid.", value, file.clone().expect("jre path should be loaded").display(), key).expect("unwrap failed"); + write!(&mut res, " Trying other config files, then using default ({}, {}, registry or JAVA_HOME) in attempt to start. Please fix this.", hardcoded_paths::get_java(), hardcoded_paths::get_jre()).expect("unwrap failed"); + return res; + } +} + +fn is_file(path: &std::path::PathBuf) -> bool { + path.metadata().map(|md| md.is_file()).unwrap_or(false) +} + + +pub fn get_property_from_file(file: Option<std::path::PathBuf>, key: &str) -> Option<String> { + match file { + None => None, + Some(path) => { + get_property_from_file_direct(path, key) + } + } +} + +fn get_property_from_file_direct(path: std::path::PathBuf, key: &str) -> Option<String> { + if !path.exists() { + None + } else if !is_file(&path) { + return None; + } else { + let fileresult = File::open(path); + match fileresult { + Err(_fe) => None, + Ok(file) => { + let result = check_file_for_property(file, key); + result + } + } + } +} + +fn check_file_for_property(file: File, key: &str) -> Option<String> { + let p = property::Property::load(file, key); + match p { + None => { None } + Some(property) => { + Some(property.value) + } + } +} + + +fn verify_jdk_string(spath: &str) -> bool { + let mut file = std::path::PathBuf::from(spath); + file.push("bin"); + file.push("java"); + if !file.exists() { + false + } else if !is_file(&file) { + false + } else { + true + } +} + +/*tests*/ +#[cfg(test)] +mod tests { + use std; + use std::fs::File; + use utils::tests_utils as tu; + + fn get_jre_from_file(file: Option<std::path::PathBuf>) -> Option<String> { + super::get_property_from_file(file, super::JRE_PROPERTY_NAME) + } + + #[test] + fn is_not_file_() { + let r = super::is_file(&std::path::PathBuf::from("/definitely/not/existing/file")); + assert_eq!(false, r); + } + + #[test] + fn is_file_() { + let dir = tu::create_tmp_file(); + let r = super::is_file(&dir); + tu::debuggable_remove_file(&dir); + assert_eq!(true, r); + } + + #[test] + fn check_file_for_property_jredir_not_found() { + let path = tu::create_tmp_file(); + let f = File::open(&path); + let prop = super::check_file_for_property(f.expect("file was not opened"), super::JRE_PROPERTY_NAME); + tu::debuggable_remove_file(&path); + assert_eq!(None, prop); + } + + #[test] + fn check_file_for_property_jredir() { + let path = tu::create_tmp_propfile_with_content(); + let f = File::open(&path); + let prop = super::check_file_for_property(f.expect("file was not opened"), super::JRE_PROPERTY_NAME); + tu::debuggable_remove_file(&path); + assert_eq!("/some/jre", prop.expect("property was supposed to be loaded")); + } + + + #[test] + fn check_file_for_property_not_found() { + let path = tu::create_tmp_propfile_with_content(); + let f = File::open(&path); + let k = "not_existing_key"; + let prop = super::check_file_for_property(f.expect("file was not opened"), k); + tu::debuggable_remove_file(&path); + assert_eq!(None, prop); + } + + #[test] + fn check_file_for_property_item_exists() { + let path = tu::create_tmp_propfile_with_content(); + let f = File::open(&path); + let k = "key2"; + let prop = super::check_file_for_property(f.expect("file was not opened"), k); + tu::debuggable_remove_file(&path); + assert_eq!("val2", prop.expect("property was supposed to be loaded")); + } + + #[test] + fn get_jre_from_file_exists() { + let path = tu::create_tmp_propfile_with_content(); + let prop = get_jre_from_file(Some(path.clone())); + tu::debuggable_remove_file(&path); + assert_eq!("/some/jre", prop.expect("property was supposed to be loaded")); + } + + #[test] + fn get_jre_from_file_not_found() { + let path = tu::create_tmp_file(); + let prop = get_jre_from_file(Some(path.clone())); + tu::debuggable_remove_file(&path); + assert_eq!(None, prop); + } + + + #[test] + fn get_jre_from_file_notexists() { + let path = tu::create_tmp_file(); + tu::debuggable_remove_file(&path); + let prop = get_jre_from_file(Some(path)); + assert_eq!(None, prop); + } + + #[test] + fn get_jre_from_file_none() { + let prop = get_jre_from_file(None); + assert_eq!(None, prop); + } + + #[test] + fn verify_jdk_string_verify_jdk_path_jdk_ok() { + let master_dir = tu::fake_jre(true); + let vs = super::verify_jdk_string(&master_dir.display().to_string()); + tu::debuggable_remove_dir(&master_dir); + assert_eq!(true, vs); + } + + #[test] + fn verify_jdk_string_verify_jdk_path_jdk_bad() { + let master_dir = tu::fake_jre(false); + let vs = super::verify_jdk_string(&master_dir.display().to_string()); + tu::debuggable_remove_dir(&master_dir); + assert_eq!(false, vs); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust-launcher/src/property_from_files_resolver.rs Fri Nov 30 19:04:42 2018 +0100 @@ -0,0 +1,229 @@ +use property_from_file; +use os_access; +use dirs_paths_helper; + +use std; +use std::string::String; +use std::fmt::Write; + +pub fn try_jdk_from_properties(logger: &os_access::Os) -> Option<String> { + //obviously search in jre dir is missing, when we search for jre + let array: [Option<std::path::PathBuf>; 4] = [ + dirs_paths_helper::get_itw_config_file(logger), + dirs_paths_helper::get_itw_legacy_config_file(logger), + dirs_paths_helper::get_itw_legacy_global_config_file(logger), + dirs_paths_helper::get_itw_global_config_file(logger) + ]; + try_key_from_properties_files(logger, &array, property_from_file::JRE_PROPERTY_NAME, &property_from_file::JreValidator {}) +} + +fn try_key_from_properties_files(logger: &os_access::Os, array: &[Option<std::path::PathBuf>], key: &str, validator: &property_from_file::Validator) -> Option<String> { + for file in array { + let mut info1 = String::new(); + write!(&mut info1, "itw-rust-debug: checking {} in: {}", key, file.clone().unwrap_or(std::path::PathBuf::from("None")).display()).expect("unwrap failed"); + logger.log(&info1); + match property_from_file::get_property_from_file(file.clone(), &key) { + Some(value) => { + let mut info2 = String::new(); + write!(&mut info2, "itw-rust-debug: located {} in file {}", value, file.clone().expect("file should be already verified").display()).expect("unwrap failed"); + logger.log(&info2); + if validator.validate(&value) { + return Some(value); + } else { + //the only output out of verbose mode + let res = validator.get_fail_message(&key, &value, file); + logger.info(&res); + } + } + None => { + logger.log("itw-rust-debug: property not located or file inaccessible"); + } + } + } + None +} + +/*tests*/ +/*To print the diagnostic output use `cargo test -- --nocapture +`*/ +#[cfg(test)] +mod tests { + use std; + use os_access; + use std::cell::RefCell; + use utils::tests_utils as tu; + use property_from_file; + //if you wont to investigate files used for testing + // use cargo test -- --nocapture to see files which needs delete + static DELETE_TEST_FILES: bool = true; + + pub struct TestLogger { + vec: RefCell<Vec<String>>, + } + + impl TestLogger { + fn get_log(&self) -> String { + let joined = self.vec.borrow_mut().join("; "); + joined + } + } + + impl os_access::Os for TestLogger { + fn log(&self, s: &str) { + let ss = String::from(s); + self.vec.borrow_mut().push(ss); + } + + fn info(&self, s: &str) { + let ss = String::from(s); + self.vec.borrow_mut().push(ss); + } + + fn get_registry_jdk(&self) -> Option<std::path::PathBuf> { + None + } + + fn spawn_java_process(&self, jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Child { + panic!("not implemented"); + } + + fn get_system_config_javadir(&self) -> Option<std::path::PathBuf> { + panic!("not implemented"); + } + + fn get_user_config_dir(&self) -> Option<std::path::PathBuf> { + panic!("not implemented"); + } + + fn get_legacy_system_config_javadir(&self) -> Option<std::path::PathBuf> { + panic!("not implemented"); + } + + fn get_legacy_user_config_dir(&self) -> Option<std::path::PathBuf> { + panic!("not implemented"); + } + } + + fn try_jdk_from_properties_files(logger: &os_access::Os, array: &[Option<std::path::PathBuf>]) -> Option<String> { + super::try_key_from_properties_files(logger, &array, property_from_file::JRE_PROPERTY_NAME, &property_from_file::JreValidator {}) + } + + #[test] + fn try_jdk_from_properties_files_4nothing() { + let array: [Option<std::path::PathBuf>; 4] = [ + None, + None, + None, + None + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + assert_eq!(None, r); + } + + #[test] + fn try_jdk_from_properties_files_4nonexisting() { + let array: [Option<std::path::PathBuf>; 4] = [ + Some(std::path::PathBuf::from("Nonexisting file 1")), + Some(std::path::PathBuf::from("Nonexisting file 2")), + Some(std::path::PathBuf::from("Nonexisting file 3")), + Some(std::path::PathBuf::from("Nonexisting file 4")), + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + assert_eq!(None, r); + } + + fn clean_fake_files(array: &[Option<std::path::PathBuf>]) { + for jdk in array { + match jdk.clone() { + Some(path) => { + if DELETE_TEST_FILES { + tu::debuggable_remove_file(&path); + } else { + println!("file {} intentionally not deleted!", path.display()); + } + } + None => {} + } + } + } + + #[test] + fn try_jdk_from_properties_files_4empty() { + let array: [Option<std::path::PathBuf>; 4] = [ + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_file())), + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + clean_fake_files(&array); + assert_eq!(None, r); + } + + #[test] + fn try_jdk_from_properties_files_invalid_jdk() { + let array: [Option<std::path::PathBuf>; 4] = [ + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre1"))), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre2"))), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre3"))), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre4"))), + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + clean_fake_files(&array); + assert_eq!(None, r); + assert_eq!(true, os.get_log().contains("is not valid")); + assert_eq!(true, os.get_log().contains("non/existing/jre1")); + assert_eq!(true, os.get_log().contains("non/existing/jre2")); + assert_eq!(true, os.get_log().contains("non/existing/jre3")); + assert_eq!(true, os.get_log().contains("non/existing/jre4")); + } + + #[test] + fn try_jdk_from_properties_files_none_and_valid() { + let master_dir = tu::fake_jre(true); + let array: [Option<std::path::PathBuf>; 4] = [ + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir.display().to_string()))), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre3"))), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content("non/existing/jre4"))), + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + clean_fake_files(&array); + assert_ne!(None, r); + assert_ne!(true, os.get_log().contains("is not valid")); + assert_ne!(true, os.get_log().contains("non/existing/jre3")); + assert_ne!(true, os.get_log().contains("non/existing/jre4")); + assert_eq!(master_dir.display().to_string(), r.expect("r should be full")); + } + + #[test] + fn try_jdk_from_properties_files_none_and_more_valid() { + let master_dir1 = tu::fake_jre(true); + let master_dir2 = tu::fake_jre(true); + let array: [Option<std::path::PathBuf>; 4] = [ + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir1.display().to_string()))), + Some(std::path::PathBuf::from(tu::create_tmp_file())), + Some(std::path::PathBuf::from(tu::create_tmp_propfile_with_custom_jre_content(&master_dir2.display().to_string()))), + ]; + let os = TestLogger { vec: RefCell::new(Vec::new()) }; + let r = try_jdk_from_properties_files(&os, &array); + println!("{}", &os.get_log()); + clean_fake_files(&array); + assert_ne!(None, r); + assert_ne!(true, os.get_log().contains("is not valid")); + assert_eq!(master_dir1.display().to_string(), r.expect("also this r should be full")); + } +} + +
--- a/rust-launcher/src/utils.rs Wed Nov 28 12:35:38 2018 +0100 +++ b/rust-launcher/src/utils.rs Fri Nov 30 19:04:42 2018 +0100 @@ -7,7 +7,7 @@ use std::fmt::Write as fmt_write; use std::io::Write; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - use jvm_from_properties; + use property_from_file; // rand is in separate crate, so using atomic increment instead static TMP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; @@ -98,7 +98,7 @@ let mut res = String::new(); write!(&mut res, "{}", "key1=val1\n").expect("unwrap failed"); write!(&mut res, "{}", "key2=val2\n").expect("unwrap failed"); - write!(&mut res, "{}", jvm_from_properties::PROPERTY_NAME).expect("unwrap failed"); + write!(&mut res, "{}", property_from_file::JRE_PROPERTY_NAME).expect("unwrap failed"); write!(&mut res, "{}", "=").expect("unwrap failed"); write!(&mut res, "{}", jre_path).expect("unwrap failed"); write!(&mut res, "{}", "\n").expect("unwrap failed");