Skip to content

Commit 7af3cc5

Browse files
committed
Remove lazy_static + cleanup lib.rs
1 parent 0a2b154 commit 7af3cc5

File tree

4 files changed

+126
-134
lines changed

4 files changed

+126
-134
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: 109 additions & 118 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,11 +104,16 @@ 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+
#[cfg(target_os = "windows")]
108+
{
150109
"jvm.dll"
151-
} else if is_macos() {
110+
}
111+
#[cfg(target_os = "macos")]
112+
{
152113
"libjvm.dylib"
153-
} else {
114+
}
115+
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
116+
{
154117
"libjvm.so"
155118
}
156119
}
@@ -160,60 +123,103 @@ pub fn get_jvm_dyn_lib_file_name() -> &'static str {
160123
/// If `JAVA_HOME` env var is defined, the function returns it without any checks whether the var points to a valid directory or not.
161124
///
162125
/// 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> {
126+
pub fn locate_java_home() -> Result<String> {
164127
match &env::var("JAVA_HOME") {
165128
Ok(s) if s.is_empty() => do_locate_java_home(),
166129
Ok(java_home_env_var) => Ok(java_home_env_var.clone()),
167130
Err(_) => do_locate_java_home(),
168131
}
169132
}
170133

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-
};
134+
#[cfg(target_os = "windows")]
135+
fn do_locate_java_home() -> Result<String> {
136+
let output = Command::new("where")
137+
.arg("java")
138+
.output()
139+
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `where` ({e})")))?;
140+
141+
let java_exec_path = std::str::from_utf8(&output.stdout)?
142+
// Windows will return multiple lines if there are multiple `java` in the PATH.
143+
.lines()
144+
// The first line is the one that would be run, so take just that line.
145+
.next()
146+
.unwrap()
147+
.trim();
148+
149+
if java_exec_path.is_empty() {
150+
return Err(JavaLocatorError::new(
151+
"Java is not installed or not in the system PATH".into(),
152+
));
153+
}
154+
155+
let mut home_path = follow_symlinks(java_exec_path);
156+
157+
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
158+
home_path.pop();
159+
home_path.pop();
160+
161+
home_path
162+
.into_os_string()
163+
.into_string()
164+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
165+
}
166+
167+
#[cfg(target_os = "macos")]
168+
fn do_locate_java_home() -> Result<String> {
169+
let output = Command::new("/usr/libexec/java_home")
170+
.output()
171+
.map_err(|e| {
172+
JavaLocatorError::new(format!(
173+
"Failed to run command `/usr/libexec/java_home` ({e})"
174+
))
175+
})?;
180176

181-
let mut command = Command::new(command_str);
177+
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
182178

183-
if !is_macos() {
184-
command.arg("java");
179+
if java_exec_path.is_empty() {
180+
return Err(JavaLocatorError::new(
181+
"Java is not installed or not in the system PATH".into(),
182+
));
185183
}
186184

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

208-
// Return early in case that the java executable is not found
209202
if java_exec_path.is_empty() {
210-
Err(errors::JavaLocatorError::new(
211-
"Java is not installed or not added in the system PATH",
212-
))?
203+
return Err(JavaLocatorError::new(
204+
"Java is not installed or not in the system PATH".into(),
205+
));
213206
}
214207

215-
let mut test_path = PathBuf::from(java_exec_path.trim());
208+
let mut home_path = follow_symlinks(java_exec_path);
209+
210+
// Here we should have found ourselves in a directory like /usr/lib/jvm/java-8-oracle/jre/bin/java
211+
home_path.pop();
212+
home_path.pop();
213+
214+
home_path
215+
.into_os_string()
216+
.into_string()
217+
.map_err(|path| JavaLocatorError::new(format!("Java path {path:?} is invalid utf8")))
218+
}
216219

220+
// Its not clear to me which systems need this so for now its run on all systems.
221+
fn follow_symlinks(path: &str) -> PathBuf {
222+
let mut test_path = PathBuf::from(path);
217223
while let Ok(path) = test_path.read_link() {
218224
test_path = if path.is_absolute() {
219225
path
@@ -223,55 +229,40 @@ fn do_locate_java_home() -> errors::Result<String> {
223229
test_path
224230
};
225231
}
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-
}
232+
test_path
240233
}
241234

242235
/// 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.*" };
236+
pub fn locate_jvm_dyn_library() -> Result<String> {
237+
#[cfg(target_os = "windows")]
238+
let jvm_dyn_lib_file_name = "jvm.dll";
239+
#[cfg(not(target_os = "windows"))]
240+
let jvm_dyn_lib_file_name = "libjvm.*";
245241

246242
locate_file(jvm_dyn_lib_file_name)
247243
}
248244

249245
/// Returns the path that contains the file with the provided name.
250246
///
251247
/// This function argument can be a wildcard.
252-
pub fn locate_file(file_name: &str) -> errors::Result<String> {
248+
pub fn locate_file(file_name: &str) -> Result<String> {
253249
// Find the JAVA_HOME
254250
let java_home = locate_java_home()?;
255251

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

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())
254+
let path = glob(&query)?.filter_map(|x| x.ok()).next().ok_or_else(|| {
255+
JavaLocatorError::new(format!(
256+
"Could not find the {file_name} library in any subdirectory of {java_home}",
257+
))
258+
})?;
259+
260+
let parent_path = path.parent().unwrap();
261+
match parent_path.to_str() {
262+
Some(parent_path) => Ok(parent_path.to_owned()),
263+
None => Err(JavaLocatorError::new(format!(
264+
"Java path {parent_path:?} is invalid utf8"
265+
))),
275266
}
276267
}
277268

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)