use std::{path::PathBuf, str::FromStr}; use oneclient_events::{EventBus, GroupedProgressSession}; use oneclient_net::RequestClient; use crate::data::JavaPackage; use crate::error::JavaResult; mod adoptium; mod corretto; mod liberica; mod microsoft; mod zulu; pub use adoptium::AdoptiumRuntimeProvider; pub use corretto::CorrettoRuntimeProvider; pub use liberica::LibericaRuntimeProvider; pub use microsoft::MicrosoftRuntimeProvider; use serde::{Deserialize, Deserializer, Serialize}; pub use zulu::ZuluRuntimeProvider; pub fn runtime_providers() -> Vec> { vec![ Box::new(MicrosoftRuntimeProvider), Box::new(ZuluRuntimeProvider), Box::new(AdoptiumRuntimeProvider), Box::new(CorrettoRuntimeProvider), Box::new(LibericaRuntimeProvider), ] } // For making sure microsoft jdk provider is first #[must_use] pub fn default_vendor() -> JavaVendor { runtime_providers() .first() .expect("the provider list is never empty") .vendor() } #[async_trait::async_trait] pub trait JavaRuntimeProvider: Send + Sync { fn vendor(&self) -> JavaVendor; async fn list_packages( &self, major: Option, net: &RequestClient, ) -> JavaResult>; #[tracing::instrument(level = "debug", skip(self, net))] async fn latest_package_by_major( &self, major: u32, net: &RequestClient, ) -> JavaResult> { let packages = self.list_packages(Some(major), net).await?; Ok(packages.into_iter().find(|p| p.java_version.first() == Some(&major))) } #[tracing::instrument(level = "debug", skip_all)] async fn install_package( &self, package: &JavaPackage, net: &RequestClient, events: &EventBus, progress: Option<&GroupedProgressSession>, ) -> JavaResult { crate::install::install_package(package, net, events, progress).await } } #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum JavaVendor { Zulu, Corretto, Oracle, Microsoft, Adoptium, Liberica, OpenJDK, Other(String), } impl std::fmt::Display for JavaVendor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { JavaVendor::Zulu => f.write_str("Zulu"), JavaVendor::Adoptium => f.write_str("Temurin"), JavaVendor::Liberica => f.write_str("Liberica"), JavaVendor::Corretto => f.write_str("Corretto"), JavaVendor::Microsoft => f.write_str("Microsoft"), JavaVendor::Oracle => f.write_str("Oracle"), JavaVendor::OpenJDK => f.write_str("OpenJDK"), JavaVendor::Other(other) => f.write_str(other), } } } impl FromStr for JavaVendor { type Err = (); fn from_str(s: &str) -> Result { let v = s.to_lowercase(); Ok(if v.contains("adoptium") || v.contains("adoptopenjdk") || v.contains("temurin") { Self::Adoptium } else if v.contains("liberica") || v.contains("bellsoft") { Self::Liberica } else if v.contains("microsoft") { Self::Microsoft } else if v.contains("openjdk") { Self::OpenJDK } else if v.contains("oracle") { Self::Oracle } else if v.contains("amazon") || v.contains("corretto") { Self::Corretto } else if v.contains("azul") || v.contains("zulu") { Self::Zulu } else { Self::Other(s.to_string()) }) } } impl<'de> Deserialize<'de> for JavaVendor { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(Self::from_str(&s).unwrap()) } }