/hg/icedtea-web: Os trait implemented for windows
jvanek at icedtea.classpath.org
jvanek at icedtea.classpath.org
Wed Feb 13 18:14:51 UTC 2019
changeset 0ec171908528 in /hg/icedtea-web
details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=0ec171908528
author: Jiri Vanek <jvanek at redhat.com>
date: Wed Feb 13 19:14:35 2019 +0100
Os trait implemented for windows
* rust-launcher/src/dirs_paths_helper.rs: added (get_os) os dependent factory method to provide os impl with debug off. (check_config_files_paths_global) split to os independent (check_config_files_paths) and rest linux only
* rust-launcher/src/jars_helper.rs: (get_bootclasspath) fixed issue with hardcoded cp delimiter in xbootclasspath
* rust-launcher/src/main.rs: added (get_os) os dependent factory method to provide os impl with debug parameter
* rust-launcher/src/os_access.rs: implemented os trait for windows
* rust-launcher/src/utils.rs: better recognition of rop_dir and parent dir in (try_jre_exists_on_path)
diffstat:
ChangeLog | 10 +
rust-launcher/src/dirs_paths_helper.rs | 28 +-
rust-launcher/src/jars_helper.rs | 3 +-
rust-launcher/src/main.rs | 14 +-
rust-launcher/src/os_access.rs | 421 +++++++++++++++++++++++++++++++++
rust-launcher/src/utils.rs | 4 +-
6 files changed, 468 insertions(+), 12 deletions(-)
diffs (truncated from 584 to 500 lines):
diff -r cb75d5ae33e0 -r 0ec171908528 ChangeLog
--- a/ChangeLog Wed Feb 13 18:05:44 2019 +0100
+++ b/ChangeLog Wed Feb 13 19:14:35 2019 +0100
@@ -1,3 +1,13 @@
+2019-02-13 Alex Kashchenko <akashche at redhat.com>
+
+ Os trait implemented for windows
+ * rust-launcher/src/dirs_paths_helper.rs: added (get_os) os dependent factory method to provide os impl with debug off.
+ (check_config_files_paths_global) split to os independent (check_config_files_paths) and rest linux only
+ * rust-launcher/src/jars_helper.rs: (get_bootclasspath) fixed issue with hardcoded cp delimiter in xbootclasspath
+ * rust-launcher/src/main.rs: added (get_os) os dependent factory method to provide os impl with debug parameter
+ * rust-launcher/src/os_access.rs: implemented os trait for windows
+ * rust-launcher/src/utils.rs: better recognition of rop_dir and parent dir in (try_jre_exists_on_path)
+
2019-02-13 Jiri Vanek <jvanek at redhat.com>
Propagating unimplemented DownloadService2. Added tests for it
diff -r cb75d5ae33e0 -r 0ec171908528 rust-launcher/src/dirs_paths_helper.rs
--- a/rust-launcher/src/dirs_paths_helper.rs Wed Feb 13 18:05:44 2019 +0100
+++ b/rust-launcher/src/dirs_paths_helper.rs Wed Feb 13 19:14:35 2019 +0100
@@ -84,18 +84,34 @@
use os_access;
use utils::tests_utils as tu;
+ #[cfg(not(windows))]
+ fn get_os() -> os_access::Linux {
+ os_access::Linux::new(false)
+ }
+
+ #[cfg(windows)]
+ fn get_os() -> os_access::Windows {
+ os_access::Windows::new(false)
+ }
+
+
+ #[test]
+ fn check_config_files_paths() {
+ let os = get_os();
+ let p3 = super::get_itw_config_file(&os);
+ assert_ne!(None, p3);
+ println!("{}", p3.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"));
+ }
+
#[test]
#[cfg(not(windows))]
- fn check_config_files_paths() {
+ fn check_config_files_paths_global() {
let os = os_access::Linux::new(false);
- let p3 = super::get_itw_config_file(&os);
let p6 = super::get_itw_global_config_file(&os);
- assert_ne!(None, p3);
assert_ne!(None, p6);
- println!("{}", p3.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, p6.clone().expect("unwrap failed").display().to_string().ends_with("deployment.properties"));
}
diff -r cb75d5ae33e0 -r 0ec171908528 rust-launcher/src/jars_helper.rs
--- a/rust-launcher/src/jars_helper.rs Wed Feb 13 18:05:44 2019 +0100
+++ b/rust-launcher/src/jars_helper.rs Wed Feb 13 19:14:35 2019 +0100
@@ -158,8 +158,7 @@
}
pub fn get_bootclasspath(jre_path: &std::path::PathBuf, os: &os_access::Os) -> String {
- let mut result = String::from("-Xbootclasspath/a");
- result.push(os.get_classpath_separator());
+ let mut result = String::from("-Xbootclasspath/a:");
result.push_str(&compose_class_path(get_bootcp_members(jre_path, os), os));
result
}
diff -r cb75d5ae33e0 -r 0ec171908528 rust-launcher/src/main.rs
--- a/rust-launcher/src/main.rs Wed Feb 13 18:05:44 2019 +0100
+++ b/rust-launcher/src/main.rs Wed Feb 13 19:14:35 2019 +0100
@@ -12,13 +12,23 @@
use os_access::Os;
use std::env;
+#[cfg(not(windows))]
+fn get_os(debug: bool) -> os_access::Linux {
+ os_access::Linux::new(debug)
+}
+
+#[cfg(windows)]
+fn get_os(debug: bool) -> os_access::Windows {
+ os_access::Windows::new(debug)
+}
+
fn is_debug_on() -> bool {
match is_debug_on_testable(env::args().collect::<Vec<_>>()) {
Some(val) => {
return val;
}
_none => {
- let os = os_access::Linux::new(false);
+ let os = get_os(false);
return property_from_files_resolver::try_main_verbose_from_properties(&os);
}
}
@@ -63,7 +73,7 @@
}
fn main() {
- let os = os_access::Linux::new(is_debug_on());
+ let os = get_os(is_debug_on());
os.log(&dirs_paths_helper::path_to_string(&dirs_paths_helper::current_program()));
let mut info1 = String::new();
write!(&mut info1, "itw-rust-debug: trying jdk over properties ({})", property_from_file::JRE_PROPERTY_NAME).expect("unwrap failed");
diff -r cb75d5ae33e0 -r 0ec171908528 rust-launcher/src/os_access.rs
--- a/rust-launcher/src/os_access.rs Wed Feb 13 18:05:44 2019 +0100
+++ b/rust-launcher/src/os_access.rs Wed Feb 13 19:14:35 2019 +0100
@@ -3,6 +3,8 @@
use std::env;
use std::fmt::Write;
+
+
pub trait Os {
// logging "api" can change
fn log(&self, s: &str);
@@ -25,16 +27,19 @@
fn get_exec_suffixes(&self) -> &'static [&'static str];
}
+#[cfg(not(windows))]
pub struct Linux {
verbose: bool,
}
+#[cfg(not(windows))]
impl Linux {
pub fn new(debug: bool) -> Linux {
Linux { verbose: debug }
}
}
+#[cfg(not(windows))]
impl Os for Linux {
fn log(&self, s: &str) {
if self.verbose {
@@ -127,3 +132,419 @@
&[""]
}
}
+
+
+#[cfg(windows)]
+pub struct Windows {
+ verbose: bool,
+}
+
+#[cfg(windows)]
+impl Windows {
+ pub fn new(debug: bool) -> Windows {
+ Windows { verbose: debug }
+ }
+
+}
+
+#[cfg(windows)]
+impl Os for Windows {
+ fn log(&self, s: &str) {
+ if self.verbose {
+ println!("{}", s);
+ }
+ }
+
+ fn info(&self, s: &str) {
+ println!("{}", s);
+ }
+
+ fn get_registry_jdk(&self) -> Option<std::path::PathBuf> {
+ std::panic::catch_unwind(|| {
+ let path = win::jdk_registry_path();
+ Some(std::path::PathBuf::from(path))
+ }).unwrap_or_else(|_e| {
+ // show_error_message(errloc_msg(&e));
+ None
+ })
+ }
+
+ fn get_system_config_javadir(&self) -> Option<std::path::PathBuf> {
+ None
+ }
+
+ fn get_user_config_dir(&self) -> Option<std::path::PathBuf> {
+ match self.get_home() {
+ Some(mut p) => {
+ p.push(".config");
+ p.push(dirs_paths_helper::ICEDTEA_WEB);
+ Some(p)
+ }
+ None => None
+ }
+ }
+
+ fn get_legacy_system_config_javadir(&self) -> Option<std::path::PathBuf> {
+ None
+ }
+
+ fn get_legacy_user_config_dir(&self) -> Option<std::path::PathBuf> {
+ 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");
+ 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)
+ }
+ }
+
+ fn get_home(&self) -> Option<std::path::PathBuf> {
+ match env::var("USERPROFILE") {
+ Ok(war) => {
+ let home_var_path = std::path::PathBuf::from(war);
+ if dirs_paths_helper::is_dir(&home_var_path) {
+ return Some(home_var_path);
+ }
+ }
+ Err(_) => {}
+ }
+ None
+ }
+
+ fn get_classpath_separator(&self) -> char {
+ ';'
+ }
+
+ //on linux, java is known to be compiled witout any suffix, on windows, it should be .exe
+ fn get_exec_suffixes(&self) -> &'static [&'static str] {
+ &[".exe"]
+ }
+}
+
+
+#[cfg(windows)]
+#[allow(non_snake_case)]
+#[allow(non_camel_case_types)]
+mod win {
+ // https://crates.io/crates/scopeguard
+ macro_rules! defer {
+ ($e:expr) => {
+ let _deferred = ScopeGuard::new((), |_| $e);
+ }
+ }
+
+ pub struct ScopeGuard<T, F> where F: FnMut(&mut T) {
+ __dropfn: F,
+ __value: T
+ }
+
+ impl<T, F> ScopeGuard<T, F> where F: FnMut(&mut T) {
+ pub fn new(v: T, dropfn: F) -> ScopeGuard<T, F> {
+ ScopeGuard {
+ __value: v,
+ __dropfn: dropfn
+ }
+ }
+ }
+
+ impl<T, F> Drop for ScopeGuard<T, F> where F: FnMut(&mut T) {
+ fn drop(&mut self) {
+ (self.__dropfn)(&mut self.__value)
+ }
+ }
+
+ // https://crates.io/crates/errloc_macros
+ macro_rules! errloc {
+ () => {
+ concat!(file!(), ':', line!())
+ }
+ }
+
+ fn errloc_msg<'a>(e: &'a Box<std::any::Any + Send + 'static>) -> &'a str {
+ match e.downcast_ref::<&str>() {
+ Some(st) => st,
+ None => {
+ match e.downcast_ref::<String>() {
+ Some(stw) => stw.as_str(),
+ None => "()",
+ }
+ },
+ }
+ }
+
+ // implementation
+
+ use std;
+ use std::os::raw::*;
+ use std::ptr::{null, null_mut};
+
+ // constants
+ const CP_UTF8: c_ulong = 65001;
+ const FORMAT_MESSAGE_ALLOCATE_BUFFER: c_ulong = 0x00000100;
+ const FORMAT_MESSAGE_FROM_SYSTEM: c_ulong = 0x00001000;
+ const FORMAT_MESSAGE_IGNORE_INSERTS: c_ulong = 0x00000200;
+ const LANG_NEUTRAL: c_ushort = 0x00;
+ const SUBLANG_DEFAULT: c_ushort = 0x01;
+ const ERROR_SUCCESS: c_ulong = 0;
+ const READ_CONTROL: c_ulong = 0x00020000;
+ const STANDARD_RIGHTS_READ: c_ulong = READ_CONTROL;
+ const KEY_QUERY_VALUE: c_ulong = 0x0001;
+ const KEY_ENUMERATE_SUB_KEYS: c_ulong = 0x0008;
+ const KEY_NOTIFY: c_ulong = 0x0010;
+ const SYNCHRONIZE: c_ulong = 0x00100000;
+ const REG_SZ: c_ulong = 1;
+ const KEY_READ: c_ulong = (
+ STANDARD_RIGHTS_READ |
+ KEY_QUERY_VALUE |
+ KEY_ENUMERATE_SUB_KEYS |
+ KEY_NOTIFY
+ ) & (!SYNCHRONIZE);
+ const HKEY_LOCAL_MACHINE: *mut c_void = 0x80000002 as *mut c_void;
+
+ // function declarations
+
+ extern "system" {
+ fn MultiByteToWideChar(
+ CodePage: c_uint,
+ dwFlags: c_ulong,
+ lpMultiByteStr: *const c_char,
+ cbMultiByte: c_int,
+ lpWideCharStr: *mut c_ushort,
+ cchWideChar: c_int
+ ) -> c_int;
+
+ fn WideCharToMultiByte(
+ CodePage: c_uint,
+ dwFlags: c_ulong,
+ lpWideCharStr: *const c_ushort,
+ cchWideChar: c_int,
+ lpMultiByteStr: *mut c_char,
+ cbMultiByte: c_int,
+ lpDefaultChar: *const c_char,
+ lpUsedDefaultChar: *mut c_int
+ ) -> c_int;
+
+ fn GetLastError() -> c_ulong;
+
+ fn FormatMessageW(
+ dwFlags: c_ulong,
+ lpSource: *const c_void,
+ dwMessageId: c_ulong,
+ dwLanguageId: c_ulong,
+ lpBuffer: *mut c_ushort,
+ nSize: c_ulong,
+ Arguments: *mut *mut c_char
+ ) -> c_ulong;
+
+ fn LocalFree(
+ hMem: *mut c_void
+ ) -> *mut c_void;
+
+ fn RegOpenKeyExW(
+ hKey: *mut c_void,
+ lpSubKey: *const c_ushort,
+ ulOptions: c_ulong,
+ samDesired: c_ulong,
+ phkResult: *mut *mut c_void
+ ) -> c_long;
+
+ fn RegCloseKey(
+ hKey: *mut c_void
+ ) -> c_long;
+
+ fn RegQueryValueExW(
+ hKey: *mut c_void,
+ lpValueName: *const c_ushort,
+ lpReserved: *mut c_ulong,
+ lpType: *mut c_ulong,
+ lpData: *mut c_uchar,
+ lpcbData: *mut c_ulong
+ ) -> c_long;
+ }
+
+ // windows-specific utilities
+
+ fn MAKELANGID(p: c_ushort, s: c_ushort) -> c_ushort {
+ (s << 10 | p)
+ }
+
+ fn widen(st: &str) -> Vec<u16> {
+ unsafe {
+ let size_needed = MultiByteToWideChar(
+ CP_UTF8,
+ 0,
+ st.as_ptr() as *mut i8,
+ st.len() as c_int,
+ null_mut::<u16>(),
+ 0);
+ if 0 == size_needed {
+ panic!(format!("Error on string widen calculation, \
+ string: [{}], error: [{}]", st, errcode_to_string(GetLastError())));
+ }
+ let mut res: Vec<u16> = Vec::new();
+ res.resize((size_needed + 1) as usize, 0);
+ let chars_copied = MultiByteToWideChar(
+ CP_UTF8,
+ 0,
+ st.as_ptr() as *mut i8,
+ st.len() as c_int,
+ res.as_mut_ptr(),
+ size_needed);
+ if chars_copied != size_needed {
+ panic!(format!("Error on string widen execution, \
+ string: [{}], error: [{}]", st, errcode_to_string(GetLastError())));
+ }
+ res.resize(size_needed as usize, 0);
+ res
+ }
+ }
+
+ fn narrow(wst: &[u16]) -> String {
+ unsafe {
+ let size_needed = WideCharToMultiByte(
+ CP_UTF8,
+ 0,
+ wst.as_ptr(),
+ wst.len() as c_int,
+ null_mut::<i8>(),
+ 0,
+ null::<c_char>(),
+ null_mut::<c_int>());
+ if 0 == size_needed {
+ panic!(format!("Error on string narrow calculation, \
+ string length: [{}], error code: [{}]", wst.len(), GetLastError()));
+ }
+ let mut vec: Vec<u8> = Vec::new();
+ vec.resize(size_needed as usize, 0);
+ let bytes_copied = WideCharToMultiByte(
+ CP_UTF8,
+ 0,
+ wst.as_ptr(),
+ wst.len() as c_int,
+ vec.as_mut_ptr() as *mut i8,
+ size_needed,
+ null::<c_char>(),
+ null_mut::<c_int>());
+ if bytes_copied != size_needed {
+ panic!(format!("Error on string narrow execution, \
+ string length: [{}], error code: [{}]", vec.len(), GetLastError()));
+ }
+ String::from_utf8(vec).expect(errloc!())
+ }
+ }
+
+ fn errcode_to_string(code: c_ulong) -> String {
+ if 0 == code {
+ return String::new();
+ }
+ unsafe {
+ let mut buf: *mut u16 = null_mut::<u16>();
+ let size = FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ null::<c_void>(),
+ code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) as c_ulong,
+ std::mem::transmute::<*mut *mut u16, *mut u16>(&mut buf),
+ 0,
+ null_mut::<*mut c_char>());
+ if 0 == size {
+ return format!("Cannot format code: [{}] \
+ into message, error code: [{}]", code, GetLastError());
+ }
+ defer!({
+ LocalFree(buf as *mut c_void);
+ });
+ if size <= 2 {
+ return format!("code: [{}], message: []", code);
+ }
+ std::panic::catch_unwind(|| {
+ let slice = std::slice::from_raw_parts(buf, (size - 2) as usize);
+ let msg = narrow(slice);
+ format!("code: [{}], message: [{}]", code, msg)
+ }).unwrap_or_else(|e| {
+ format!("Cannot format code: [{}] \
+ into message, narrow error: [{}]", code, errloc_msg(&e))
+ })
+ }
+ }
More information about the distro-pkg-dev
mailing list