Skip to content

Commit dac6523

Browse files
Merge pull request #6 from rukai/cleanup
Remove lazy_static + cleanup lib.rs
2 parents 0a2b154 + 2c97eb8 commit dac6523

File tree

4 files changed

+121
-136
lines changed

4 files changed

+121
-136
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ required-features = ["build-binary"]
2323

2424
[dependencies]
2525
glob = "0.3"
26-
lazy_static = "1.4"
2726
docopt = { version = "1.1", optional = true }
2827

2928
[features]

src/errors.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,21 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
use std::{fmt, result, string};
1514
use std::error::Error;
15+
use std::{fmt, result};
1616

1717
use glob;
1818

1919
pub type Result<T> = result::Result<T, JavaLocatorError>;
2020

2121
#[derive(Debug)]
2222
pub struct JavaLocatorError {
23-
description: String
23+
description: String,
2424
}
2525

2626
impl JavaLocatorError {
27-
pub(crate) fn new(description: &str) -> JavaLocatorError {
28-
JavaLocatorError {
29-
description: description.to_string(),
30-
}
27+
pub(crate) fn new(description: String) -> JavaLocatorError {
28+
JavaLocatorError { description }
3129
}
3230
}
3331

@@ -45,18 +43,24 @@ impl Error for JavaLocatorError {
4543

4644
impl From<std::io::Error> for JavaLocatorError {
4745
fn from(err: std::io::Error) -> JavaLocatorError {
48-
JavaLocatorError { description: format!("{:?}", err) }
46+
JavaLocatorError {
47+
description: format!("{:?}", err),
48+
}
4949
}
5050
}
5151

52-
impl From<string::FromUtf8Error> for JavaLocatorError {
53-
fn from(err: string::FromUtf8Error) -> JavaLocatorError {
54-
JavaLocatorError { description: format!("{:?}", err) }
52+
impl From<std::str::Utf8Error> for JavaLocatorError {
53+
fn from(err: std::str::Utf8Error) -> JavaLocatorError {
54+
JavaLocatorError {
55+
description: format!("{:?}", err),
56+
}
5557
}
5658
}
5759

5860
impl From<glob::PatternError> for JavaLocatorError {
5961
fn from(err: glob::PatternError) -> JavaLocatorError {
60-
JavaLocatorError { description: format!("{:?}", err) }
62+
JavaLocatorError {
63+
description: format!("{:?}", err),
64+
}
6165
}
62-
}
66+
}

src/lib.rs

Lines changed: 104 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -91,53 +91,11 @@ use std::env;
9191
use std::path::PathBuf;
9292
use std::process::Command;
9393

94+
use errors::{JavaLocatorError, Result};
9495
use glob::{glob, Pattern};
95-
use lazy_static::lazy_static;
9696

9797
pub mod errors;
9898

99-
const WINDOWS: &'static str = "windows";
100-
const MACOS: &'static str = "macos";
101-
const ANDROID: &'static str = "android";
102-
const UNIX: &'static str = "unix";
103-
104-
lazy_static! {
105-
static ref TARGET_OS: String = {
106-
let target_os_res = env::var("CARGO_CFG_TARGET_OS");
107-
let tos = target_os_res.as_ref().map(|x| &**x).unwrap_or_else(|_| {
108-
if cfg!(windows) {
109-
WINDOWS
110-
} else if cfg!(target_os = "macos") {
111-
MACOS
112-
} else if cfg!(target_os = "android") {
113-
ANDROID
114-
} else {
115-
UNIX
116-
}
117-
});
118-
119-
tos.to_string()
120-
};
121-
}
122-
123-
fn is_windows() -> bool {
124-
&*TARGET_OS == WINDOWS
125-
}
126-
127-
fn is_macos() -> bool {
128-
&*TARGET_OS == MACOS
129-
}
130-
131-
#[allow(dead_code)]
132-
fn is_android() -> bool {
133-
&*TARGET_OS == ANDROID
134-
}
135-
136-
#[allow(dead_code)]
137-
fn is_unix() -> bool {
138-
&*TARGET_OS == UNIX
139-
}
140-
14199
/// Returns the name of the jvm dynamic library:
142100
///
143101
/// * libjvm.so for Linux
@@ -146,9 +104,9 @@ fn is_unix() -> bool {
146104
///
147105
/// * jvm.dll for Windows
148106
pub fn get_jvm_dyn_lib_file_name() -> &'static str {
149-
if is_windows() {
107+
if cfg!(target_os = "windows") {
150108
"jvm.dll"
151-
} else if is_macos() {
109+
} else if cfg!(target_os = "macos") {
152110
"libjvm.dylib"
153111
} else {
154112
"libjvm.so"
@@ -160,60 +118,102 @@ pub fn get_jvm_dyn_lib_file_name() -> &'static str {
160118
/// If `JAVA_HOME` env var is defined, the function returns it without any checks whether the var points to a valid directory or not.
161119
///
162120
/// If `JAVA_HOME` is not defined, the function tries to locate it using the `java` executable.
163-
pub fn locate_java_home() -> errors::Result<String> {
121+
pub fn locate_java_home() -> Result<String> {
164122
match &env::var("JAVA_HOME") {
165123
Ok(s) if s.is_empty() => do_locate_java_home(),
166124
Ok(java_home_env_var) => Ok(java_home_env_var.clone()),
167125
Err(_) => do_locate_java_home(),
168126
}
169127
}
170128

171-
fn do_locate_java_home() -> errors::Result<String> {
172-
// Prepare the command depending on the host
173-
let command_str = if is_windows() {
174-
"where"
175-
} else if is_macos() {
176-
"/usr/libexec/java_home"
177-
} else {
178-
"which"
179-
};
129+
#[cfg(target_os = "windows")]
130+
fn do_locate_java_home() -> Result<String> {
131+
let output = Command::new("where")
132+
.arg("java")
133+
.output()
134+
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `where` ({e})")))?;
180135

181-
let mut command = Command::new(command_str);
136+
let java_exec_path_raw = std::str::from_utf8(&output.stdout)?;
137+
java_exec_path_validation(java_exec_path_raw)?;
182138

183-
if !is_macos() {
184-
command.arg("java");
139+
// Windows will return multiple lines if there are multiple `java` in the PATH.
140+
let paths_found = java_exec_path_raw.lines().count();
141+
if paths_found > 1 {
142+
eprintln!("WARNING: java_locator found {paths_found} possible java locations. Using the first one. To silence this warning set JAVA_HOME env var.")
185143
}
186144

187-
let output = command.output().map_err(|error| {
188-
let message = format!(
189-
"Command '{}' is not found in the system PATH ({})",
190-
command_str, error
191-
);
192-
errors::JavaLocatorError::new(&message)
193-
})?;
194-
let java_exec_path = String::from_utf8(output.stdout).map(|jp| {
195-
let mut lines: Vec<&str> = jp.lines().collect();
196-
if lines.len() > 1 {
197-
println!(
198-
"WARNING: java_locator found {} possible java locations: {}. Using the last one.",
199-
lines.len(),
200-
lines.join(", ")
201-
);
202-
lines.remove(lines.len() - 1).to_string()
203-
} else {
204-
jp
205-
}
206-
})?;
145+
let java_exec_path = java_exec_path_raw
146+
.lines()
147+
// The first line is the one that would be run, so take just that line.
148+
.next()
149+
.expect("gauranteed to have at least one line by java_exec_path_validation")
150+
.trim();
151+
152+
let mut home_path = follow_symlinks(java_exec_path);
153+
154+
home_path.pop();
155+
home_path.pop();
156+
157+
home_path
158+
.into_os_string()
159+
.into_string()
160+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
161+
}
207162

208-
// Return early in case that the java executable is not found
209-
if java_exec_path.is_empty() {
210-
Err(errors::JavaLocatorError::new(
211-
"Java is not installed or not added in the system PATH",
212-
))?
163+
#[cfg(target_os = "macos")]
164+
fn do_locate_java_home() -> Result<String> {
165+
let output = Command::new("/usr/libexec/java_home")
166+
.output()
167+
.map_err(|e| {
168+
JavaLocatorError::new(format!(
169+
"Failed to run command `/usr/libexec/java_home` ({e})"
170+
))
171+
})?;
172+
173+
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
174+
175+
java_exec_path_validation(java_exec_path)?;
176+
let home_path = follow_symlinks(java_exec_path);
177+
178+
home_path
179+
.into_os_string()
180+
.into_string()
181+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
182+
}
183+
184+
#[cfg(not(any(target_os = "windows", target_os = "macos")))] // Unix
185+
fn do_locate_java_home() -> Result<String> {
186+
let output = Command::new("which")
187+
.arg("java")
188+
.output()
189+
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `which` ({e})")))?;
190+
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
191+
192+
java_exec_path_validation(java_exec_path)?;
193+
let mut home_path = follow_symlinks(java_exec_path);
194+
195+
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
196+
home_path.pop();
197+
home_path.pop();
198+
199+
home_path
200+
.into_os_string()
201+
.into_string()
202+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
203+
}
204+
205+
fn java_exec_path_validation(path: &str) -> Result<()> {
206+
if path.is_empty() {
207+
return Err(JavaLocatorError::new(
208+
"Java is not installed or not in the system PATH".into(),
209+
));
213210
}
214211

215-
let mut test_path = PathBuf::from(java_exec_path.trim());
212+
Ok(())
213+
}
216214

215+
fn follow_symlinks(path: &str) -> PathBuf {
216+
let mut test_path = PathBuf::from(path);
217217
while let Ok(path) = test_path.read_link() {
218218
test_path = if path.is_absolute() {
219219
path
@@ -223,55 +223,39 @@ fn do_locate_java_home() -> errors::Result<String> {
223223
test_path
224224
};
225225
}
226-
227-
if !is_macos() {
228-
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
229-
test_path.pop();
230-
test_path.pop();
231-
}
232-
233-
match test_path.to_str() {
234-
Some(s) => Ok(String::from(s)),
235-
None => Err(errors::JavaLocatorError::new(&format!(
236-
"Could not convert path {:?} to String",
237-
test_path
238-
))),
239-
}
226+
test_path
240227
}
241228

242229
/// Returns the path that contains the `libjvm.so` (or `jvm.dll` in windows).
243-
pub fn locate_jvm_dyn_library() -> errors::Result<String> {
244-
let jvm_dyn_lib_file_name = if is_windows() { "jvm.dll" } else { "libjvm.*" };
245-
246-
locate_file(jvm_dyn_lib_file_name)
230+
pub fn locate_jvm_dyn_library() -> Result<String> {
231+
if cfg!(target_os = "windows") {
232+
locate_file("jvm.dll")
233+
} else {
234+
locate_file("libjvm.*")
235+
}
247236
}
248237

249238
/// Returns the path that contains the file with the provided name.
250239
///
251240
/// This function argument can be a wildcard.
252-
pub fn locate_file(file_name: &str) -> errors::Result<String> {
241+
pub fn locate_file(file_name: &str) -> Result<String> {
253242
// Find the JAVA_HOME
254243
let java_home = locate_java_home()?;
255244

256245
let query = format!("{}/**/{}", Pattern::escape(&java_home), file_name);
257246

258-
let paths_vec: Vec<String> = glob(&query)?
259-
.filter_map(Result::ok)
260-
.map(|path_buf| {
261-
let mut pb = path_buf.clone();
262-
pb.pop();
263-
pb.to_str().unwrap_or("").to_string()
264-
})
265-
.filter(|s: &String| !s.is_empty())
266-
.collect();
267-
268-
if paths_vec.is_empty() {
269-
Err(errors::JavaLocatorError::new(&format!(
270-
"Could not find the {} library in any subdirectory of {}",
271-
file_name, java_home
272-
)))
273-
} else {
274-
Ok(paths_vec[0].clone())
247+
let path = glob(&query)?.filter_map(|x| x.ok()).next().ok_or_else(|| {
248+
JavaLocatorError::new(format!(
249+
"Could not find the {file_name} library in any subdirectory of {java_home}",
250+
))
251+
})?;
252+
253+
let parent_path = path.parent().unwrap();
254+
match parent_path.to_str() {
255+
Some(parent_path) => Ok(parent_path.to_owned()),
256+
None => Err(JavaLocatorError::new(format!(
257+
"Java path {parent_path:?} is invalid utf8"
258+
))),
275259
}
276260
}
277261

src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
// limitations under the License.
1414
use docopt::Docopt;
1515

16-
use java_locator;
17-
18-
const USAGE: &'static str = "
16+
const USAGE: &str = "
1917
java-locator locates the active Java installation in the host.
2018
2119
Usage:

0 commit comments

Comments
 (0)