lighty_java/
jre_downloader.rs

1
2use std::io::Cursor;
3use std::path::{Path, PathBuf};
4use crate::errors::{JreError, JreResult};
5use path_absolutize::Absolutize;
6use tokio::fs;
7
8use lighty_core::system::{ OperatingSystem, OS};
9use lighty_core::download::{download_file};
10use lighty_core::extract::{tar_gz_extract, zip_extract} ;
11
12use super::JavaDistribution;
13
14/// Find java binary in JRE folder
15pub async fn find_java_binary(
16    runtimes_folder: &Path,
17    jre_distribution: &JavaDistribution,
18    jre_version: &u32,
19) -> JreResult<PathBuf> {
20    let runtime_path =
21        runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));
22
23    // Find JRE in runtime folder
24    let mut files = fs::read_dir(&runtime_path).await?;
25
26    if let Some(jre_folder) = files.next_entry().await? {
27        let folder_path = jre_folder.path();
28
29        let java_binary = match OS {
30            OperatingSystem::WINDOWS => folder_path.join("bin").join("java.exe"),
31            OperatingSystem::OSX => folder_path
32                .join("Contents")
33                .join("Home")
34                .join("bin")
35                .join("java"),
36            _ => folder_path.join("bin").join("java"),
37        };
38
39        if java_binary.exists() {
40            // Check if the binary has execution permissions on linux and macOS
41            #[cfg(unix)]
42            {
43                use std::os::unix::fs::PermissionsExt;
44
45                let metadata = fs::metadata(&java_binary).await?;
46
47                if metadata.permissions().mode() & 0o111 == 0 {
48                    // try to change permissions
49                    let mut permissions = metadata.permissions();
50                    permissions.set_mode(0o755);
51                    fs::set_permissions(&java_binary, permissions).await?;
52                }
53            }
54
55            return Ok(java_binary.absolutize()?.to_path_buf());
56        }
57    }
58
59    Err(JreError::NotFound {
60        path: runtime_path.display().to_string(),
61    })
62}
63
64/// Download specific JRE to runtimes
65pub async fn jre_download<F>(
66    runtimes_folder: &Path,
67    jre_distribution: &JavaDistribution,
68    jre_version: &u32,
69    on_progress: F,
70) -> JreResult<PathBuf>
71where
72    F: Fn(u64, u64),
73{
74    let runtime_path =
75        runtimes_folder.join(format!("{}_{}", jre_distribution.get_name(), jre_version));
76
77    if runtime_path.exists() {
78        fs::remove_dir_all(&runtime_path).await?;
79    }
80    fs::create_dir_all(&runtime_path).await?;
81
82    let url = jre_distribution.get_url(jre_version)
83        .map_err(|e| JreError::Download(format!("Failed to get URL: {}", e)))?;
84
85    let retrieved_bytes = download_file(&url, on_progress).await
86        .map_err(|e| JreError::Download(format!("Download failed: {}", e)))?;
87
88    let cursor = Cursor::new(&retrieved_bytes[..]);
89
90    match OS {
91        OperatingSystem::WINDOWS => {
92            zip_extract(cursor, runtime_path.as_path()).await
93                .map_err(|e| JreError::Extraction(format!("ZIP extraction failed: {}", e)))?;
94        }
95        OperatingSystem::LINUX | OperatingSystem::OSX => {
96            tar_gz_extract(cursor, runtime_path.as_path()).await
97                .map_err(|e| JreError::Extraction(format!("TAR.GZ extraction failed: {}", e)))?;
98        }
99        OperatingSystem::UNKNOWN => {
100            return Err(JreError::UnsupportedOS);
101        }
102    }
103
104    // Find JRE afterwards
105    find_java_binary(runtimes_folder, jre_distribution, jre_version).await
106}