Skip to content

Commit 09ee779

Browse files
committed
Remove lazy_static + cleanup lib.rs
1 parent 0a2b154 commit 09ee779

File tree

4 files changed

+121
-135
lines changed

4 files changed

+121
-135
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 & 119 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,103 @@ 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})")))?;
135+
136+
let java_exec_path = std::str::from_utf8(&output.stdout)?
137+
// Windows will return multiple lines if there are multiple `java` in the PATH.
138+
.lines()
139+
// The first line is the one that would be run, so take just that line.
140+
.next()
141+
.unwrap()
142+
.trim();
180143

181-
let mut command = Command::new(command_str);
144+
if java_exec_path.is_empty() {
145+
return Err(JavaLocatorError::new(
146+
"Java is not installed or not in the system PATH".into(),
147+
));
148+
}
149+
150+
let mut home_path = follow_symlinks(java_exec_path);
151+
152+
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
153+
home_path.pop();
154+
home_path.pop();
155+
156+
home_path
157+
.into_os_string()
158+
.into_string()
159+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
160+
}
182161

183-
if !is_macos() {
184-
command.arg("java");
162+
#[cfg(target_os = "macos")]
163+
fn do_locate_java_home() -> Result<String> {
164+
let output = Command::new("/usr/libexec/java_home")
165+
.output()
166+
.map_err(|e| {
167+
JavaLocatorError::new(format!(
168+
"Failed to run command `/usr/libexec/java_home` ({e})"
169+
))
170+
})?;
171+
172+
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
173+
174+
if java_exec_path.is_empty() {
175+
return Err(JavaLocatorError::new(
176+
"Java is not installed or not in the system PATH".into(),
177+
));
185178
}
186179

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-
})?;
180+
let home_path = follow_symlinks(java_exec_path);
181+
182+
home_path
183+
.into_os_string()
184+
.into_string()
185+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
186+
}
187+
188+
// TODO: double check this
189+
#[cfg(not(any(target_os = "windows", target_os = "macos")))] // Unix
190+
fn do_locate_java_home() -> Result<String> {
191+
let output = Command::new("which")
192+
.arg("java")
193+
.output()
194+
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `which` ({e})")))?;
195+
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
207196

208-
// Return early in case that the java executable is not found
209197
if java_exec_path.is_empty() {
210-
Err(errors::JavaLocatorError::new(
211-
"Java is not installed or not added in the system PATH",
212-
))?
198+
return Err(JavaLocatorError::new(
199+
"Java is not installed or not in the system PATH".into(),
200+
));
213201
}
214202

215-
let mut test_path = PathBuf::from(java_exec_path.trim());
203+
let mut home_path = follow_symlinks(java_exec_path);
204+
205+
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
206+
home_path.pop();
207+
home_path.pop();
216208

209+
home_path
210+
.into_os_string()
211+
.into_string()
212+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
213+
}
214+
215+
// Its not clear to me which systems need this so for now its run on all systems.
216+
fn follow_symlinks(path: &str) -> PathBuf {
217+
let mut test_path = PathBuf::from(path);
217218
while let Ok(path) = test_path.read_link() {
218219
test_path = if path.is_absolute() {
219220
path
@@ -223,55 +224,39 @@ fn do_locate_java_home() -> errors::Result<String> {
223224
test_path
224225
};
225226
}
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-
}
227+
test_path
240228
}
241229

242230
/// 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)
231+
pub fn locate_jvm_dyn_library() -> Result<String> {
232+
if cfg!(target_os = "windows") {
233+
locate_file("jvm.dll")
234+
} else {
235+
locate_file("libjvm.*")
236+
}
247237
}
248238

249239
/// Returns the path that contains the file with the provided name.
250240
///
251241
/// This function argument can be a wildcard.
252-
pub fn locate_file(file_name: &str) -> errors::Result<String> {
242+
pub fn locate_file(file_name: &str) -> Result<String> {
253243
// Find the JAVA_HOME
254244
let java_home = locate_java_home()?;
255245

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

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())
248+
let path = glob(&query)?.filter_map(|x| x.ok()).next().ok_or_else(|| {
249+
JavaLocatorError::new(format!(
250+
"Could not find the {file_name} library in any subdirectory of {java_home}",
251+
))
252+
})?;
253+
254+
let parent_path = path.parent().unwrap();
255+
match parent_path.to_str() {
256+
Some(parent_path) => Ok(parent_path.to_owned()),
257+
None => Err(JavaLocatorError::new(format!(
258+
"Java path {parent_path:?} is invalid utf8"
259+
))),
275260
}
276261
}
277262

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)