changeset 1550:6a1effecd739

Native launchers got support for modular jdk (via @MODULARJDK_ARGS_LOCATION file) * rust-launcher/src/hardcoded_paths.rs: introduced MODULARJDK_ARGS_LOCATION recognition * rust-launcher/src/jars_helper.rs: now are able search in bin, and this reads MODULARJDK_ARGS_LOCATION * rust-launcher/src/main.rs: now reads java -version, and if modular, put MODULARJDK_ARGS_LOCATION to args * rust-launcher/src/os_access.rs: removed duplicated code form windows in java spawn, extracted args creation so it could be reused for java version recognition * rust-launcher/src/property.rs: added note about Unicode failure in case properties (thus jre location) contains \u values
author Jiri Vanek <jvanek@redhat.com>
date Fri, 15 Feb 2019 16:03:31 +0100
parents 0ec171908528
children 8b44a9e23bd2
files ChangeLog rust-launcher/src/hardcoded_paths.rs rust-launcher/src/jars_helper.rs rust-launcher/src/main.rs rust-launcher/src/os_access.rs rust-launcher/src/property.rs
diffstat 6 files changed, 156 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Feb 13 19:14:35 2019 +0100
+++ b/ChangeLog	Fri Feb 15 16:03:31 2019 +0100
@@ -1,3 +1,13 @@
+2019-02-15  Jiri Vanek <jvanek@redhat.com>
+
+	Native launchers got support for modular jdk  (via @MODULARJDK_ARGS_LOCATION file)
+	* rust-launcher/src/hardcoded_paths.rs: introduced MODULARJDK_ARGS_LOCATION recognition
+	* rust-launcher/src/jars_helper.rs: now are able search in bin, and this reads MODULARJDK_ARGS_LOCATION
+	* rust-launcher/src/main.rs: now reads java -version, and if modular, put MODULARJDK_ARGS_LOCATION to args
+	* rust-launcher/src/os_access.rs: removed duplicated code form windows in java spawn, extracted args creation
+	so it could be reused for java version recognition
+	* rust-launcher/src/property.rs: added note about Unicode failure in case properties (thus jre location) contains \u values
+
 2019-02-13  Alex Kashchenko <akashche@redhat.com>
 
 	Os trait implemented for windows
--- a/rust-launcher/src/hardcoded_paths.rs	Wed Feb 13 19:14:35 2019 +0100
+++ b/rust-launcher/src/hardcoded_paths.rs	Fri Feb 15 16:03:31 2019 +0100
@@ -18,6 +18,7 @@
 const TAGSOUP_JAR: Option<&'static str> = option_env!("TAGSOUP_JAR");
 const RHINO_JAR: Option<&'static str> = option_env!("RHINO_JAR");
 const ITW_LIBS: Option<&'static str> = option_env!("ITW_LIBS");
+const MODULARJDK_ARGS_LOCATION: Option<&'static str> = option_env!("MODULARJDK_ARGS_LOCATION");
 
 
 pub fn get_jre() -> &'static str {
@@ -63,6 +64,10 @@
 
 pub fn get_rhino() -> Option<&'static str> { RHINO_JAR }
 
+pub fn get_argsfile() -> &'static str {
+    MODULARJDK_ARGS_LOCATION.unwrap_or("MODULARJDK_ARGS_LOCATION-dev-unspecified")
+}
+
 
 #[derive(PartialEq)]
 pub enum ItwLibSearch {
@@ -137,6 +142,7 @@
         assert_ne!(String::from(super::get_splash()).trim(), String::from("SPLASH_PNG-dev-unspecified"));
         assert_ne!(String::from(super::get_netx()).trim(), String::from("NETX_JAR-dev-unspecified"));
         assert_ne!(String::from(super::get_itwlibsearch()).trim(), String::from("ITW_LIBS-dev-unspecified"));
+        assert_ne!(String::from(super::get_argsfile()).trim(), String::from("MODULARJDK_ARGS_LOCATION-dev-unspecified"));
     }
 
     #[test]
@@ -149,6 +155,7 @@
         assert_ne!(String::from(super::get_splash()).trim(), String::from(""));
         assert_ne!(String::from(super::get_netx()).trim(), String::from(""));
         assert_ne!(String::from(super::get_itwlibsearch()).trim(), String::from(""));
+        assert_ne!(String::from(super::get_argsfile()).trim(), String::from(""));
     }
 
     #[test]
--- a/rust-launcher/src/jars_helper.rs	Wed Feb 13 19:14:35 2019 +0100
+++ b/rust-launcher/src/jars_helper.rs	Fri Feb 15 16:03:31 2019 +0100
@@ -16,7 +16,24 @@
     "../linux-deps-runtime",
     "../win-deps-runtime",
     "../win-deps-all",
-    "."];
+    ".",
+    "bin",
+    "../bin"];
+
+pub fn resolve_argsfile(logger: &os_access::Os) -> std::path::PathBuf {
+    resolve_jar(hardcoded_paths::get_argsfile(), logger)
+}
+
+pub fn resolve_jsobject(logger: &os_access::Os) -> Option<std::path::PathBuf> {
+    match hardcoded_paths::get_jsobject() {
+        Some(js) => {
+            Some(resolve_jar(js, logger))
+        }
+        None => {
+            None
+        }
+    }
+}
 
 
 pub fn resolve_splash(logger: &os_access::Os) -> std::path::PathBuf {
--- a/rust-launcher/src/main.rs	Wed Feb 13 19:14:35 2019 +0100
+++ b/rust-launcher/src/main.rs	Fri Feb 15 16:03:31 2019 +0100
@@ -139,7 +139,17 @@
             os.log("itw-rust-debug: splash excluded");
         }
     }
-
+    if is_modular_jdk(os, &java_dir) {
+        all_args.push(resolve_argsfile(os));
+        let js_object_candidate = get_jsobject_patchmodule(os);
+        match js_object_candidate {
+            Some(js_object_path) => {
+                all_args.push(js_object_path.0);
+                all_args.push(js_object_path.1);
+            }
+            _none => {}
+        }
+    }
     all_args.push(bootcp);
     all_args.push(String::from("-classpath"));
     all_args.push(cp);
@@ -152,6 +162,78 @@
     all_args
 }
 
+fn is_modular_jdk(os: &os_access::Os, jre_dir: &std::path::PathBuf) -> bool {
+    if jdk_version(os, jre_dir) > 8 {
+        os.log("itw-rust-debug: modular jdk");
+        true
+    } else {
+        os.log("itw-rust-debug: non-modular jdk");
+        false
+    }
+}
+
+fn jdk_version(os: &os_access::Os, jre_dir: &std::path::PathBuf) -> i32 {
+    let vec = vec!["-version".to_string()];
+    //this of  course fails during tests
+    let output_result = os_access::create_java_cmd(os, jre_dir, &vec).output();
+    match output_result {
+        Ok(output) => {
+            for line in String::from_utf8(output.stderr).expect("java version was supopsed to return output").lines() {
+                if line.contains("version")
+                    && (line.contains("\"1")
+                    || line.contains("\"2")
+                    || line.contains("\"3")) {
+                    if line.contains("\"1.7.0") || line.contains("\"1.7.1") {
+                        os.log("itw-rust-debug: detected jdk 7");
+                        return 7
+                    } else if line.contains("\"1.8.0") {
+                        os.log("itw-rust-debug: detected jdk 8");
+                        return 8
+                    } else {
+                        //currently this serves only to determine module/non modular jdk
+                        os.log("itw-rust-debug: detected jdk 9 or up");
+                        return 9
+                    }
+                }
+            }
+            os.log("itw-rust-debug: unrecognized jdk! Fallback to 8!");
+            return 8;
+        }
+        _Error => {
+            os.log("itw-rust-debug: failed to launch jdk recognition. fallback to 8");
+            return 8
+        }
+    }
+}
+
+fn resolve_argsfile(os: &os_access::Os) -> String {
+    let args_location = dirs_paths_helper::path_to_string(&jars_helper::resolve_argsfile(os));
+    let mut owned_string: String = args_location.to_owned();
+    let splash_switch: &str = "@";
+    owned_string.insert_str(0, splash_switch);
+    let r = String::from(owned_string);
+    r
+}
+
+
+fn get_jsobject_patchmodule(os: &os_access::Os) -> Option<(String, String)> {
+    let js_object_candidate = jars_helper::resolve_jsobject(os);
+    match js_object_candidate {
+        Some(js_object_path) => {
+            let args_location = dirs_paths_helper::path_to_string(&js_object_path);
+            let mut owned_string: String = args_location.to_owned();
+            let splash_switch: &str = "jdk.jsobject=";
+            owned_string.insert_str(0, splash_switch);
+            let r = String::from(owned_string);
+            let tuple = ("--patch-module".to_string(), r);
+            return Some(tuple)
+        }
+        None => {
+            return None
+        }
+    }
+}
+
 fn get_splash(os: &os_access::Os) -> Option<String> {
     let headless = is_headless_enforced();
     let splash_forbidden = is_splash_forbidden();
--- a/rust-launcher/src/os_access.rs	Wed Feb 13 19:14:35 2019 +0100
+++ b/rust-launcher/src/os_access.rs	Fri Feb 15 16:03:31 2019 +0100
@@ -3,7 +3,32 @@
 use std::env;
 use std::fmt::Write;
 
+pub fn create_java_cmd(os: &Os,jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Command {
+    let mut bin_java = jre_dir.clone();
+    bin_java.push("bin");
+    bin_java.push("java");
+    let mut cmd = std::process::Command::new(&bin_java);
+    for ar in args.into_iter() {
+        cmd.arg(ar);
+    }
+    let mut info = String::new();
+    write!(&mut info, "itw-rust-debug: command {}", format!("{:?}", cmd)).expect("unwrap failed");
+    os.log(&info);
+    return cmd;
+}
 
+fn spawn_java_process(os: &Os, jre_dir: &std::path::PathBuf, args: &Vec<String>) -> std::process::Child {
+    let mut cmd = create_java_cmd(os, jre_dir, args);
+    cmd.stdin(std::process::Stdio::inherit());
+    cmd.stdout(std::process::Stdio::inherit());
+    cmd.stderr(std::process::Stdio::inherit());
+    let res = cmd.spawn();
+    match res {
+        Ok(child) => child,
+        Err(_) => panic!("Error spawning JVM process, \
+                 java executable: [{}], arguments: [{:?}]", jre_dir.clone().into_os_string().to_str().expect("path should unwrap"), args)
+    }
+}
 
 pub trait Os {
     // logging "api" can change
@@ -86,25 +111,7 @@
     }
 
     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");
-        bin_java.push("java");
-        let mut cmd = std::process::Command::new(&bin_java);
-        for ar in args.into_iter() {
-            cmd.arg(ar);
-        }
-        cmd.stdin(std::process::Stdio::inherit());
-        cmd.stdout(std::process::Stdio::inherit());
-        cmd.stderr(std::process::Stdio::inherit());
-        let mut info = String::new();
-        write!(&mut info, "itw-rust-debug: command {}", format!("{:?}", cmd)).expect("unwrap failed");
-        self.log(&info);
-        let res = cmd.spawn();
-        match res {
-            Ok(child) => child,
-            Err(_) => panic!("Error spawning JVM process, \
-                 java executable: [{}], arguments: [{:?}]", bin_java.into_os_string().to_str().expect("path should unwrap"), args)
-        }
+        spawn_java_process(self, jre_dir, args)
     }
 
     fn get_home(&self) -> Option<std::path::PathBuf> {
@@ -193,25 +200,8 @@
     }
 
     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");
-        bin_java.push("java");
-        let mut cmd = std::process::Command::new(&bin_java);
-        for ar in args.into_iter() {
-            cmd.arg(ar);
-        }
-        cmd.stdin(std::process::Stdio::inherit());
-        cmd.stdout(std::process::Stdio::inherit());
-        cmd.stderr(std::process::Stdio::inherit());
-        let mut info = String::new();
-        write!(&mut info, "itw-rust-debug: command {}", format!("{:?}", cmd)).expect("unwrap failed");
-        self.log(&info);
-        let res = cmd.spawn();
-        match res {
-            Ok(child) => child,
-            Err(_) => panic!("Error spawning JVM process, \
-                 java executable: [{}], arguments: [{:?}]", bin_java.into_os_string().to_str().expect("path should unwrap"), args)
-        }
+        //there was an intention, which caused all the os trait, to implement this better. However developer (alex) faield and gave up
+        spawn_java_process(self, jre_dir, args)
     }
 
     fn get_home(&self) -> Option<std::path::PathBuf> {
--- a/rust-launcher/src/property.rs	Wed Feb 13 19:14:35 2019 +0100
+++ b/rust-launcher/src/property.rs	Fri Feb 15 16:03:31 2019 +0100
@@ -63,6 +63,15 @@
     }
 }
 
+//error[E0658]: use of unstable library feature 'str_escape': return type may change to be an iterator (see issue #27791)
+//
+//                             let a = kvv.value.escape_unicode();
+//For more information about this error, try `rustc --explain E0658`.
+//https://icedtea.classpath.org/bugzilla/show_bug.cgi?id=3697
+fn escape_unicode(src: String) -> String {
+    src
+}
+
 fn check_file_for_property(file: File, key: &str) -> Option<String> {
     let bf = BufReader::new(file);
     for lineresult in bf.lines() {
@@ -76,7 +85,7 @@
                     None => {}
                     Some(kvv) => {
                         if kvv.key.eq(key) {
-                            return Some(kvv.value);
+                            return Some(escape_unicode(kvv.value));
                         }
                     }
                 }