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", and "11" to "24" (or the same version numbers in `integer`) or any newer version if it is available for the selected distribution. For `macOS` on `aarch64` architecture (Apple Silicon) certain `Java` versions are not available.
4- # ' @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.
3+ # ' @inheritParams global_version_param
4+ # ' @param distribution The Java distribution to download. One of "Corretto", "Temurin", or "Zulu". Defaults to "Corretto". Ignored if `version` is a SDKMAN identifier.
5+ # ' @inheritParams global_backend_param
56# ' @param cache_path The destination directory to download the Java distribution to. Defaults to a user-specific data directory.
67# ' @param platform The platform for which to download the Java distribution. Defaults to the current platform.
78# ' @param arch The architecture for which to download the Java distribution. Defaults to the current architecture.
89# ' @param force A logical. Whether the distribution file should be overwritten or not. Defaults to `FALSE`.
910# ' @param temp_dir A logical. Whether the file should be saved in a temporary directory. Defaults to `FALSE`.
1011# ' @inheritParams global_quiet_param
12+ # ' @inheritParams global_sdkman_references
1113# '
1214# ' @return The path to the downloaded Java distribution file.
1315# ' @export
2022# '
2123# ' # download default Java distribution (version 21)
2224# ' java_download(temp_dir = TRUE)
25+ # '
26+ # ' # download using SDKMAN backend
27+ # ' java_download(version = "21", backend = "sdkman", temp_dir = TRUE)
2328# ' }
2429java_download <- function (
2530 version = 21 ,
2631 distribution = " Corretto" ,
32+ backend = getOption(" rJavaEnv.backend" , " native" ),
2733 cache_path = getOption(" rJavaEnv.cache_path" ),
2834 platform = platform_detect()$ os ,
2935 arch = platform_detect()$ arch ,
3036 quiet = FALSE ,
3137 force = FALSE ,
3238 temp_dir = FALSE
3339) {
34- # override cache_path if temp_dir is set to TRUE
40+ # Override cache_path if temp_dir is set to TRUE
3541 if (temp_dir ) {
3642 temp_dir <- tempdir()
3743 setwd(temp_dir )
@@ -41,45 +47,35 @@ java_download <- function(
4147 cache_path <- file.path(temp_dir , " rJavaEnv_cache" )
4248 }
4349
44- # rje_consent_check() # disabling consent check for now
45- java_urls <- java_urls_load()
46-
47- valid_distributions <- names(java_urls )
48- valid_platforms <- names(java_urls [[distribution ]])
49- valid_architectures <- names(java_urls [[distribution ]][[platform ]])
50-
51- # Checks for the parameters
52- checkmate :: check_vector(version , len = 1 )
50+ # Validate version
5351 version <- as.character(version )
52+ checkmate :: check_vector(version , len = 1 )
5453
55- # Optimized validation: check fast list first, only hit network if needed
56- if (! version %in% java_valid_versions_fast()) {
57- # Version not in fast/offline list, check if it's a new version online
58- checkmate :: assert_choice(
59- version ,
60- java_valid_versions(
61- distribution = distribution ,
62- platform = platform ,
63- arch = arch
54+ # Auto-detect SDKMAN identifier
55+ if (is_sdkman_identifier(version )) {
56+ if (! quiet ) {
57+ cli :: cli_alert_info(
58+ " Detected SDKMAN identifier {.val {version}}. Using sdkman backend."
6459 )
65- )
60+ }
61+ backend <- " sdkman"
62+ distribution <- sdkman_vendor_to_distribution(sdkman_vendor_code(version ))
63+ if (! quiet ) {
64+ cli :: cli_alert_info(" Distribution: {.val {distribution}}" )
65+ }
6666 }
6767
68- checkmate :: assert_choice(distribution , valid_distributions )
69-
70- # Create the distrib subfolder within the destination directory
71- cache_path <- file.path(cache_path , " distrib" )
72- if (! dir.exists(cache_path )) {
73- dir.create(cache_path , recursive = TRUE )
68+ # Validate distribution (only for native backend)
69+ if (backend == " native" ) {
70+ valid_distributions <- c(" Corretto" , " Temurin" , " Zulu" )
71+ checkmate :: assert_choice(distribution , valid_distributions )
7472 }
75- checkmate :: assert_directory_exists(cache_path , access = " rw" , add = TRUE )
7673
77- checkmate :: assert_choice(platform , valid_platforms )
78- checkmate :: assert_choice(arch , valid_architectures )
79- checkmate :: assert_flag(quiet )
80- checkmate :: assert_flag(force )
74+ # Validate backend
75+ valid_backends <- c(" native" , " sdkman" )
76+ checkmate :: assert_choice(backend , valid_backends )
8177
82- # Print out the detected platform and architecture
78+ # Print detected platform and architecture
8379 if (! quiet ) {
8480 cli :: cli_inform(c(
8581 " Detected platform: {.strong {platform}}" ,
@@ -88,91 +84,94 @@ java_download <- function(
8884 ))
8985 }
9086
91- if (! distribution %in% names(java_urls )) {
92- cli :: cli_abort(
93- " Unsupported distribution: {.val {distribution}}" ,
94- .envir = environment()
95- )
96- }
97-
98- if (! platform %in% names(java_urls [[distribution ]])) {
99- cli :: cli_abort(
100- " Unsupported platform: {.val {platform}}" ,
101- .envir = environment()
102- )
103- }
87+ # Resolve metadata
88+ build <- resolve_java_metadata(version , distribution , platform , arch , backend )
10489
105- if (! arch %in% names(java_urls [[distribution ]][[platform ]])) {
106- cli :: cli_abort(
107- " Unsupported architecture: {.val {arch}}" ,
108- .envir = environment()
109- )
90+ # Prepare destination directory
91+ dest_dir <- file.path(cache_path , " distrib" )
92+ if (! dir.exists(dest_dir )) {
93+ dir.create(dest_dir , recursive = TRUE )
11094 }
95+ dest <- file.path(dest_dir , build $ filename )
11196
112- url_template <- java_urls [[distribution ]][[platform ]][[arch ]]
113- url <- gsub(" \\ {version\\ }" , version , url_template )
114- url_md5 <- gsub(" latest/" , " latest_checksum/" , url )
97+ # Download and verify
98+ result_path <- download_java_with_checksum(build , dest , quiet , force )
11599
116- dest_file <- file.path(cache_path , basename(url ))
117- dest_file_md5 <- paste0(file.path(cache_path , basename(url_md5 )), " .md5" )
100+ # Attach metadata attributes for downstream functions
101+ attr(result_path , " distribution" ) <- distribution
102+ attr(result_path , " backend" ) <- backend
103+ attr(result_path , " version" ) <- version
104+ attr(result_path , " platform" ) <- platform
105+ attr(result_path , " arch" ) <- arch
118106
119- if (! quiet ) {
120- cli :: cli_inform(
121- " Downloading Java {version} ({distribution}) for {platform} {arch} to {dest_file}" ,
122- .envir = environment()
123- )
124- }
107+ result_path
108+ }
125109
126- if (file.exists(dest_file ) & ! force ) {
110+ # ' Download and verify checksum
111+ # '
112+ # ' Internal function to download a Java distribution and verify its checksum
113+ # '
114+ # ' @param build A java_build object containing download metadata
115+ # ' @param dest Destination file path
116+ # ' @param quiet Logical, suppress messages
117+ # ' @param force Logical, overwrite existing files
118+ # '
119+ # ' @return Path to downloaded file
120+ # ' @keywords internal
121+ download_java_with_checksum <- function (build , dest , quiet , force ) {
122+ # Check if file already exists
123+ if (file.exists(dest ) && ! force ) {
127124 if (! quiet ) {
128- cli :: cli_inform(
129- " File already exists. Skipping download." ,
130- .envir = environment()
131- )
125+ cli :: cli_inform(" File already cached: {basename(dest)}" )
132126 }
133- return (dest_file )
127+ return (dest )
134128 }
135129
136- if (file.exists(dest_file ) & force ) {
130+ # Remove existing file if force=TRUE
131+ if (file.exists(dest ) && force ) {
137132 if (! quiet ) {
138- cli :: cli_inform(" Removing existing installation. " , .envir = environment() )
133+ cli :: cli_inform(" Removing existing file... " )
139134 }
140- file.remove( dest_file )
135+ unlink( dest )
141136 }
142137
143- download_dist_with_md5_check(url , dest_file , url_md5 , dest_file_md5 , quiet )
144-
145- return (dest_file )
146- }
147-
148- # Helper function to download a distribution and verify its MD5 checksum
149- download_dist_with_md5_check <- function (
150- url ,
151- dest_file ,
152- url_md5 ,
153- dest_file_md5 ,
154- quiet
155- ) {
156- # Perform downloads
157- curl :: curl_download(url , dest_file , quiet = quiet )
158- curl :: curl_download(url_md5 , dest_file_md5 , quiet = quiet )
159-
138+ # Download
160139 if (! quiet ) {
161- cli :: cli_inform(" Download completed ." )
140+ cli :: cli_inform(" Downloading {build$vendor} Java {build$major}.. ." )
162141 }
142+ curl :: curl_download(build $ download_url , dest , quiet = quiet )
163143
164- # Verify checksum
165- md5sum_actual <- tools :: md5sum(dest_file )
166- md5sum_expected <- readLines(dest_file_md5 , warn = FALSE )
144+ # Verify checksum if available
145+ if (! is.null(build $ checksum ) && ! is.null(build $ checksum_type )) {
146+ if (! quiet ) {
147+ cli :: cli_inform(" Verifying {build$checksum_type} checksum..." )
148+ }
167149
168- if (md5sum_actual != md5sum_expected ) {
169- unlink(dest_file ) # Clean up failed download
170- cli :: cli_abort(
171- " MD5 checksum mismatch. Please try downloading the file again."
150+ actual <- switch (
151+ build $ checksum_type ,
152+ " md5" = tools :: md5sum(dest ),
153+ " sha256" = digest :: digest(dest , algo = " sha256" , file = TRUE ),
154+ " sha512" = digest :: digest(dest , algo = " sha512" , file = TRUE ),
155+ NULL
172156 )
173- }
174157
175- if (! quiet ) {
176- cli :: cli_inform(" MD5 checksum verified." )
158+ if (! is.null(actual ) && actual != build $ checksum ) {
159+ unlink(dest )
160+ cli :: cli_abort(" {build$checksum_type} checksum mismatch! File deleted." )
161+ }
162+
163+ if (! quiet ) cli :: cli_inform(" Checksum verified." )
164+ } else if (build $ backend == " sdkman" ) {
165+ if (! quiet ) {
166+ cli :: cli_alert_warning(" Skipping checksum (unavailable for SDKMAN)" )
167+ }
177168 }
169+
170+ dest
171+ }
172+
173+ # ' Get extension for platform
174+ # ' @keywords internal
175+ get_java_archive_extension <- function (platform ) {
176+ if (platform == " windows" ) " zip" else " tar.gz"
178177}
0 commit comments