Skip to content

Commit

Permalink
java checker and finder
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlan404 committed Jun 22, 2024
1 parent 225ef10 commit 4985d56
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 0 deletions.
Binary file added res/java/JavaInfo.class
Binary file not shown.
23 changes: 23 additions & 0 deletions res/java/JavaInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
public final class JavaInfo {
private static final String[] CHECKED_PROPERTIES = new String[] {
"os.arch",
"java.version",
"java.vendor"
};

public static void main(String[] args) {
int returnCode = 0;

for (String key : CHECKED_PROPERTIES) {
String property = System.getProperty(key);

if (property != null) {
System.out.println(key + "=" + property);
} else {
returnCode = 1;
}
}

System.exit(returnCode);
}
}
1 change: 1 addition & 0 deletions res/java/compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
javac -target 7 -source 7 -Xlint:deprecation -Xlint:unchecked JavaInfo.java
49 changes: 49 additions & 0 deletions src/api/tools/java/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::{collections::HashMap, path::Path, process::Command};

use super::{extract_java_majorminor_version, JavaInstallation, JAVA_BIN};

pub fn check_java(path: &Path) -> Option<JavaInstallation> {

Check warning on line 5 in src/api/tools/java/check.rs

View workflow job for this annotation

GitHub Actions / clippy

function `check_java` is never used

warning: function `check_java` is never used --> src/api/tools/java/check.rs:5:8 | 5 | pub fn check_java(path: &Path) -> Option<JavaInstallation> { | ^^^^^^^^^^
let Ok(path) = std::fs::canonicalize(path) else {
return None;
};

let java = if path.file_name()?.to_str()? != JAVA_BIN {
path.join(JAVA_BIN)
} else {
path.clone()
};

Check warning on line 14 in src/api/tools/java/check.rs

View workflow job for this annotation

GitHub Actions / clippy

unnecessary `!=` operation

warning: unnecessary `!=` operation --> src/api/tools/java/check.rs:10:16 | 10 | let java = if path.file_name()?.to_str()? != JAVA_BIN { | ________________^ 11 | | path.join(JAVA_BIN) 12 | | } else { 13 | | path.clone() 14 | | }; | |_____^ | = help: change to `==` and swap the blocks of the `if`/`else` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else = note: `-W clippy::if-not-else` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::if_not_else)]`

if !java.exists() {
return None;
};

let tempdir = tempfile::tempdir().ok()?.into_path();
let file_path = tempdir.join("JavaInfo.class");
std::fs::write(&file_path, include_bytes!("../../../../res/java/JavaInfo.class")).ok()?;

let output = Command::new(&java)
.arg("-cp")
.arg(file_path.parent().unwrap())
.arg("JavaInfo")
.output()
.ok()?;

let stdout = String::from_utf8_lossy(&output.stdout);

let mut info = HashMap::new();

for line in stdout.lines() {
let Some((key, value)) = line.split_once('=') else {
continue;
};

info.insert(key.to_owned(), value.to_owned());
}

Some(JavaInstallation {
path,
version: extract_java_majorminor_version(info.get("java.version")?).ok()?.1,
architecture: info.get("os.arch")?.clone(),
vendor: info.get("java.vendor")?.clone(),
})
}
83 changes: 83 additions & 0 deletions src/api/tools/java/find.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::collections::HashMap;
use std::env;
use std::path::PathBuf;
use std::collections::HashSet;

enum JavaLocation {

Check warning on line 6 in src/api/tools/java/find.rs

View workflow job for this annotation

GitHub Actions / clippy

enum `JavaLocation` is never used

warning: enum `JavaLocation` is never used --> src/api/tools/java/find.rs:6:6 | 6 | enum JavaLocation { | ^^^^^^^^^^^^
Path(&'static str),
PathSubpathAndWildcard(&'static str, Vec<&'static str>),
PathWildcard(&'static str, Vec<&'static str>),
}

fn env_paths() -> HashSet<PathBuf> {

Check warning on line 12 in src/api/tools/java/find.rs

View workflow job for this annotation

GitHub Actions / clippy

function `env_paths` is never used

warning: function `env_paths` is never used --> src/api/tools/java/find.rs:12:4 | 12 | fn env_paths() -> HashSet<PathBuf> { | ^^^^^^^^^
let paths =
env::var("PATH").map(|x| env::split_paths(&x).collect::<HashSet<_>>());
paths.unwrap_or_else(|_| HashSet::new())
}

pub(super) fn collect_possible_java_paths() -> HashSet<PathBuf> {

Check warning on line 18 in src/api/tools/java/find.rs

View workflow job for this annotation

GitHub Actions / clippy

function `collect_possible_java_paths` is never used

warning: function `collect_possible_java_paths` is never used --> src/api/tools/java/find.rs:18:15 | 18 | pub(super) fn collect_possible_java_paths() -> HashSet<PathBuf> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
let locations = &get_possible_java_locations()[env::consts::OS];

let mut paths = HashSet::new();

paths.extend(env_paths());

for loc in locations {
match loc {
JavaLocation::Path(path) => {
paths.insert(path.into());
}
JavaLocation::PathWildcard(base, extras) => {
if let Ok(entries) = PathBuf::from(base).read_dir() {
for entry in entries.flatten() {
for extra in extras {
paths.insert(entry.path().join(extra));
}
}
}
}
JavaLocation::PathSubpathAndWildcard(base, extras) => {
paths.insert(base.into());
for extra in extras {
paths.insert(PathBuf::from(base).join(extra));
}
if let Ok(entries) = PathBuf::from(base).read_dir() {
for entry in entries.flatten() {
for extra in extras {
paths.insert(entry.path().join(extra));
}
}
}
}
}
}

paths
}

fn get_possible_java_locations() -> HashMap<&'static str, Vec<JavaLocation>> {

Check warning on line 58 in src/api/tools/java/find.rs

View workflow job for this annotation

GitHub Actions / clippy

function `get_possible_java_locations` is never used

warning: function `get_possible_java_locations` is never used --> src/api/tools/java/find.rs:58:4 | 58 | fn get_possible_java_locations() -> HashMap<&'static str, Vec<JavaLocation>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
HashMap::from([
("windows", vec![
JavaLocation::PathWildcard(r"C:/Program Files/Java", vec!["bin"]),
JavaLocation::PathWildcard(r"C:/Program Files (x86)/Java", vec!["bin"]),
JavaLocation::PathWildcard(r"C:\Program Files\Eclipse Adoptium", vec!["bin"]),
JavaLocation::PathWildcard(r"C:\Program Files (x86)\Eclipse Adoptium", vec!["bin"]),
]),
("macos", vec![
JavaLocation::Path(r"/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java"),
JavaLocation::Path(r"/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home"),
JavaLocation::Path(r"/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands"),
JavaLocation::PathWildcard(r"/Library/Java/JavaVirtualMachines/", vec![r"Contents/Home/bin"]),
]),
("linux", vec![
JavaLocation::PathSubpathAndWildcard(r"/usr", vec!["jre/bin", "bin"]),
JavaLocation::PathSubpathAndWildcard(r"/usr/java", vec!["jre/bin", "bin"]),
JavaLocation::PathSubpathAndWildcard(r"/usr/lib/jvm", vec!["jre/bin", "bin"]),
JavaLocation::PathSubpathAndWildcard(r"/usr/lib64/jvm", vec!["jre/bin", "bin"]),
JavaLocation::PathSubpathAndWildcard(r"/opt/jdk", vec!["jre/bin", "bin"]),
JavaLocation::PathSubpathAndWildcard(r"/opt/jdks", vec!["jre/bin", "bin"]),
])
])
}


44 changes: 44 additions & 0 deletions src/api/tools/java/installation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::path::PathBuf;

use anyhow::{anyhow, Result};

use super::JavaVersion;

pub struct JavaInstallation {

Check warning on line 7 in src/api/tools/java/installation.rs

View workflow job for this annotation

GitHub Actions / clippy

struct `JavaInstallation` is never constructed

warning: struct `JavaInstallation` is never constructed --> src/api/tools/java/installation.rs:7:12 | 7 | pub struct JavaInstallation { | ^^^^^^^^^^^^^^^^
pub path: PathBuf,
pub version: JavaVersion,
pub architecture: String,
pub vendor: String,
}

/// Extract major/minor version from a java version string
/// Gets the minor version or an error, and assumes 1 for major version if it could not find
/// "1.8.0_361" -> (1, 8)

Check warning on line 16 in src/api/tools/java/installation.rs

View workflow job for this annotation

GitHub Actions / clippy

item in documentation is missing backticks

warning: item in documentation is missing backticks --> src/api/tools/java/installation.rs:16:6 | 16 | /// "1.8.0_361" -> (1, 8) | ^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown help: try | 16 | /// "`1.8.0_361`" -> (1, 8) | ~~~~~~~~~~~
/// "20" -> (1, 20)
pub fn extract_java_majorminor_version(

Check warning on line 18 in src/api/tools/java/installation.rs

View workflow job for this annotation

GitHub Actions / clippy

function `extract_java_majorminor_version` is never used

warning: function `extract_java_majorminor_version` is never used --> src/api/tools/java/installation.rs:18:8 | 18 | pub fn extract_java_majorminor_version( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
version: &str,
) -> Result<(u32, u32)> {
let mut split = version.split('.');
let major_opt = split.next();

let mut major;
// Try minor. If doesn't exist, in format like "20" so use major
let mut minor = if let Some(minor) = split.next() {
major = major_opt.unwrap_or("1").parse::<u32>()?;
minor.parse::<u32>()?
} else {
// Formatted like "20", only one value means that is minor version
major = 1;
major_opt
.ok_or_else(|| anyhow!("Invalid JRE version"))?
.parse::<u32>()?
};

// Java start should always be 1. If more than 1, it is formatted like "17.0.1.2" and starts with minor version
if major > 1 {
minor = major;
major = 1;
}

Ok((major, minor))
}
14 changes: 14 additions & 0 deletions src/api/tools/java/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
pub const JAVA_BIN: &str = "java";

Check warning on line 1 in src/api/tools/java/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

constant `JAVA_BIN` is never used

warning: constant `JAVA_BIN` is never used --> src/api/tools/java/mod.rs:1:11 | 1 | pub const JAVA_BIN: &str = "java"; | ^^^^^^^^
pub type JavaVersion = u32;

Check warning on line 2 in src/api/tools/java/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

type alias `JavaVersion` is never used

warning: type alias `JavaVersion` is never used --> src/api/tools/java/mod.rs:2:10 | 2 | pub type JavaVersion = u32; | ^^^^^^^^^^^

mod installation;
mod find;
mod check;
pub use installation::*;
pub use find::*;

Check warning on line 8 in src/api/tools/java/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

glob import doesn't reexport anything with visibility `pub` because no imported item is public enough

warning: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough --> src/api/tools/java/mod.rs:8:9 | 8 | pub use find::*; | ^^^^^^^ | note: the most public imported item is `pub(self)` --> src/api/tools/java/mod.rs:8:9 | 8 | pub use find::*; | ^^^^^^^ = help: reduce the glob import's visibility or increase visibility of imported items
pub use check::*;

pub fn get_java_installations() -> Vec<JavaInstallation> {

Check warning on line 11 in src/api/tools/java/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

function `get_java_installations` is never used

warning: function `get_java_installations` is never used --> src/api/tools/java/mod.rs:11:8 | 11 | pub fn get_java_installations() -> Vec<JavaInstallation> { | ^^^^^^^^^^^^^^^^^^^^^^
let paths = collect_possible_java_paths();

paths.into_iter().filter_map(|path| check_java(&path)).collect()
}

0 comments on commit 4985d56

Please sign in to comment.