Skip to content

Commit aa6503c

Browse files
committed
add dynamic corretto version check
1 parent 02ce031 commit aa6503c

13 files changed

+356
-23
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export(java_install)
1010
export(java_list)
1111
export(java_quick_install)
1212
export(java_unpack)
13+
export(java_valid_versions)
1314
export(rje_consent)
1415
export(use_java)
1516
importFrom(utils,getFromNamespace)

R/internal_utilities.R

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,22 @@
77
platform_detect <- function(quiet = TRUE) {
88
sys_info <- tolower(Sys.info())
99

10-
os <- switch(sys_info["sysname"],
10+
os <- switch(
11+
sys_info["sysname"],
1112
"windows" = "windows",
1213
"linux" = "linux",
1314
"darwin" = "macos",
1415
stop(cli::cli_abort("Unsupported platform"))
1516
)
1617

17-
arch <- switch(sys_info["machine"],
18+
arch <- switch(
19+
sys_info["machine"],
1820
"x86-64" = "x64",
1921
"x86_64" = "x64",
2022
"i386" = "x86",
2123
"i686" = "x86",
22-
"aarch64" = "arm64",
23-
"arm64" = "arm64",
24+
"aarch64" = "aarch64",
25+
"arm64" = "aarch64",
2426
stop(cli::cli_abort("Unsupported architecture"))
2527
)
2628

@@ -67,7 +69,10 @@ urls_test_all <- function() {
6769

6870
try(
6971
{
70-
response <- curl::curl_fetch_memory(url, handle = curl::new_handle(nobody = TRUE))
72+
response <- curl::curl_fetch_memory(
73+
url,
74+
handle = curl::new_handle(nobody = TRUE)
75+
)
7176
status <- response$status_code
7277
},
7378
silent = TRUE
@@ -113,9 +118,18 @@ java_version_check_rscript <- function(java_home) {
113118
Sys.setenv(PATH = paste(new_path, old_path, sep = .Platform$path.sep))
114119

115120
suppressWarnings(rJava::.jinit())
116-
suppressWarnings(java_version <- rJava::.jcall("java.lang.System", "S", "getProperty", "java.version"))
121+
suppressWarnings(
122+
java_version <- rJava::.jcall(
123+
"java.lang.System",
124+
"S",
125+
"getProperty",
126+
"java.version"
127+
)
128+
)
117129

118-
message <- cli::format_message("rJava and other rJava/Java-based packages will use Java version: {.val {java_version}}")
130+
message <- cli::format_message(
131+
"rJava and other rJava/Java-based packages will use Java version: {.val {java_version}}"
132+
)
119133

120134
message
121135
},

R/java_download.R

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#' Download a Java distribution
22
#'
3-
#' @param version `Integer` or `character` vector of length 1 for major version of Java to download or install. If not specified, defaults to the latest LTS version. Can be "8", "11", "17", "21", "22", or 8, 11, 17, 21, or 22.
3+
#' @param version `Integer` or `character` vector of length 1 for major version of Java to download or install. If not specified, defaults to the latest LTS version. Can be "8", "11", "17", "21", "22", "23", "24", or 8, 11, 17, 21, 22, 23, 24 or any newer version if it is available for the selected distribution.
44
#' @param distribution The Java distribution to download. If not specified, defaults to "Amazon Corretto". Currently only \href{https://aws.amazon.com/corretto/}{"Amazon Corretto"} is supported.
55
#' @param cache_path The destination directory to download the Java distribution to. Defaults to a user-specific data directory.
66
#' @param platform The platform for which to download the Java distribution. Defaults to the current platform.
@@ -31,10 +31,8 @@ java_download <- function(
3131
force = FALSE,
3232
temp_dir = FALSE
3333
) {
34-
3534
# Download distribution and check MD5 checksum
3635
download_dist_check_md5 <- function(url, dest_file, quiet) {
37-
3836
curl::curl_download(url, dest_file, quiet = FALSE)
3937
curl::curl_download(url_md5, dest_file_md5, quiet = TRUE)
4038

@@ -45,7 +43,10 @@ java_download <- function(
4543
md5sum_expected <- readLines(dest_file_md5, warn = FALSE)
4644

4745
if (md5sum != md5sum_expected) {
48-
cli::cli_abort("MD5 checksum mismatch. Please try downloading the file again.", .envir = environment())
46+
cli::cli_abort(
47+
"MD5 checksum mismatch. Please try downloading the file again.",
48+
.envir = environment()
49+
)
4950
unlink(dest_file)
5051
return(NULL)
5152
} else {
@@ -75,7 +76,10 @@ java_download <- function(
7576
# Checks for the parameters
7677
checkmate::check_vector(version, len = 1)
7778
version <- as.character(version)
78-
checkmate::assert_choice(version, getOption("rJavaEnv.valid_major_java_versions"))
79+
checkmate::assert_choice(
80+
as.character(version),
81+
java_valid_versions()
82+
)
7983

8084
checkmate::assert_choice(distribution, valid_distributions)
8185

@@ -101,15 +105,24 @@ java_download <- function(
101105
}
102106

103107
if (!distribution %in% names(java_urls)) {
104-
cli::cli_abort("Unsupported distribution: {.val {distribution}}", .envir = environment())
108+
cli::cli_abort(
109+
"Unsupported distribution: {.val {distribution}}",
110+
.envir = environment()
111+
)
105112
}
106113

107114
if (!platform %in% names(java_urls[[distribution]])) {
108-
cli::cli_abort("Unsupported platform: {.val {platform}}", .envir = environment())
115+
cli::cli_abort(
116+
"Unsupported platform: {.val {platform}}",
117+
.envir = environment()
118+
)
109119
}
110120

111121
if (!arch %in% names(java_urls[[distribution]][[platform]])) {
112-
cli::cli_abort("Unsupported architecture: {.val {arch}}", .envir = environment())
122+
cli::cli_abort(
123+
"Unsupported architecture: {.val {arch}}",
124+
.envir = environment()
125+
)
113126
}
114127

115128
url_template <- java_urls[[distribution]][[platform]][[arch]]
@@ -120,17 +133,23 @@ java_download <- function(
120133
dest_file_md5 <- paste0(file.path(cache_path, basename(url_md5)), ".md5")
121134

122135
if (!quiet) {
123-
cli::cli_inform("Downloading Java {version} ({distribution}) for {platform} {arch} to {dest_file}", .envir = environment())
136+
cli::cli_inform(
137+
"Downloading Java {version} ({distribution}) for {platform} {arch} to {dest_file}",
138+
.envir = environment()
139+
)
124140
}
125141

126142
if (file.exists(dest_file) & !force) {
127143
if (!quiet) {
128-
cli::cli_inform("File already exists. Skipping download.", .envir = environment())
144+
cli::cli_inform(
145+
"File already exists. Skipping download.",
146+
.envir = environment()
147+
)
129148
}
130-
} else if(file.exists(dest_file) & force) {
149+
} else if (file.exists(dest_file) & force) {
131150
if (!quiet) {
132151
cli::cli_inform("Removing existing installation.", .envir = environment())
133-
}
152+
}
134153
file.remove(dest_file)
135154
download_dist_check_md5(url, dest_file, quiet)
136155
} else if (!file.exists(dest_file)) {

R/java_valid_versions.R

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#' Retrieve Valid Java Versions
2+
#'
3+
#' This function retrieves a list of valid Java versions by querying an appropriate API endpoint based on the chosen distribution.
4+
#' The result is cached for 8 hours to avoid repeated API calls. If the API call fails (for example, due to a lack of internet connectivity),
5+
#' the function falls back to a pre-defined list of Java versions.
6+
#'
7+
#' @param distribution Character. The Java distribution to use. If set to `"Oracle"`, the Oracle API is used.
8+
#' If set to `"Corretto"` (the default), an Amazon Corretto endpoint is used.
9+
#' @param force Logical. If TRUE, forces a fresh API call even if a cached value exists. Defaults to FALSE.
10+
#'
11+
#' @return A character vector of valid Java versions.
12+
#'
13+
#' @examples
14+
#' \dontrun{
15+
#' # Retrieve valid Java versions (cached if available) using Amazon Corretto endpoint
16+
#' versions <- java_valid_versions()
17+
#'
18+
#' # Force refresh the list of Java versions using the Oracle endpoint
19+
#' versions <- java_valid_versions(distribution = "Corretto", force = TRUE)
20+
#' }
21+
#'
22+
#' @export
23+
java_valid_versions <- function(
24+
distribution = "Corretto",
25+
force = FALSE
26+
) {
27+
# Define cache expiry time (in hours)
28+
expiry_hours <- 8
29+
30+
# Retrieve cached values from options
31+
valid_versions_cache <- getOption("rJavaEnv.valid_versions_cache")
32+
valid_versions_timestamp <- getOption("rJavaEnv.valid_versions_timestamp")
33+
34+
# Return cached value if available and not expired, unless force is TRUE.
35+
if (
36+
!force &&
37+
!is.null(valid_versions_cache) &&
38+
!is.null(valid_versions_timestamp) &&
39+
as.numeric(difftime(
40+
Sys.time(),
41+
valid_versions_timestamp,
42+
units = "hours"
43+
)) <
44+
expiry_hours
45+
) {
46+
return(valid_versions_cache)
47+
}
48+
49+
# Select helper based on distribution value.
50+
new_versions <- switch(
51+
distribution,
52+
# "Oracle" = java_valid_versions_oracle(),
53+
"Corretto" = java_valid_major_versions_corretto(),
54+
stop("Unsupported distribution")
55+
)
56+
57+
# Update the cache options with the new values and current timestamp.
58+
options(
59+
rJavaEnv.valid_versions_cache = new_versions,
60+
rJavaEnv.valid_versions_timestamp = Sys.time()
61+
)
62+
63+
return(new_versions)
64+
}
65+
66+
#' Get Available Online Versions of Amazon Corretto
67+
#'
68+
#' This function downloads the latest Amazon Corretto version information from the
69+
#' Corretto GitHub endpoint and returns a data frame with details for all eligible releases.
70+
#'
71+
#' It leverages the existing \code{platform_detect()} function to infer the current operating
72+
#' system and architecture if these are not provided.
73+
#'
74+
#' @param arch Optional character string for the target architecture (e.g., "x64").
75+
#' If \code{NULL}, it is inferred using \code{platform_detect()}.
76+
#' @param platform Optional character string for the operating system (e.g., "windows", "macos", "linux").
77+
#' If \code{NULL}, it is inferred using \code{platform_detect()}.
78+
#' @param imageType Optional character string to filter on; defaults to \code{"jdk"}.
79+
#' @param extension Optional character string specifying the desired file extension; defaults to \code{"tar.gz"}.
80+
#'
81+
#' @return A `character` vector of available major Corretto versions.
82+
#'
83+
java_valid_major_versions_corretto <- function(
84+
arch = NULL,
85+
platform = NULL,
86+
imageType = "jdk",
87+
extension = "tar.gz"
88+
) {
89+
# If platform or arch are not provided, detect them using the existing function.
90+
if (is.null(platform) || is.null(arch)) {
91+
plat <- platform_detect(quiet = TRUE)
92+
if (is.null(platform)) platform <- plat$os
93+
if (is.null(arch)) arch <- plat$arch
94+
}
95+
96+
# URL for the Corretto version information.
97+
availableVersionsUrl <- "https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json"
98+
99+
# Fetch and parse the JSON using httr.
100+
corretto_versions <- tryCatch(
101+
{
102+
json_data <- jsonlite::read_json(availableVersionsUrl)
103+
eligible <- json_data[[platform]][[arch]][[imageType]]
104+
if (is.null(eligible)) {
105+
stop(
106+
"No eligible versions found for the specified platform, architecture, and image type."
107+
)
108+
}
109+
names(eligible)
110+
},
111+
error = function(e) {
112+
getOption("rJavaEnv.fallback_valid_versions")
113+
}
114+
)
115+
116+
corretto_versions <- as.character(sort(as.numeric(corretto_versions)))
117+
return(corretto_versions)
118+
}
119+
120+
# Helper function for Oracle distribution
121+
# java_valid_versions_oracle <- function() {
122+
# oracle_api_url <- "https://java.oraclecloud.com/javaVersions"
123+
# tryCatch(
124+
# {
125+
# oracle_java_versions <- jsonlite::fromJSON(
126+
# oracle_api_url,
127+
# simplifyDataFrame = TRUE
128+
# )
129+
# # Combine "8" and "11" with the sorted versions from the API
130+
# c("8", "11", sort(as.character(oracle_java_versions$items$jdkVersion)))
131+
# },
132+
# error = function(e) {
133+
# # If the API call fails, use the fallback list stored in options.
134+
# getOption("rJavaEnv.fallback_valid_versions")
135+
# }
136+
# )
137+
# }

R/onLoad.R

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,23 @@
44
# this default folder choice is in-line with what renv package does
55
# https://github.com/rstudio/renv/blob/d6bced36afa0ad56719ca78be6773e9b4bbb078f/R/bootstrap.R#L940-L950
66
rJavaEnv.cache_path = tools::R_user_dir("rJavaEnv", which = "cache"),
7-
rJavaEnv.valid_major_java_versions = c("8", "11", "17", "21", "22")
7+
rJavaEnv.valid_versions_cache = NULL,
8+
rJavaEnv.valid_versions_timestamp = NULL,
9+
# Fallback list of valid Java versions if the API call fails (e.g., no internet) as of 2025-04-02
10+
rJavaEnv.fallback_valid_versions = c(
11+
"8",
12+
"11",
13+
# "15", # not available from Amazon Corretto
14+
# "16", # not available from Amazon Corretto
15+
"17",
16+
"18",
17+
"19",
18+
"20",
19+
"21",
20+
"22",
21+
"23",
22+
"24"
23+
)
824
)
925
toset <- !(names(op.rJavaEnv) %in% names(op))
1026
if (any(toset)) options(op.rJavaEnv[toset])

man/java_download.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/java_quick_install.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/java_valid_major_versions_corretto.Rd

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)