mc_launcher/java/
mod.rs

1use std::path::{Path, PathBuf};
2use error::{JavaError, JavaErrorKind, Result};
3use version::JavaVersion;
4use crate::{os::{process::ProgramPathFinder, OsAbstraction}, utils::choice_by_os};
5
6pub mod error;
7pub mod version;
8
9pub const JAVA_SEPARATOR: &str = if cfg!(target_os = "windows") { ";" } else { ":" };
10
11#[derive(Debug, Clone)]
12pub struct Java {
13  base_path: PathBuf,
14  version: JavaVersion
15}
16
17impl TryFrom<String> for Java {
18  type Error = JavaError;
19
20  fn try_from(value: String) -> Result<Self> {
21    Self::new(Path::new(&value).to_path_buf())
22  }
23}
24
25impl Java {
26  pub fn new(base_path: PathBuf) -> Result<Self> {
27    if !base_path.is_dir() {
28      return Err(JavaError::new(JavaErrorKind::NotFound));
29    }
30
31    let version = JavaVersion::get_verison(&base_path)?;
32
33    Ok(Self {
34      base_path,
35      version
36    })
37  }
38
39  /// Trying to find Java on the PC
40  pub fn find() -> Result<Self> {
41    // if JAVA_HOME provided
42    if let Ok(path) = std::env::var("JAVA_HOME") {
43      return Java::try_from(path);
44    }
45
46    // if not - we tryna find java in system
47
48    // caching error instance
49    let java_err = JavaError::new(JavaErrorKind::InvalidJavaFolderStructure);
50
51    let path = OsAbstraction::find_path("java")?;
52
53    let parent = path.ancestors()
54      .next().ok_or(java_err.clone())?
55      .file_name().ok_or(java_err.clone())?
56      .to_str().ok_or(java_err.clone())?;
57
58    if parent != "bin" {
59      return Err(java_err);
60    }
61
62    Self::new(path)
63  }
64
65  pub fn get_java(&self) -> Result<PathBuf> {
66    let path = self.base_path
67      .join("bin")
68      .join(choice_by_os("java", "java.exe"));
69
70    if !path.is_file() {
71      return Err(JavaError::new(JavaErrorKind::NotFound))
72    }
73
74    Ok(path)
75  }
76
77  pub fn get_javaw(&self) -> Result<PathBuf> {
78    let path = self.base_path
79      .join("bin")
80      // linux/macos doesn't have javaw, so we just return java instead
81      .join(choice_by_os("java", "javaw.exe"));
82
83    if !path.is_file() {
84      return Err(JavaError::new(JavaErrorKind::NotFound))
85    }
86
87    Ok(path)
88  }
89
90  pub fn version(&self) -> &JavaVersion {
91    &self.version
92  }
93
94  /// Checks that Java client is STRICTLY equal to needed_version
95  ///
96  /// Example
97  /// ```rs
98  /// let client = Java::find()?;
99  /// client.is_version_equal(16)?;
100  /// ```
101  pub fn is_version_equal(&self, needed_version: u8) -> Result<()> {
102    if self.version.main_version() != needed_version {
103      return Err(JavaError::new(JavaErrorKind::DifferentVersion))
104    }
105
106    Ok(())
107  }
108
109  /// Checks if Java client is higher or equal to needed_version
110  ///
111  /// Example
112  /// ```rs
113  /// let client = Java::find()?;
114  /// client.is_version_at_least(16)?;
115  /// ```
116  pub fn is_version_at_least(&self, needed_version: u8) -> Result<()> {
117    if self.version.main_version() != needed_version {
118      return Err(JavaError::new(JavaErrorKind::DifferentVersion))
119    }
120
121    Ok(())
122  }
123}