summaryrefslogtreecommitdiffstats
path: root/src/launcher/jre.rs
blob: 2979c52a1a728ee6e49df0988c31c817fa63fa57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::path::{Path, PathBuf};
use log::{debug, info, warn};
use tokio::{fs, io};

mod arch;
mod manifest;

use arch::JRE_ARCH;
use manifest::JavaRuntimesManifest;
use crate::launcher::jre::manifest::JavaRuntimeManifest;
use super::constants;

pub struct JavaRuntimeRepository {
    home: PathBuf,
    manifest: JavaRuntimesManifest
}

impl JavaRuntimeRepository {
    pub async fn new(home: impl AsRef<Path>) -> Result<Self, JavaRuntimeError> {
        info!("Java runtime architecture is \"{}\".", JRE_ARCH);

        fs::create_dir_all(&home).await.map_err(|e| JavaRuntimeError::IO { what: "creating home directory", error: e })?;

        let manifest: JavaRuntimesManifest = reqwest::get(constants::URL_JRE_MANIFEST).await
            .map_err(|e| JavaRuntimeError::Download {
                what: "runtime manifest (all.json)",
                error: e
            })?.json().await
            .map_err(|e| JavaRuntimeError::Download {
                what: "runtime manifest (all.json)",
                error: e
            })?;

        Ok(JavaRuntimeRepository {
            home: home.as_ref().to_path_buf(),
            manifest
        })
    }

    pub async fn choose_runtime(&self, component: &str) -> Result<JavaRuntimeManifest, JavaRuntimeError> {
        let Some(runtime_components) = self.manifest.get(JRE_ARCH) else {
            return Err(JavaRuntimeError::UnsupportedArch(JRE_ARCH));
        };

        let Some(runtime_component) = runtime_components.get(component) else {
            return Err(JavaRuntimeError::UnsupportedComponent { arch: JRE_ARCH, component: component.to_owned() });
        };

        let Some(runtime) = runtime_component.iter().filter(|r| r.availability.progress == 100).next() else {
            if !runtime_components.is_empty() {
                warn!("Weird: the only java runtimes in {JRE_ARCH}.{component} has a progress of less than 100!");
            }

            return Err(JavaRuntimeError::UnsupportedComponent { arch: JRE_ARCH, component: component.to_owned() });
        };

        let Some(ref url) = runtime.manifest.url else {
            return Err(JavaRuntimeError::MalformedManifest);
        };

        debug!("Ensuring manifest for runtime {JRE_ARCH}.{component}: {url}");


        // hmm maybe

        todo!()
    }
}

#[derive(Debug)]
pub enum JavaRuntimeError {
    IO { what: &'static str, error: io::Error },
    Download { what: &'static str, error: reqwest::Error },
    UnsupportedArch(&'static str),
    UnsupportedComponent { arch: &'static str, component: String },
    MalformedManifest
}

impl Display for JavaRuntimeError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            JavaRuntimeError::IO { what, error } => write!(f, "i/o error ({}): {}", what, error),
            JavaRuntimeError::Download { what, error } => write!(f, "error downloading {}: {}", what, error),
            JavaRuntimeError::UnsupportedArch(arch) => write!(f, r#"unsupported architecture "{arch}""#),
            JavaRuntimeError::UnsupportedComponent { arch, component } => write!(f, r#"unsupported component "{component}" for architecture "{arch}""#),
            JavaRuntimeError::MalformedManifest => f.write_str("malformed runtime manifest (launcher bug?)"),
        }
    }
}

impl Error for JavaRuntimeError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            JavaRuntimeError::IO { error, .. } => Some(error),
            JavaRuntimeError::Download { error, .. } => Some(error),
            _ => None
        }
    }
}