├── .github
├── .gitignore
├── workflows
│ ├── pkgcheck.yaml
│ ├── R-CMD-check-HTML5.yaml
│ ├── pkgdown.yaml
│ ├── render-README.yaml
│ ├── R-CMD-check.yaml
│ ├── update-citation-cff.yaml
│ ├── java-live-tests.yml
│ ├── test-coverage.yaml
│ └── rhub.yaml
├── CONTRIBUTING.md
└── CODE_OF_CONDUCT.md
├── vignettes
├── .gitignore
├── data-for-vignettes
│ ├── get-data-for-vignettes.R
│ ├── rJava_dlstats.csv
│ ├── ggplot2_dlstats.csv
│ └── data_table_dlstats.csv
├── bibliography.bib
├── multiple-java-with-targets-callr.qmd
└── install-rjava-from-source.qmd
├── LICENSE
├── man
├── figures
│ ├── card.png
│ └── logo.png
├── urls_test_all.Rd
├── java_get_home.Rd
├── java_urls_load.Rd
├── global_quiet_param.Rd
├── java_version_check_rscript.Rd
├── java_env_set_session.Rd
├── rje_envvar_exists.Rd
├── platform_detect.Rd
├── java_build_env_set_rprofile.Rd
├── set_java_build_env_vars.Rd
├── rje_consent_check.Rd
├── java_env_set_rprofile.Rd
├── java_check_version_system.Rd
├── java_check_version_cmd.Rd
├── java_clear_in_project.Rd
├── java_clear_distrib_cache.Rd
├── java_clear_installed_cache.Rd
├── java_list_in_project.Rd
├── java_build_env_unset.Rd
├── java_list_distrib_cache.Rd
├── java_list_installed_cache.Rd
├── java_env_unset.Rd
├── java_check_version_rjava.Rd
├── java_clear.Rd
├── java_valid_major_versions_corretto.Rd
├── java_unpack.Rd
├── rje_consent.Rd
├── java_list.Rd
├── java_valid_versions.Rd
├── java_install.Rd
├── java_build_env_set.Rd
├── java_env_set.Rd
├── java_download.Rd
├── java_quick_install.Rd
├── use_java.Rd
└── rJavaEnv-package.Rd
├── pkgdown
├── favicon
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── apple-touch-icon.png
│ ├── apple-touch-icon-60x60.png
│ ├── apple-touch-icon-76x76.png
│ ├── apple-touch-icon-120x120.png
│ ├── apple-touch-icon-152x152.png
│ ├── apple-touch-icon-180x180.png
│ ├── web-app-manifest-192x192.png
│ ├── web-app-manifest-512x512.png
│ └── site.webmanifest
└── assets
│ └── images
│ └── card.png
├── R
├── rJavaEnv-package.R
├── global_params.R
├── java_quick_install.R
├── use_java.R
├── onLoad.R
├── java_manage.R
├── java_manage_distrib_cache.R
├── consent.R
├── java_unpack.R
├── java_manage_installed_cache.R
├── java_manage_project.R
├── java_valid_versions.R
└── internal_utilities.R
├── .gitignore
├── .editorconfig
├── tests
├── testthat
│ ├── setup-mock-globals.R
│ ├── test-java_env.R
│ ├── test-java_unpack.R
│ ├── test-onLoad.R
│ ├── test-internal_utilities_extra.R
│ ├── test-java_env_linux.R
│ ├── test-java_valid_versions.R
│ ├── test-java_wrappers.R
│ ├── helper-mocks.R
│ ├── test-java_download-mocked.R
│ ├── test-internal_utilities_version.R
│ ├── test-java_env_unit.R
│ ├── test-java_full-cycle-live.R
│ ├── test-internal_utilities.R
│ └── test-java_manage.R
└── testthat.R
├── rJavaEnv.Rproj
├── tools
└── meta-data-update-and-submission.R
├── inst
├── CITATION
├── extdata
│ └── java_urls.json
├── resources
│ └── consent-info
└── schemaorg.json
├── NAMESPACE
├── .Rbuildignore
├── cran-comments.md
├── LICENSE.md
├── _pkgdown.yml
├── DESCRIPTION
└── NEWS.md
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2024
2 | COPYRIGHT HOLDER: rJavaEnv authors
3 |
--------------------------------------------------------------------------------
/man/figures/card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/man/figures/card.png
--------------------------------------------------------------------------------
/man/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/man/figures/logo.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/favicon.ico
--------------------------------------------------------------------------------
/pkgdown/assets/images/card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/assets/images/card.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/favicon-96x96.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/pkgdown/favicon/web-app-manifest-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/web-app-manifest-192x192.png
--------------------------------------------------------------------------------
/pkgdown/favicon/web-app-manifest-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/e-kotov/rJavaEnv/HEAD/pkgdown/favicon/web-app-manifest-512x512.png
--------------------------------------------------------------------------------
/R/rJavaEnv-package.R:
--------------------------------------------------------------------------------
1 | #' @keywords internal
2 | "_PACKAGE"
3 |
4 | ## usethis namespace: start
5 | #' @import rlang
6 | #' @importFrom utils getFromNamespace
7 | ## usethis namespace: end
8 | NULL
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .Rdata
4 | .httr-oauth
5 | .DS_Store
6 | .quarto
7 | docs
8 | bin
9 | private
10 | README_cache
11 | renv
12 | .Rprofile
13 | rjavaenv
14 | /doc/
15 | /Meta/
16 |
17 | /.quarto/
18 | revdep
19 | .cache
20 | .config
21 | .jupyter
22 | .local
23 | .ipython
24 | .vscode
25 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 |
9 | [*.{r,R,rmd,Rmd,qmd}]
10 | indent_size = 2
11 | trim_trailing_whitespace = true
12 |
13 | [*.{cpp,h,hpp}]
14 | indent_size = 2
15 | trim_trailing_whitespace = true
16 |
17 | [Makefile]
18 | indent_style = tab
--------------------------------------------------------------------------------
/R/global_params.R:
--------------------------------------------------------------------------------
1 | #' @title Global Quiet Parameter
2 | #'
3 | #' @description
4 | #' Documentation for the `quiet` parameter, used globally.
5 | #'
6 | #' @param quiet A `logical` value indicating whether to suppress messages. Can be `TRUE` or `FALSE`.
7 | #' @keywords internal
8 | global_quiet_param <- function(quiet){
9 | # this is just a placeholder for global quiet parameter
10 | }
11 |
--------------------------------------------------------------------------------
/man/urls_test_all.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/internal_utilities.R
3 | \name{urls_test_all}
4 | \alias{urls_test_all}
5 | \title{Test all Java URLs}
6 | \usage{
7 | urls_test_all()
8 | }
9 | \value{
10 | A list with the results of testing all Java URLs.
11 | }
12 | \description{
13 | Test all Java URLs
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/java_get_home.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_get_home}
4 | \alias{java_get_home}
5 | \title{Get JAVA_HOME}
6 | \usage{
7 | java_get_home()
8 | }
9 | \value{
10 | The value of the JAVA_HOME environment variable.
11 | }
12 | \description{
13 | Get the current JAVA_HOME environment variable.
14 | }
15 | \examples{
16 | java_get_home()
17 | }
18 |
--------------------------------------------------------------------------------
/tests/testthat/setup-mock-globals.R:
--------------------------------------------------------------------------------
1 | # This file is run automatically by testthat before tests are run.
2 | # It's a good place for mocks that are used across multiple test files.
3 |
4 | # NOTE: Mocks defined here with local_mocked_bindings() will NOT persist
5 | # into the test files because the scope ends when this file finishes sourcing.
6 | # Instead, we use helper-mocks.R which defines functions to apply mocks
7 | # within the test scopes.
8 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | # This file is part of the standard setup for testthat.
2 | # It is recommended that you do not modify it.
3 | #
4 | # Where should you do additional test configuration?
5 | # Learn more about the roles of various files in:
6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
7 | # * https://testthat.r-lib.org/articles/special-files.html
8 |
9 | library(testthat)
10 | library(rJavaEnv)
11 |
12 | test_check("rJavaEnv")
13 |
--------------------------------------------------------------------------------
/man/java_urls_load.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/internal_utilities.R
3 | \name{java_urls_load}
4 | \alias{java_urls_load}
5 | \title{Load Java URLs from JSON file}
6 | \usage{
7 | java_urls_load()
8 | }
9 | \value{
10 | A list with the Java URLs structured as in the JSON file by distribution, platform, and architecture.
11 | }
12 | \description{
13 | Load Java URLs from JSON file
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_env.R:
--------------------------------------------------------------------------------
1 | test_that("java_get_home() gets JAVA_HOME", {
2 | withr::with_envvar(
3 | c("JAVA_HOME" = "/path/to/java"),
4 | expect_equal(java_get_home(), "/path/to/java")
5 | )
6 | })
7 |
8 | test_that("java_get_home() returns empty string when JAVA_HOME is not set", {
9 | withr::with_envvar(
10 | c("JAVA_HOME" = NA),
11 | {
12 | Sys.unsetenv("JAVA_HOME")
13 | expect_equal(java_get_home(), "")
14 | }
15 | )
16 | })
17 |
--------------------------------------------------------------------------------
/man/global_quiet_param.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/global_params.R
3 | \name{global_quiet_param}
4 | \alias{global_quiet_param}
5 | \title{Global Quiet Parameter}
6 | \usage{
7 | global_quiet_param(quiet)
8 | }
9 | \arguments{
10 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
11 | }
12 | \description{
13 | Documentation for the \code{quiet} parameter, used globally.
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/java_version_check_rscript.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/internal_utilities.R
3 | \name{java_version_check_rscript}
4 | \alias{java_version_check_rscript}
5 | \title{Check Java version using rJava}
6 | \usage{
7 | java_version_check_rscript(java_home)
8 | }
9 | \arguments{
10 | \item{java_home}{}
11 | }
12 | \value{
13 | A message with the Java version or an error message.
14 | }
15 | \description{
16 | Check Java version using rJava
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/man/java_env_set_session.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_env_set_session}
4 | \alias{java_env_set_session}
5 | \title{Set the JAVA_HOME and PATH environment variables for the current session}
6 | \usage{
7 | java_env_set_session(java_home)
8 | }
9 | \arguments{
10 | \item{java_home}{The path to the desired JAVA_HOME.}
11 | }
12 | \description{
13 | Set the JAVA_HOME and PATH environment variables for the current session
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/rJavaEnv.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: No
4 | SaveWorkspace: No
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 | LineEndingConversion: Posix
18 |
19 | BuildType: Package
20 | PackageUseDevtools: Yes
21 | PackageInstallArgs: --no-multiarch --with-keep.source
22 | PackageRoxygenize: rd,collate,namespace,vignette
23 |
--------------------------------------------------------------------------------
/pkgdown/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/web-app-manifest-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png",
9 | "purpose": "maskable"
10 | },
11 | {
12 | "src": "/web-app-manifest-512x512.png",
13 | "sizes": "512x512",
14 | "type": "image/png",
15 | "purpose": "maskable"
16 | }
17 | ],
18 | "theme_color": "#ffffff",
19 | "background_color": "#ffffff",
20 | "display": "standalone"
21 | }
--------------------------------------------------------------------------------
/man/rje_envvar_exists.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/consent.R
3 | \name{rje_envvar_exists}
4 | \alias{rje_envvar_exists}
5 | \title{Helper for clean env var check}
6 | \usage{
7 | rje_envvar_exists(key)
8 | }
9 | \arguments{
10 | \item{key}{The environment variable key to check.}
11 | }
12 | \description{
13 | #' The function is based on the code of the \code{renv} package.
14 | Copyright 2023 Posit Software, PBC
15 | License: https://github.com/rstudio/renv/blob/main/LICENSE
16 | }
17 | \keyword{internal}
18 |
--------------------------------------------------------------------------------
/tools/meta-data-update-and-submission.R:
--------------------------------------------------------------------------------
1 | # before release
2 | # usethis::use_version("patch")
3 | # devtools::spell_check()
4 | usethis::use_tidy_description()
5 | cffr::cff_write()
6 | codemetar::write_codemeta(write_minimeta = T)
7 | # urlchecker::url_check()
8 | # devtools::check(remote = TRUE, manual = TRUE)
9 | # devtools::check_win_devel()
10 | # revdepcheck::revdep_check(num_workers = 4)
11 | # devtools::submit_cran()
12 |
13 | # usethis::use_github_release()
14 | # usethis::use_dev_version(push = TRUE)
15 | # rdocdump::rdd_to_txt(".", file = "private/rJavaEnv.txt")
16 |
--------------------------------------------------------------------------------
/inst/CITATION:
--------------------------------------------------------------------------------
1 | bibentry(
2 | key = "rjavaenv",
3 | bibtype = "Manual",
4 | title = "rJavaEnv: Java Environments for R Projects",
5 | author = c(
6 | person("Egor", "Kotov", , "kotov.egor@gmail.com", role = c("aut", "cre", "cph"),
7 | comment = c(ORCID = "0000-0001-6690-5345")),
8 | person("Chung-hong", "Chan", , "chainsawtiney@gmail.com", role = "aut",
9 | comment = c(ORCID = "0000-0002-6232-7530"))
10 | ),
11 | year = "2024",
12 | url = "https://github.com/e-kotov/rJavaEnv",
13 | doi = "10.32614/CRAN.package.rJavaEnv"
14 | )
15 |
--------------------------------------------------------------------------------
/man/platform_detect.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/internal_utilities.R
3 | \name{platform_detect}
4 | \alias{platform_detect}
5 | \title{Detect platform and architecture}
6 | \usage{
7 | platform_detect(quiet = TRUE)
8 | }
9 | \arguments{
10 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
11 | }
12 | \value{
13 | A list of length 2 with the detected platform and architecture.
14 | }
15 | \description{
16 | Detect platform and architecture
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(java_build_env_set)
4 | export(java_build_env_unset)
5 | export(java_check_version_cmd)
6 | export(java_check_version_rjava)
7 | export(java_clear)
8 | export(java_download)
9 | export(java_env_set)
10 | export(java_env_unset)
11 | export(java_get_home)
12 | export(java_install)
13 | export(java_list)
14 | export(java_quick_install)
15 | export(java_unpack)
16 | export(java_valid_versions)
17 | export(rje_consent)
18 | export(use_java)
19 | import(rlang)
20 | importFrom(utils,getFromNamespace)
21 | importFrom(utils,installed.packages)
22 |
--------------------------------------------------------------------------------
/man/java_build_env_set_rprofile.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_build_env.R
3 | \name{java_build_env_set_rprofile}
4 | \alias{java_build_env_set_rprofile}
5 | \title{Helper function to write build environment settings to .Rprofile}
6 | \usage{
7 | java_build_env_set_rprofile(java_home, project_path)
8 | }
9 | \arguments{
10 | \item{java_home}{The path to the desired \code{JAVA_HOME}.}
11 |
12 | \item{project_path}{The path to the project directory.}
13 | }
14 | \description{
15 | Helper function to write build environment settings to .Rprofile
16 | }
17 | \keyword{internal}
18 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^rJavaEnv\.Rproj$
2 | ^\.Rproj\.user$
3 | ^LICENSE\.md$
4 | ^README\.Rmd$
5 | ^README\.qmd$
6 | ^cran-comments\.md$
7 | ^_pkgdown\.yml$
8 | ^docs$
9 | ^pkgdown$
10 | ^\.github$
11 | ^\.Rprofile$
12 | ^rjavaenv$
13 | ^private$
14 | ^codemeta\.json$
15 | ^CITATION\.cff$
16 | ^doc$
17 | ^Meta$
18 | ^CODE_OF_CONDUCT\.md$
19 | ^vignettes/why-rJavaEnv\.qmd$
20 | ^vignettes/data-for-vignettes$
21 | ^vignettes/bibliography.bib$
22 | ^vignettes/media$
23 | ^CRAN-SUBMISSION$
24 | ^vignettes/.quarto$
25 | ^revdep$
26 | ^man/figures/card.png$
27 | ^tools$
28 | ^\.editorconfig$
29 | ^revdep$
30 | ^\.cache$
31 | ^\.config$
32 | ^\.local$
33 | ^\.jupyter$
34 |
--------------------------------------------------------------------------------
/man/set_java_build_env_vars.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_build_env.R
3 | \name{set_java_build_env_vars}
4 | \alias{set_java_build_env_vars}
5 | \title{Helper function to set Java build environment variables}
6 | \usage{
7 | set_java_build_env_vars(java_home, quiet = FALSE)
8 | }
9 | \arguments{
10 | \item{java_home}{The path to the desired \code{JAVA_HOME}.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 | }
14 | \description{
15 | Helper function to set Java build environment variables
16 | }
17 | \keyword{internal}
18 |
--------------------------------------------------------------------------------
/man/rje_consent_check.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/consent.R
3 | \name{rje_consent_check}
4 | \alias{rje_consent_check}
5 | \title{Verify User Consent for rJavaEnv}
6 | \usage{
7 | rje_consent_check()
8 | }
9 | \value{
10 | \code{TRUE} if consent is verified, otherwise an error is raised.
11 | }
12 | \description{
13 | Ensure that the user has granted permission for rJavaEnv to manage files on their file system.
14 | }
15 | \details{
16 | The function is based on the code of the \code{renv} package.
17 | Copyright 2023 Posit Software, PBC
18 | License: https://github.com/rstudio/renv/blob/main/LICENSE
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/java_env_set_rprofile.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_env_set_rprofile}
4 | \alias{java_env_set_rprofile}
5 | \title{Update the .Rprofile file in the project directory}
6 | \usage{
7 | java_env_set_rprofile(java_home, project_path = NULL)
8 | }
9 | \arguments{
10 | \item{java_home}{The path to the desired JAVA_HOME.}
11 |
12 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
13 | }
14 | \description{
15 | Update the .Rprofile file in the project directory
16 | }
17 | \keyword{internal}
18 |
--------------------------------------------------------------------------------
/man/java_check_version_system.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_check_version_system}
4 | \alias{java_check_version_system}
5 | \title{Check and print Java path and version using system commands}
6 | \usage{
7 | java_check_version_system(quiet)
8 | }
9 | \arguments{
10 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
11 | }
12 | \value{
13 | A \code{character} vector of length 1 containing the major Java version.
14 | }
15 | \description{
16 | This function checks the Java executable path and retrieves the Java version,
17 | then prints these details to the console.
18 | }
19 | \keyword{internal}
20 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_unpack.R:
--------------------------------------------------------------------------------
1 | test_that("bad java_distrib_path", {
2 | bad_path <- tempfile()
3 | expect_error(java_unpack(bad_path))
4 |
5 | bad_path <- "/home/johndoe/.cache/R/rJavaEnv/distrib/amazon-corretto-21-x64-linux-jdk.tar.7z"
6 | expect_error(java_unpack(bad_path), "Unsupported file format")
7 |
8 | bad_path <- "/home/johndoe/.cache/R/rJavaEnv/distrib/amazon-corretto-x64-linux-jdk.tar.zip"
9 | expect_error(java_unpack(bad_path), "Java version")
10 |
11 | bad_path <- "/home/johndoe/.cache/R/rJavaEnv/distrib/amazon-corretto-21-linux-jdk.tar.zip"
12 | expect_error(java_unpack(bad_path), "architecture")
13 |
14 | bad_path <- "/home/johndoe/.cache/R/rJavaEnv/distrib/amazon-corretto-21-x64-msdos-jdk.tar.zip"
15 | expect_error(java_unpack(bad_path), "platform")
16 |
17 | })
18 |
--------------------------------------------------------------------------------
/man/java_check_version_cmd.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_check_version_cmd}
4 | \alias{java_check_version_cmd}
5 | \title{Check installed Java version using terminal commands}
6 | \usage{
7 | java_check_version_cmd(java_home = NULL, quiet = FALSE)
8 | }
9 | \arguments{
10 | \item{java_home}{Path to Java home directory. If NULL, the function uses the JAVA_HOME environment variable.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 | }
14 | \value{
15 | A \code{character} vector of length 1 containing the major Java version.
16 | }
17 | \description{
18 | Check installed Java version using terminal commands
19 | }
20 | \examples{
21 | java_check_version_cmd()
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/.github/workflows/pkgcheck.yaml:
--------------------------------------------------------------------------------
1 | name: pkgcheck
2 |
3 | # This will cancel running jobs once a new run is triggered
4 | concurrency:
5 | group: ${{ github.workflow }}-${{ github.head_ref }}
6 | cancel-in-progress: true
7 |
8 | on:
9 | # Manually trigger the Action under Actions/pkgcheck
10 | workflow_dispatch:
11 | # Run on every push to main
12 | push:
13 | branches:
14 | - main
15 | pull_request:
16 | branches:
17 | - main
18 |
19 | jobs:
20 | pkgcheck:
21 | runs-on: ubuntu-latest
22 | env:
23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
24 | RUN_JAVA_DOWNLOAD_TESTS: "TRUE"
25 | RUN_JAVA_DOWNLOAD_TESTS_QUIET: "FALSE"
26 | RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD: "TRUE"
27 | permissions:
28 | issues: write
29 | steps:
30 | - uses: ropensci-review-tools/pkgcheck-action@main
31 |
--------------------------------------------------------------------------------
/man/java_clear_in_project.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_project.R
3 | \name{java_clear_in_project}
4 | \alias{java_clear_in_project}
5 | \title{Clear the Java versions symlinked in the current project}
6 | \usage{
7 | java_clear_in_project(project_path = NULL, check = TRUE, delete_all = FALSE)
8 | }
9 | \arguments{
10 | \item{project_path}{The project directory to clear. Defaults to the current working directory.}
11 |
12 | \item{check}{Whether to list the symlinked Java versions before clearing them. Defaults to TRUE.}
13 |
14 | \item{delete_all}{Whether to delete all symlinks without prompting. Defaults to FALSE.}
15 | }
16 | \value{
17 | A message indicating whether the symlinks were cleared or not.
18 | }
19 | \description{
20 | Clear the Java versions symlinked in the current project
21 | }
22 | \keyword{internal}
23 |
--------------------------------------------------------------------------------
/man/java_clear_distrib_cache.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_distrib_cache.R
3 | \name{java_clear_distrib_cache}
4 | \alias{java_clear_distrib_cache}
5 | \title{Clear the Java distributions cache folder}
6 | \usage{
7 | java_clear_distrib_cache(
8 | cache_path = getOption("rJavaEnv.cache_path"),
9 | check = TRUE,
10 | delete_all = FALSE
11 | )
12 | }
13 | \arguments{
14 | \item{cache_path}{The cache directory to clear. Defaults to the user-specific data directory.}
15 |
16 | \item{check}{Whether to list the contents of the cache directory before clearing it. Defaults to TRUE.}
17 |
18 | \item{delete_all}{Whether to delete all items without prompting. Defaults to FALSE.}
19 | }
20 | \value{
21 | A message indicating whether the cache was cleared or not.
22 | }
23 | \description{
24 | Clear the Java distributions cache folder
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/tests/testthat/test-onLoad.R:
--------------------------------------------------------------------------------
1 | test_that(".onLoad sets default options", {
2 | # Save original options to restore later
3 | op <- options()
4 | on.exit(options(op))
5 |
6 | # Clear specific options to test if they get set
7 | options(
8 | rJavaEnv.fallback_valid_versions_current_platform = NULL,
9 | rJavaEnv.valid_versions_cache = NULL
10 | )
11 |
12 | # Manually trigger .onLoad
13 | rJavaEnv:::.onLoad("rJavaEnv", "rJavaEnv")
14 |
15 | # Check if the platform fallback was set
16 | fallback <- getOption("rJavaEnv.fallback_valid_versions_current_platform")
17 | expect_false(is.null(fallback))
18 | expect_true(length(fallback) > 0)
19 |
20 | # Check if valid_versions_cache was initialized (it's set to NULL, which removes it)
21 | # We just verify that .onLoad ran without error and set the other options correctly
22 | expect_true(is.null(getOption("rJavaEnv.valid_versions_cache")))
23 | })
24 |
--------------------------------------------------------------------------------
/man/java_clear_installed_cache.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_installed_cache.R
3 | \name{java_clear_installed_cache}
4 | \alias{java_clear_installed_cache}
5 | \title{Clear the Java installations cache folder}
6 | \usage{
7 | java_clear_installed_cache(
8 | check = TRUE,
9 | delete_all = FALSE,
10 | cache_path = getOption("rJavaEnv.cache_path")
11 | )
12 | }
13 | \arguments{
14 | \item{check}{Whether to list the contents of the cache directory before clearing it. Defaults to TRUE.}
15 |
16 | \item{delete_all}{Whether to delete all installations without prompting. Defaults to FALSE.}
17 |
18 | \item{cache_path}{The cache directory to clear. Defaults to the user-specific data directory.}
19 | }
20 | \value{
21 | A message indicating whether the cache was cleared or not.
22 | }
23 | \description{
24 | Clear the Java installations cache folder
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | # rJavaEnv 0.3.0 (2025-04-04)
2 |
3 |
4 | ## New features
5 |
6 | - `Java` version (currently still only for `Amazon Corretto`) is now determined dynamically using the official GitHub `json` with releases, so when new `Java` version becomes available, you will not be depenent on `rJavaEnv` to be updated. As a fallback, versions up to 24 are hardcoded.
7 |
8 | - Added `force` argument to `java_download()`. When set to `TRUE`, allows to overwrite the distribution file if it already exist in the cache. This save the trouble of deleting the cached file with `java_clear()` before re-downloading.
9 |
10 | - Added a new function `java_valid_versions()` allows to retrieve a list of all available `Java` versions for the current automatically detected OS and CPU architecture, or user-specified platform and architecture.
11 |
12 | ## Improvements
13 |
14 | - Better command line `Java` detection (thanks to Jonas Lieth)
15 |
16 | - Test coverage is now 7.2%
17 |
--------------------------------------------------------------------------------
/man/java_list_in_project.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_project.R
3 | \name{java_list_in_project}
4 | \alias{java_list_in_project}
5 | \title{List the Java versions symlinked in the current project}
6 | \usage{
7 | java_list_in_project(
8 | project_path = NULL,
9 | output = c("data.frame", "vector"),
10 | quiet = TRUE
11 | )
12 | }
13 | \arguments{
14 | \item{project_path}{The project directory to list. Defaults to the current working directory.}
15 |
16 | \item{output}{The format of the output: "data.frame" or "vector". Defaults to "data.frame".}
17 |
18 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
19 | }
20 | \value{
21 | A data frame or character vector with the symlinked Java versions in the project directory.
22 | }
23 | \description{
24 | List the Java versions symlinked in the current project
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/man/java_build_env_unset.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_build_env.R
3 | \name{java_build_env_unset}
4 | \alias{java_build_env_unset}
5 | \title{Unset the Java build environment variables in the project .Rprofile}
6 | \usage{
7 | java_build_env_unset(project_path = NULL, quiet = FALSE)
8 | }
9 | \arguments{
10 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 | }
14 | \value{
15 | Does not return a value. Invisibly returns \code{NULL}.
16 | }
17 | \description{
18 | Unset the Java build environment variables in the project .Rprofile
19 | }
20 | \examples{
21 | \dontrun{
22 | # Remove Java build environment settings from the current project
23 | java_build_env_unset()
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/man/java_list_distrib_cache.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_distrib_cache.R
3 | \name{java_list_distrib_cache}
4 | \alias{java_list_distrib_cache}
5 | \title{List the contents of the Java distributions cache folder}
6 | \usage{
7 | java_list_distrib_cache(
8 | cache_path = getOption("rJavaEnv.cache_path"),
9 | output = c("data.frame", "vector"),
10 | quiet = TRUE
11 | )
12 | }
13 | \arguments{
14 | \item{cache_path}{The destination directory to download the Java distribution to. Defaults to a user-specific data directory.}
15 |
16 | \item{output}{The format of the output: "data.frame" or "vector". Defaults to "data.frame".}
17 |
18 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
19 | }
20 | \value{
21 | A character vector with the contents of the cache directory.
22 | }
23 | \description{
24 | List the contents of the Java distributions cache folder
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/man/java_list_installed_cache.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage_installed_cache.R
3 | \name{java_list_installed_cache}
4 | \alias{java_list_installed_cache}
5 | \title{List the contents of the Java installations cache folder}
6 | \usage{
7 | java_list_installed_cache(
8 | output = c("data.frame", "vector"),
9 | quiet = TRUE,
10 | cache_path = getOption("rJavaEnv.cache_path")
11 | )
12 | }
13 | \arguments{
14 | \item{output}{The format of the output: "data.frame" or "vector". Defaults to "data.frame".}
15 |
16 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
17 |
18 | \item{cache_path}{The cache directory to list. Defaults to the user-specific data directory. Not recommended to change.}
19 | }
20 | \value{
21 | A data frame or character vector with the contents of the cache directory.
22 | }
23 | \description{
24 | List the contents of the Java installations cache folder
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/man/java_env_unset.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_env_unset}
4 | \alias{java_env_unset}
5 | \title{Unset the JAVA_HOME and PATH environment variables in the project .Rprofile}
6 | \usage{
7 | java_env_unset(project_path = NULL, quiet = FALSE)
8 | }
9 | \arguments{
10 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 | }
14 | \value{
15 | Nothing. Removes the JAVA_HOME and PATH environment variables settings from the project .Rprofile.
16 | }
17 | \description{
18 | Unset the JAVA_HOME and PATH environment variables in the project .Rprofile
19 | }
20 | \examples{
21 | \dontrun{
22 | # clear the JAVA_HOME and PATH environment variables in the specified project .Rprofile
23 | java_env_unset(project_path = tempdir())
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2024 rJavaEnv authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/man/java_check_version_rjava.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_check_version_rjava}
4 | \alias{java_check_version_rjava}
5 | \title{Check Java Version with a Specified JAVA_HOME Using a Separate R Session}
6 | \usage{
7 | java_check_version_rjava(java_home = NULL, quiet = FALSE)
8 | }
9 | \arguments{
10 | \item{java_home}{Path to Java home directory. If NULL, the function uses the JAVA_HOME environment variable.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 | }
14 | \value{
15 | A \code{character} vector of length 1 containing the major Java version.
16 | }
17 | \description{
18 | This function sets the JAVA_HOME environment variable, initializes the JVM using rJava, and prints the Java version that would be used if the user sets the given JAVA_HOME in the current R session. This check is performed in a separate R session to avoid having to reload the current R session. The reason for this is that once Java is initialized in an R session, it cannot be uninitialized unless the current R session is restarted.
19 | }
20 | \examples{
21 | \dontrun{
22 | java_check_version_rjava()
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/vignettes/data-for-vignettes/get-data-for-vignettes.R:
--------------------------------------------------------------------------------
1 | if (!requireNamespace("pacman", quietly = TRUE)) {
2 | install.packages("pacman")
3 | }
4 | package_list <- c("devtools", "dlstats", "tidyverse")
5 | pacman::p_load(char = package_list)
6 | rm(package_list)
7 |
8 |
9 | dlstats::set_cran_start_year(2014)
10 |
11 | rJava_dependants <- devtools::revdep("rJava", dependencies = c("Imports", "Depends"), bioconductor = TRUE)
12 |
13 | rJava_dlstats <- dlstats::cran_stats("rJava", use_cache = FALSE)
14 | rJava_dependants_dlstats_cran <- dlstats::cran_stats(rJava_dependants, use_cache = FALSE)
15 | rJava_dependants_dlstats_bioc <- dlstats::bioc_stats(rJava_dependants, use_cache = FALSE, type = "Software")
16 | data_table_dlstats <- dlstats::cran_stats("data.table", use_cache = FALSE)
17 | ggplot2_dlstats <- dlstats::cran_stats("ggplot2", use_cache = FALSE)
18 |
19 |
20 |
21 | write_csv2(rJava_dlstats, "vignettes/data-for-vignettes/rJava_dlstats.csv")
22 | write_csv2(rJava_dependants_dlstats_cran, "vignettes/data-for-vignettes/rJava_dependants_dlstats_cran.csv")
23 | write_csv2(rJava_dependants_dlstats_bioc, "vignettes/data-for-vignettes/rJava_dependants_dlstats_bioc.csv")
24 | write_csv2(data_table_dlstats, "vignettes/data-for-vignettes/data_table_dlstats.csv")
25 | write_csv2(ggplot2_dlstats, "vignettes/data-for-vignettes/ggplot2_dlstats.csv")
26 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check-HTML5.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: R-CMD-check-HTML5
10 |
11 | jobs:
12 | R-CMD-check:
13 | runs-on: ubuntu-latest
14 | env:
15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
16 | R_KEEP_PKG_SOURCE: yes
17 | _R_CHECK_RD_VALIDATE_RD2HTML_: TRUE
18 | steps:
19 | - uses: actions/checkout@v2
20 |
21 | - name: Install pdflatex
22 | run: sudo apt-get install texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra
23 |
24 | - name: Install tidy
25 | run: sudo apt install tidy
26 |
27 | - uses: r-lib/actions/setup-r@v2
28 | with:
29 | r-version: 'devel'
30 | http-user-agent: 'release'
31 | use-public-rspm: true
32 |
33 | - uses: r-lib/actions/setup-r-dependencies@v2
34 | with:
35 | extra-packages: any::rcmdcheck
36 | needs: check
37 |
38 | - uses: r-lib/actions/check-r-package@v2
39 | with:
40 | args: '"--as-cran"'
41 | build_args: 'character()'
42 | error-on: '"note"'
43 |
--------------------------------------------------------------------------------
/man/java_clear.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage.R
3 | \name{java_clear}
4 | \alias{java_clear}
5 | \title{Manage Java installations and distributions caches}
6 | \usage{
7 | java_clear(
8 | type = c("project", "installed", "distrib"),
9 | target_dir = NULL,
10 | check = TRUE,
11 | delete_all = FALSE
12 | )
13 | }
14 | \arguments{
15 | \item{type}{What to clear: "project" - remove symlinks to install cache in the current project, "installed" - remove installed Java versions, "distrib" - remove downloaded Java distributions.}
16 |
17 | \item{target_dir}{The directory to clear. Defaults to current working directory for "project" and user-specific data directory for "installed" and "distrib". Not recommended to change.}
18 |
19 | \item{check}{Whether to list the contents of the cache directory before clearing it. Defaults to TRUE.}
20 |
21 | \item{delete_all}{Whether to delete all items without prompting. Defaults to FALSE.}
22 | }
23 | \value{
24 | A message indicating whether the cache was cleared or not.
25 | }
26 | \description{
27 | Wrapper function to clear the Java symlinked in the current project, installed, or distributions caches.
28 | }
29 | \examples{
30 | \dontrun{
31 | java_clear("project", target_dir = tempdir())
32 | java_clear("installed", target_dir = tempdir())
33 | java_clear("distrib", target_dir = tempdir())
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/man/java_valid_major_versions_corretto.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_valid_versions.R
3 | \name{java_valid_major_versions_corretto}
4 | \alias{java_valid_major_versions_corretto}
5 | \title{Get Available Online Versions of Amazon Corretto}
6 | \usage{
7 | java_valid_major_versions_corretto(
8 | arch = NULL,
9 | platform = NULL,
10 | imageType = "jdk"
11 | )
12 | }
13 | \arguments{
14 | \item{arch}{Optional character string for the target architecture (e.g., "x64").
15 | If \code{NULL}, it is inferred using \code{platform_detect()}.}
16 |
17 | \item{platform}{Optional character string for the operating system (e.g., "windows", "macos", "linux").
18 | If \code{NULL}, it is inferred using \code{platform_detect()}.}
19 |
20 | \item{imageType}{Optional character string to filter on; defaults to \code{"jdk"}. Can be set to \code{"jre"} for Windows Java Runtime Environment.}
21 | }
22 | \value{
23 | A \code{character} vector of available major Corretto versions.
24 | }
25 | \description{
26 | This function downloads the latest Amazon Corretto version information from the
27 | Corretto GitHub endpoint and returns a data frame with details for all eligible releases.
28 | }
29 | \details{
30 | It leverages the existing \code{platform_detect()} function to infer the current operating
31 | system and architecture if these are not provided.
32 | }
33 | \keyword{internal}
34 |
--------------------------------------------------------------------------------
/inst/extdata/java_urls.json:
--------------------------------------------------------------------------------
1 | {
2 | "Corretto": {
3 | "windows": {
4 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-windows-jdk.zip"
5 | },
6 | "linux": {
7 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-linux-jdk.tar.gz",
8 | "aarch64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-aarch64-linux-jdk.tar.gz"
9 | },
10 | "macos": {
11 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-macos-jdk.tar.gz",
12 | "aarch64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-aarch64-macos-jdk.tar.gz"
13 | },
14 | "alpine-linux": {
15 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-alpine-jdk.tar.gz",
16 | "aarch64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-aarch64-alpine-jdk.tar.gz"
17 | },
18 | "amazon-linux": {
19 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-al2-jdk.rpm",
20 | "aarch64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-aarch64-al2-jdk.rpm"
21 | },
22 | "amazon-linux-2023": {
23 | "x64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-x64-al2023-jdk.rpm",
24 | "aarch64": "https://corretto.aws/downloads/latest/amazon-corretto-{version}-aarch64-al2023-jdk.rpm"
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/java_unpack.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_unpack.R
3 | \name{java_unpack}
4 | \alias{java_unpack}
5 | \title{Unpack a Java distribution file into cache directory}
6 | \usage{
7 | java_unpack(java_distrib_path, quiet = FALSE, force = FALSE)
8 | }
9 | \arguments{
10 | \item{java_distrib_path}{A \code{character} vector of length 1 containing the path to the Java distribution file.}
11 |
12 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
13 |
14 | \item{force}{A logical. Whether to overwrite an existing installation. Defaults to \code{FALSE}.}
15 | }
16 | \value{
17 | A \code{character} vector containing of length 1 containing the path to the unpacked Java directory.
18 | }
19 | \description{
20 | Unpack the Java distribution file into cache directory and return the path to the unpacked Java directory with Java binaries.
21 | }
22 | \examples{
23 | \dontrun{
24 |
25 | # set cache dir to temporary directory
26 | options(rJavaEnv.cache_path = tempdir())
27 |
28 | # download Java 17 distrib and unpack it into cache dir
29 | java_17_distrib <- java_download(version = "17")
30 | java_home <- java_unpack(java_distrib_path = java_17_distrib)
31 |
32 | # set the JAVA_HOME environment variable in the current session
33 | # to the cache dir without touching any files in the current project directory
34 | java_env_set(where = "session", java_home = java_home)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/tests/testthat/test-internal_utilities_extra.R:
--------------------------------------------------------------------------------
1 | test_that("java_urls_load loads JSON correctly", {
2 | # Real test of the JSON file included in the package
3 | urls <- rJavaEnv:::java_urls_load()
4 | expect_type(urls, "list")
5 | expect_true("Corretto" %in% names(urls))
6 | })
7 |
8 | test_that("urls_test_all checks URLs without network", {
9 | # Mock internal loader to return small subset
10 | local_mocked_bindings(
11 | java_urls_load = function() list(
12 | TestDist = list(
13 | linux = list(x64 = "http://example.com/jdk-{version}.tar.gz")
14 | )
15 | ),
16 | .package = "rJavaEnv"
17 | )
18 |
19 | # Mock curl to avoid network
20 | local_mocked_bindings(
21 | curl_fetch_memory = function(...) list(status_code = 200),
22 | .package = "curl"
23 | )
24 |
25 | res <- rJavaEnv:::urls_test_all()
26 | expect_type(res, "list")
27 | expect_equal(res[["TestDist-linux-x64"]]$status, 200)
28 | })
29 |
30 | test_that("java_version_check_rscript function exists", {
31 | # We cannot safely test this function without loading rJava, which crashes when
32 | # Java is not configured. Testing the error path is also unsafe because mocking
33 | # base functions like Sys.setenv or list.files interferes with testthat's own operations.
34 | # Instead, we just verify the function exists and has correct structure.
35 |
36 | expect_true(exists("java_version_check_rscript", where = asNamespace("rJavaEnv")))
37 | expect_type(rJavaEnv:::java_version_check_rscript, "closure")
38 | })
39 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_env_linux.R:
--------------------------------------------------------------------------------
1 | test_that("java_env_set_session function exists and handles basic cases", {
2 | # Mocking base functions like file.exists or list.files interferes with R's package
3 | # loading system and testthat's operations. Instead, we test the non-Linux path which
4 | # doesn't require complex mocks.
5 |
6 | # Mock installed.packages to avoid rJava checks
7 | local_mocked_bindings(
8 | installed.packages = function(...) matrix(character(0), nrow=0, ncol=2),
9 | .package = "utils"
10 | )
11 |
12 | # On non-Linux platforms, the function just sets environment variables
13 | # This should work without triggering libjvm.so loading
14 | skip_on_os("linux") # Skip on actual Linux to avoid system-specific issues
15 |
16 | expect_no_error(
17 | rJavaEnv:::java_env_set_session(java_home = "/mock/java")
18 | )
19 | })
20 |
21 | test_that("java_env_set_session warns if rJava is already loaded", {
22 | # Mock installed.packages to say rJava is installed
23 | local_mocked_bindings(
24 | installed.packages = function() matrix(c("rJava"), dimnames=list(NULL, "Package")),
25 | .package = "utils"
26 | )
27 |
28 | # Mock loadedNamespaces to say rJava is loaded
29 | local_mocked_bindings(
30 | loadedNamespaces = function() c("base", "rJava"),
31 | .package = "base"
32 | )
33 |
34 | # Expect the warning message
35 | expect_message(
36 | rJavaEnv:::java_env_set_session(java_home = "/mock/java"),
37 | "You have `rJava` R package loaded"
38 | )
39 | })
40 |
--------------------------------------------------------------------------------
/.github/workflows/pkgdown.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 | release:
9 | types: [published]
10 | workflow_dispatch:
11 |
12 | name: pkgdown
13 |
14 | permissions: read-all
15 |
16 | jobs:
17 | pkgdown:
18 | runs-on: ubuntu-latest
19 | # Only restrict concurrency for non-PR jobs
20 | concurrency:
21 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
22 | env:
23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
24 | permissions:
25 | contents: write
26 | steps:
27 | - uses: actions/checkout@v4
28 |
29 | - uses: r-lib/actions/setup-pandoc@v2
30 |
31 | - uses: r-lib/actions/setup-r@v2
32 | with:
33 | use-public-rspm: true
34 |
35 | - uses: r-lib/actions/setup-r-dependencies@v2
36 | with:
37 | extra-packages: any::pkgdown, any::bookdown, local::.
38 | needs: website
39 |
40 | - name: Build site
41 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
42 | shell: Rscript {0}
43 |
44 | - name: Deploy to GitHub pages 🚀
45 | if: github.event_name != 'pull_request'
46 | uses: JamesIves/github-pages-deploy-action@v4.5.0
47 | with:
48 | clean: false
49 | branch: gh-pages
50 | folder: docs
51 |
--------------------------------------------------------------------------------
/man/rje_consent.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/consent.R
3 | \name{rje_consent}
4 | \alias{rje_consent}
5 | \title{Obtain User Consent for rJavaEnv}
6 | \usage{
7 | rje_consent(provided = FALSE)
8 | }
9 | \arguments{
10 | \item{provided}{Logical indicating if consent is already provided.
11 | To provide consent in non-interactive \R sessions
12 | use \code{rJavaEnv::rje_consent(provided = TRUE)}. Default is \code{FALSE}.}
13 | }
14 | \value{
15 | \code{TRUE} if consent is given, otherwise an error is raised.
16 | }
17 | \description{
18 | Get user consent for rJavaEnv to write and update files on the file system.
19 | rJavaEnv needs permission to manage files in your project and cache directories
20 | to function correctly.
21 | }
22 | \details{
23 | In line with \href{https://cran.r-project.org/web/packages/policies.html}{CRAN policies}, explicit user consent is required before making these changes.
24 | Please call \code{rJavaEnv::consent()} to provide consent.
25 |
26 | Alternatively, you can set the following \R option
27 | (especially useful for non-interactive R sessions):
28 |
29 | \if{html}{\out{
}}\preformatted{options(rJavaEnv.consent = TRUE)
30 | }\if{html}{\out{
}}
31 |
32 | The function is based on the code of the \code{renv} package.
33 | Copyright 2023 Posit Software, PBC
34 | License: https://github.com/rstudio/renv/blob/main/LICENSE
35 | }
36 | \examples{
37 | \dontrun{
38 |
39 | # to provide consent and prevent other functions from interrupting to get the consent
40 | rje_consent(provided = TRUE)
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/.github/workflows/render-README.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | paths: ['README.Rmd']
6 | workflow_dispatch:
7 | paths: ['README.Rmd']
8 |
9 |
10 | name: Render README
11 |
12 | jobs:
13 | render-rmarkdown:
14 | runs-on: ubuntu-latest
15 | env:
16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
17 | steps:
18 | - name: Checkout repo
19 | uses: actions/checkout@v3
20 | with:
21 | fetch-depth: 0
22 |
23 | - uses: r-lib/actions/setup-pandoc@v2
24 |
25 | - uses: r-lib/actions/setup-r@v2
26 |
27 | - name: install rmarkdown from PPM
28 | run: Rscript -e 'install.packages("rmarkdown", repos=c("https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"))'
29 |
30 | - name: Install devtools and the target package
31 | run: |
32 | Rscript -e 'install.packages("rJavaEnv", repos=c("https://community.r-multiverse.org", "https://packagemanager.posit.co/cran/__linux__/jammy/latest"))'
33 |
34 |
35 | - name: Render README.Rmd
36 | run: |
37 | Rscript -e 'rmarkdown::render("README.Rmd")'
38 |
39 | - name: Commit results
40 | run: |
41 | git config --local user.name "github-actions[bot]"
42 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
43 | git add README.md
44 | git commit -m 'Re-build README.Rmd' || echo "No changes to commit"
45 | git push origin || echo "No changes to commit"
46 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | name: R-CMD-check
10 |
11 | permissions: read-all
12 |
13 | jobs:
14 | R-CMD-check:
15 | runs-on: ${{ matrix.config.os }}
16 |
17 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
18 |
19 | strategy:
20 | fail-fast: false
21 | matrix:
22 | config:
23 | - {os: macos-latest, r: 'release'}
24 | - {os: windows-latest, r: 'release'}
25 | - {os: windows-latest, r: 'oldrel-4'}
26 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
27 | - {os: ubuntu-latest, r: 'release'}
28 | - {os: ubuntu-latest, r: 'oldrel-1'}
29 |
30 | env:
31 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
32 | R_KEEP_PKG_SOURCE: yes
33 |
34 | steps:
35 | - uses: actions/checkout@v4
36 |
37 | - uses: r-lib/actions/setup-pandoc@v2
38 |
39 | - uses: r-lib/actions/setup-r@v2
40 | with:
41 | r-version: ${{ matrix.config.r }}
42 | http-user-agent: ${{ matrix.config.http-user-agent }}
43 | use-public-rspm: true
44 |
45 | - uses: r-lib/actions/setup-r-dependencies@v2
46 | with:
47 | extra-packages: any::rcmdcheck
48 | needs: check
49 |
50 | - uses: r-lib/actions/check-r-package@v2
51 | with:
52 | upload-snapshots: true
53 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
54 |
--------------------------------------------------------------------------------
/man/java_list.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_manage.R
3 | \name{java_list}
4 | \alias{java_list}
5 | \title{List the contents of the Java versions installed or cached}
6 | \usage{
7 | java_list(
8 | type = c("project", "installed", "distrib"),
9 | output = c("data.frame", "vector"),
10 | quiet = TRUE,
11 | target_dir = NULL
12 | )
13 | }
14 | \arguments{
15 | \item{type}{The type of cache to list: "distrib", "installed", or "project". Defaults to "project".}
16 |
17 | \item{output}{The format of the output: \verb{data.frame`` or }vector``. Defaults to \code{data.frame}.}
18 |
19 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
20 |
21 | \item{target_dir}{The cache directory to list. Defaults to the user-specific data directory for "distrib" and "installed", and the current working directory for "project".}
22 | }
23 | \value{
24 | A \code{dataframe} or \code{character} \code{vector} with the contents of the specified cache or project directory.
25 | }
26 | \description{
27 | This function lists one of the following:
28 | \itemize{
29 | \item \code{project} - list the contents of the Java symlinked/copied in the current project or directory specified by \code{target_dir}
30 | \item \code{distrib} - list the contents of the downloaded Java distributions cache in default location or specified by \code{target_dir}
31 | \item \code{installed} - list the contents of the Java installations cache (unpacked distributions) in default location or specified by \code{target_dir}
32 | }
33 | }
34 | \examples{
35 | \dontrun{
36 | java_list("project")
37 | java_list("installed")
38 | java_list("distrib")
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/man/java_valid_versions.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_valid_versions.R
3 | \name{java_valid_versions}
4 | \alias{java_valid_versions}
5 | \title{Retrieve Valid Java Versions}
6 | \usage{
7 | java_valid_versions(
8 | distribution = "Corretto",
9 | platform = platform_detect()$os,
10 | arch = platform_detect()$arch,
11 | force = FALSE
12 | )
13 | }
14 | \arguments{
15 | \item{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.}
16 |
17 | \item{platform}{The platform for which to download the Java distribution. Defaults to the current platform.}
18 |
19 | \item{arch}{The architecture for which to download the Java distribution. Defaults to the current architecture.}
20 |
21 | \item{force}{Logical. If TRUE, forces a fresh API call even if a cached value exists. Defaults to FALSE.}
22 | }
23 | \value{
24 | A character vector of valid Java versions.
25 | }
26 | \description{
27 | This function retrieves a list of valid Java versions by querying an appropriate API endpoint based on the chosen distribution.
28 | 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),
29 | the function falls back to a pre-defined list of Java versions.
30 | }
31 | \examples{
32 | \dontrun{
33 | # Retrieve valid Java versions (cached if available) using Amazon Corretto endpoint
34 | versions <- java_valid_versions()
35 |
36 | # Force refresh the list of Java versions using the Oracle endpoint
37 | versions <- java_valid_versions(distribution = "Corretto", force = TRUE)
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_valid_versions.R:
--------------------------------------------------------------------------------
1 | test_that("java_valid_versions returns a character vector with required versions", {
2 | skip_on_cran()
3 | # Clear any cached values
4 | options(
5 | rJavaEnv.valid_versions_cache = NULL,
6 | rJavaEnv.valid_versions_timestamp = NULL
7 | )
8 |
9 | # Retrieve Java versions
10 | versions <- java_valid_versions()
11 |
12 | # Verify the result is a character vector and contains "8" and "11"
13 | expect_type(versions, "character")
14 | expect_true("8" %in% versions)
15 | expect_true("11" %in% versions)
16 | expect_true("24" %in% versions)
17 | })
18 |
19 | test_that("force parameter bypasses the cache", {
20 | # Set a fake cache in the options
21 | fake_cache <- c("8", "11")
22 | options(
23 | rJavaEnv.valid_versions_cache = fake_cache,
24 | rJavaEnv.valid_versions_timestamp = Sys.time()
25 | )
26 |
27 | # Force a refresh by setting force = TRUE.
28 | versions_force <- java_valid_versions(force = TRUE)
29 |
30 | # The returned value should not equal the fake cache.
31 | expect_false(identical(versions_force, fake_cache))
32 | })
33 |
34 | test_that("fallback is used when the API call fails", {
35 | # Clear the cache to force an API call.
36 | options(
37 | rJavaEnv.valid_versions_cache = NULL,
38 | rJavaEnv.valid_versions_timestamp = NULL
39 | )
40 |
41 | local_mocked_bindings(
42 | read_json = function(...) stop("Simulated API failure"),
43 | .package = "jsonlite"
44 | )
45 |
46 | fallback <- getOption("rJavaEnv.fallback_valid_versions_current_platform")
47 | versions <- java_valid_versions(force = TRUE)
48 |
49 | ## When the API call fails, the fallback list should be returned.
50 | expect_equal(versions, fallback)
51 | })
52 |
--------------------------------------------------------------------------------
/man/java_install.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_install.R
3 | \name{java_install}
4 | \alias{java_install}
5 | \title{Install Java from a distribution file}
6 | \usage{
7 | java_install(
8 | java_distrib_path,
9 | project_path = NULL,
10 | autoset_java_env = TRUE,
11 | quiet = FALSE,
12 | force = FALSE
13 | )
14 | }
15 | \arguments{
16 | \item{java_distrib_path}{A \code{character} vector of length 1 containing the path to the Java distribution file.}
17 |
18 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
19 |
20 | \item{autoset_java_env}{A \code{logical} indicating whether to set the \code{JAVA_HOME} and \code{PATH} environment variables to the installed Java directory. Defaults to \code{TRUE}.}
21 |
22 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
23 |
24 | \item{force}{A logical. Whether to overwrite an existing installation. Defaults to \code{FALSE}.}
25 | }
26 | \value{
27 | The path to the installed Java directory.
28 | }
29 | \description{
30 | Unpack Java distribution file into cache directory and link the installation into a project directory, optionally setting the \code{JAVA_HOME} and \code{PATH} environment variables to the Java version that was just installed.
31 | }
32 | \examples{
33 | \dontrun{
34 |
35 | # set cache dir to temporary directory
36 | options(rJavaEnv.cache_path = tempdir())
37 | # download, install and autoset environmnet variables for Java 17
38 | java_17_distrib <- java_download(version = "17")
39 | java_install(java_distrib_path = java_17_distrib, project_path = tempdir())
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.github/workflows/update-citation-cff.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples
2 | # The action runs when:
3 | # - A new release is published
4 | # - The DESCRIPTION or inst/CITATION are modified
5 | # - Can be run manually
6 | # For customizing the triggers, visit https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
7 | on:
8 | release:
9 | types: [published]
10 | push:
11 | branches: [master, main]
12 | paths:
13 | - DESCRIPTION
14 | - inst/CITATION
15 | workflow_dispatch:
16 |
17 | name: Update CITATION.cff
18 |
19 | jobs:
20 | update-citation-cff:
21 | runs-on: macos-latest
22 | env:
23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
24 | steps:
25 | - uses: actions/checkout@v3
26 | - uses: r-lib/actions/setup-r@v2
27 | - uses: r-lib/actions/setup-r-dependencies@v2
28 | with:
29 | extra-packages: |
30 | any::cffr
31 | any::V8
32 |
33 | - name: Update CITATION.cff
34 | run: |
35 |
36 | library(cffr)
37 |
38 | # Customize with your own code
39 | # See https://docs.ropensci.org/cffr/articles/cffr.html
40 |
41 | # Write your own keys
42 | mykeys <- list()
43 |
44 | # Create your CITATION.cff file
45 | cff_write(keys = mykeys)
46 |
47 | shell: Rscript {0}
48 |
49 | - name: Commit results
50 | run: |
51 | git config --local user.name "github-actions[bot]"
52 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
53 | git add CITATION.cff
54 | git commit -m 'Update CITATION.cff' || echo "No changes to commit"
55 | git push origin || echo "No changes to commit"
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/R/java_quick_install.R:
--------------------------------------------------------------------------------
1 | #' Download and install and set Java in current working/project directory
2 | #'
3 | #' @inheritParams java_download
4 | #' @inheritParams java_install
5 | #' @inheritParams global_quiet_param
6 | #' @return Invisibly returns the path to the Java home directory. If quiet is set to `FALSE`, also prints a message indicating that Java was installed and set in the current working/project directory.
7 | #' @export
8 | #'
9 | #' @examples
10 | #' \dontrun{
11 | #'
12 | #' # quick download, unpack, install and set in current working directory default Java version (21)
13 | #' java_quick_install(17, temp_dir = TRUE)
14 | #' }
15 | java_quick_install <- function(
16 | version = 21,
17 | distribution = "Corretto",
18 | project_path = NULL,
19 | platform = platform_detect()$os,
20 | arch = platform_detect()$arch,
21 | quiet = FALSE,
22 | temp_dir = FALSE
23 | ) {
24 | rje_consent_check()
25 |
26 | if (temp_dir) {
27 | temp_dir <- tempdir()
28 | setwd(temp_dir)
29 | if (!dir.exists("rJavaEnv_cache")) {
30 | dir.create("rJavaEnv_cache", recursive = TRUE)
31 | }
32 | cache_path <- file.path(temp_dir, "rJavaEnv_cache")
33 | if (!dir.exists("rJavaEnv_project")) {
34 | dir.create("rJavaEnv_project", recursive = TRUE)
35 | }
36 | project_path <- file.path(temp_dir, "rJavaEnv_project")
37 | } else {
38 | cache_path <- getOption("rJavaEnv.cache_path")
39 | }
40 |
41 | java_distrib_path <- java_download(
42 | version = version,
43 | distribution = distribution,
44 | cache_path = cache_path,
45 | platform = platform,
46 | arch = arch,
47 | quiet = quiet
48 | )
49 |
50 | java_home <- java_install(
51 | java_distrib_path,
52 | project_path = project_path,
53 | autoset_java_env = TRUE,
54 | quiet = quiet
55 | )
56 | return(invisible(java_home))
57 | }
58 |
--------------------------------------------------------------------------------
/.github/workflows/java-live-tests.yml:
--------------------------------------------------------------------------------
1 | # GitHub Actions workflow to run the long-running live Java download tests.
2 | # This test downloads, installs, checks, and clears every supported Java version.
3 | # It is run on a schedule to avoid slowing down pull request checks.
4 |
5 | name: R Java Live Integration Tests
6 |
7 | on:
8 | # Allows you to run this workflow manually from the Actions tab
9 | workflow_dispatch:
10 |
11 | schedule:
12 | # Runs at 00:00 UTC on Saturday.
13 | # This corresponds to 1:00 AM in Berlin (CET, UTC+1) during standard time,
14 | # and 2:00 AM (CEST, UTC+2) during daylight saving time.
15 | - cron: '0 0 * * 6'
16 |
17 |
18 | jobs:
19 | R-CMD-check:
20 | runs-on: ${{ matrix.config.os }}
21 |
22 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
23 |
24 | strategy:
25 | fail-fast: false
26 | matrix:
27 | config:
28 | - {os: macos-latest, r: 'release'}
29 | - {os: windows-latest, r: 'release'}
30 | - {os: ubuntu-latest, r: 'release'}
31 |
32 | env:
33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
34 | R_KEEP_PKG_SOURCE: yes
35 | RUN_JAVA_DOWNLOAD_TESTS: "TRUE"
36 | RUN_JAVA_DOWNLOAD_TESTS_QUIET: "FALSE"
37 | RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD: "TRUE"
38 |
39 | steps:
40 | - uses: actions/checkout@v4
41 |
42 | - uses: r-lib/actions/setup-pandoc@v2
43 |
44 | - uses: r-lib/actions/setup-r@v2
45 | with:
46 | r-version: ${{ matrix.config.r }}
47 | http-user-agent: ${{ matrix.config.http-user-agent }}
48 | use-public-rspm: true
49 |
50 | - uses: r-lib/actions/setup-r-dependencies@v2
51 | with:
52 | extra-packages: any::rcmdcheck
53 | needs: check
54 |
55 | - uses: r-lib/actions/check-r-package@v2
56 | with:
57 | upload-snapshots: true
58 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
59 |
--------------------------------------------------------------------------------
/man/java_build_env_set.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_build_env.R
3 | \name{java_build_env_set}
4 | \alias{java_build_env_set}
5 | \title{Set up the environment for building R packages with Java dependencies from source}
6 | \usage{
7 | java_build_env_set(
8 | java_home = Sys.getenv("JAVA_HOME"),
9 | where = c("session", "project", "both"),
10 | project_path = NULL,
11 | quiet = FALSE
12 | )
13 | }
14 | \arguments{
15 | \item{java_home}{The path to the desired \code{JAVA_HOME}. Defaults to the value of the \code{JAVA_HOME} environment variable.}
16 |
17 | \item{where}{Where to set the build environment: "session", "project", or "both". Defaults to "session". When "both" or "project" is selected, the function updates the .Rprofile file in the project directory.}
18 |
19 | \item{project_path}{The path to the project directory, required when \code{where} is "project" or "both". Defaults to the current working directory.}
20 |
21 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
22 | }
23 | \value{
24 | Invisibly returns \code{NULL} after setting the environment variables.
25 | }
26 | \description{
27 | This function configures the current R session with the necessary environment
28 | variables to compile Java-dependent packages like 'rJava' from source. \strong{Note: this function is still experimental.}
29 | }
30 | \examples{
31 | \dontrun{
32 | # Download and install Java 17
33 | java_17_distrib <- java_download(version = "17", temp_dir = TRUE)
34 | java_home_path <- java_install(
35 | java_distrib_path = java_17_distrib,
36 | project_path = tempdir(),
37 | autoset_java_env = FALSE # Manually set env
38 | )
39 |
40 | # Set up the build environment in the current session
41 | java_build_env_set(java_home = java_home_path)
42 |
43 | # Now, install rJava from source
44 | install.packages("rJava", type = "source", repos = "https://cloud.r-project.org")
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/man/java_env_set.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_env.R
3 | \name{java_env_set}
4 | \alias{java_env_set}
5 | \title{Set the \code{JAVA_HOME} and \code{PATH} environment variables to a given path}
6 | \usage{
7 | java_env_set(
8 | where = c("session", "both", "project"),
9 | java_home,
10 | project_path = NULL,
11 | quiet = FALSE
12 | )
13 | }
14 | \arguments{
15 | \item{where}{Where to set the \code{JAVA_HOME}: "session", "project", or "both". Defaults to "session" and only updates the paths in the current R session. When "both" or "project" is selected, the function updates the .Rprofile file in the project directory to set the JAVA_HOME and PATH environment variables at the start of the R session.}
16 |
17 | \item{java_home}{The path to the desired \code{JAVA_HOME}.}
18 |
19 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
20 |
21 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
22 | }
23 | \value{
24 | Nothing. Sets the JAVA_HOME and PATH environment variables.
25 | }
26 | \description{
27 | Set the \code{JAVA_HOME} and \code{PATH} environment variables to a given path
28 | }
29 | \examples{
30 | \dontrun{
31 | # download, install Java 17
32 | java_17_distrib <- java_download(version = "17", temp_dir = TRUE)
33 | java_home <- java_install(
34 | java_distrib_path = java_17_distrib,
35 | project_path = tempdir(),
36 | autoset_java_env = FALSE
37 | )
38 |
39 | # now manually set the JAVA_HOME and PATH environment variables in current session
40 | java_env_set(
41 | where = "session",
42 | java_home = java_home
43 | )
44 |
45 | # or set JAVA_HOME and PATH in the spefific projects' .Rprofile
46 | java_env_set(
47 | where = "project",
48 | java_home = java_home,
49 | project_path = tempdir()
50 | )
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_wrappers.R:
--------------------------------------------------------------------------------
1 | # Tests for java_quick_install() and use_java()
2 |
3 | test_that("java_quick_install executes flow correctly", {
4 | # Setup temp directories
5 | local_cache <- withr::local_tempdir()
6 | local_proj <- withr::local_tempdir()
7 |
8 | # Mock dependencies to prevent actual download/install
9 | local_mocked_bindings(
10 | java_download = function(...) file.path("mock", "distrib.tar.gz"),
11 | java_install = function(...) file.path("mock", "java_home"),
12 | rje_consent_check = function(...) TRUE,
13 | .package = "rJavaEnv"
14 | )
15 |
16 | # Test 1: Standard Execution
17 | expect_invisible(
18 | result <- java_quick_install(
19 | version = 17,
20 | project_path = local_proj,
21 | quiet = TRUE
22 | )
23 | )
24 | expect_equal(result, file.path("mock", "java_home"))
25 |
26 | # Test 2: Temp Directory execution
27 | # We can't easily check internal variables, but we ensure it runs without error
28 | # and returns the mocked path, implying logic held up.
29 |
30 | expect_invisible(
31 | res_temp <- java_quick_install(version = 17, temp_dir = TRUE, quiet = TRUE)
32 | )
33 | expect_equal(res_temp, file.path("mock", "java_home"))
34 | })
35 |
36 | test_that("use_java executes flow correctly", {
37 | # Mock dependencies
38 | local_mocked_bindings(
39 | java_download = function(...) "mock_distrib_path",
40 | java_unpack = function(...) "mock_install_path",
41 | # Capture the arguments passed to java_env_set to verify logic
42 | java_env_set = function(where, java_home, quiet) {
43 | if (where != "session") stop("Wrong 'where' argument")
44 | if (java_home != "mock_install_path") stop("Wrong 'java_home' argument")
45 | invisible(NULL)
46 | },
47 | java_valid_versions = function(...) c("8", "11", "17", "21"),
48 | .package = "rJavaEnv"
49 | )
50 |
51 | # Should run silently and pass verification inside the mock
52 | expect_silent(use_java(version = 17, quiet = TRUE))
53 |
54 | # Test message output when not quiet
55 | expect_message(use_java(version = 17, quiet = FALSE), "Java version 17 was set")
56 | })
57 |
--------------------------------------------------------------------------------
/man/java_download.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_download.R
3 | \name{java_download}
4 | \alias{java_download}
5 | \title{Download a Java distribution}
6 | \usage{
7 | java_download(
8 | version = 21,
9 | distribution = "Corretto",
10 | cache_path = getOption("rJavaEnv.cache_path"),
11 | platform = platform_detect()$os,
12 | arch = platform_detect()$arch,
13 | quiet = FALSE,
14 | force = FALSE,
15 | temp_dir = FALSE
16 | )
17 | }
18 | \arguments{
19 | \item{version}{\code{Integer} or \code{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 \code{integer}) or any newer version if it is available for the selected distribution. For \code{macOS} on \code{aarch64} architecture (Apple Silicon) certain \code{Java} versions are not available.}
20 |
21 | \item{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.}
22 |
23 | \item{cache_path}{The destination directory to download the Java distribution to. Defaults to a user-specific data directory.}
24 |
25 | \item{platform}{The platform for which to download the Java distribution. Defaults to the current platform.}
26 |
27 | \item{arch}{The architecture for which to download the Java distribution. Defaults to the current architecture.}
28 |
29 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
30 |
31 | \item{force}{A logical. Whether the distribution file should be overwritten or not. Defaults to \code{FALSE}.}
32 |
33 | \item{temp_dir}{A logical. Whether the file should be saved in a temporary directory. Defaults to \code{FALSE}.}
34 | }
35 | \value{
36 | The path to the downloaded Java distribution file.
37 | }
38 | \description{
39 | Download a Java distribution
40 | }
41 | \examples{
42 | \dontrun{
43 |
44 | # download distribution of Java version 17
45 | java_download(version = "17", temp_dir = TRUE)
46 |
47 | # download default Java distribution (version 21)
48 | java_download(temp_dir = TRUE)
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/.github/workflows/test-coverage.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | workflow_dispatch:
8 |
9 | name: test-coverage.yaml
10 |
11 | permissions: read-all
12 |
13 | jobs:
14 | test-coverage:
15 | runs-on: ubuntu-latest
16 | env:
17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
18 | RUN_JAVA_DOWNLOAD_TESTS: "TRUE"
19 | RUN_JAVA_DOWNLOAD_TESTS_QUIET: "FALSE"
20 | RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD: "TRUE"
21 |
22 | steps:
23 | - uses: actions/checkout@v4
24 |
25 | - uses: r-lib/actions/setup-r@v2
26 | with:
27 | use-public-rspm: true
28 |
29 | - uses: r-lib/actions/setup-r-dependencies@v2
30 | with:
31 | extra-packages: any::covr, any::xml2
32 | needs: coverage
33 |
34 | - name: Test coverage
35 | run: |
36 | cov <- covr::package_coverage(
37 | quiet = FALSE,
38 | clean = FALSE,
39 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
40 | )
41 | print(cov)
42 | covr::to_cobertura(cov)
43 | shell: Rscript {0}
44 |
45 | - uses: codecov/codecov-action@v5
46 | with:
47 | # Fail if error if not on PR, or if on PR and token is given
48 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
49 | files: ./cobertura.xml
50 | plugins: noop
51 | disable_search: true
52 | token: ${{ secrets.CODECOV_TOKEN }}
53 |
54 | - name: Show testthat output
55 | if: always()
56 | run: |
57 | ## --------------------------------------------------------------------
58 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
59 | shell: bash
60 |
61 | - name: Upload test results
62 | if: failure()
63 | uses: actions/upload-artifact@v4
64 | with:
65 | name: coverage-test-failures
66 | path: ${{ runner.temp }}/package
67 |
--------------------------------------------------------------------------------
/inst/resources/consent-info:
--------------------------------------------------------------------------------
1 | `rJavaEnv`: Manage Java Environments for R Projects
2 |
3 | Welcome to `rJavaEnv`! It looks like this is your first time using `rJavaEnv`.
4 | This message will guide you through some of the key features and how `rJavaEnv` works.
5 |
6 | `rJavaEnv` will manage Java Development Kits (JDKs) specifically for your R projects,
7 | ensuring that each project uses the appropriate Java version
8 | without affecting other projects or your system-wide Java installation.
9 |
10 | Here's what `rJavaEnv` will do:
11 |
12 | - Create a 'rjavaenv' folder in your project/current working directory.
13 | - Generate necessary configuration files in the project/current working directory.
14 | - Update your $JAVA_HOME and $PATH variables within the current R session.
15 |
16 | `rJavaEnv` will also update some existing files in your project/current working directory, such as:
17 |
18 | - .Rprofile
19 |
20 | Additionally, `rJavaEnv` maintains a cache of Java distributions and installations at:
21 |
22 | - ${rJavaEnv_CACHE}
23 |
24 | You can customize this path by setting the option `options(rJavaEnv.cache_path = 'path/to/your/java/cache')`.
25 | Alternatively, you can set the cache folder as argument `cache_path` package functions that have option.
26 | The same cache folder is used for both zipped java distributions and extracted distribution files.
27 |
28 | For more information, read the introductory vignette with `vignette("rJavaEnv")` and browse the package documentation online at https://www.ekotov.pro/rJavaEnv/.
29 |
30 | Whenever you install any `Java` JDK, kindly read the respective software license and agree to it before use.
31 | For the current default JDK installed with rJavaEnv, which is Amazon Corretto, please find the license for the version
32 | you are installing at https://github.com/corretto/.
33 |
34 | Finally, if you are on a Linux system that did not have any 'Java' version previoulsy installed and you are not using pre-build 'R' package binaries (for example from 'Posit Package Manager') and instead install all 'R' packages from source, after this step you may have to quit R, follow these steps: https://solutions.posit.co/envs-pkgs/using-rjava/#reconfigure-r to set configure 'Java' for 'R', and only then install 'rJava', as otherwise 'rJava' cannot be built from source.
35 |
--------------------------------------------------------------------------------
/man/java_quick_install.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/java_quick_install.R
3 | \name{java_quick_install}
4 | \alias{java_quick_install}
5 | \title{Download and install and set Java in current working/project directory}
6 | \usage{
7 | java_quick_install(
8 | version = 21,
9 | distribution = "Corretto",
10 | project_path = NULL,
11 | platform = platform_detect()$os,
12 | arch = platform_detect()$arch,
13 | quiet = FALSE,
14 | temp_dir = FALSE
15 | )
16 | }
17 | \arguments{
18 | \item{version}{\code{Integer} or \code{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 \code{integer}) or any newer version if it is available for the selected distribution. For \code{macOS} on \code{aarch64} architecture (Apple Silicon) certain \code{Java} versions are not available.}
19 |
20 | \item{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.}
21 |
22 | \item{project_path}{A \code{character} vector of length 1 containing the project directory where Java should be installed. If not specified or \code{NULL}, defaults to the current working directory.}
23 |
24 | \item{platform}{The platform for which to download the Java distribution. Defaults to the current platform.}
25 |
26 | \item{arch}{The architecture for which to download the Java distribution. Defaults to the current architecture.}
27 |
28 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
29 |
30 | \item{temp_dir}{A logical. Whether the file should be saved in a temporary directory. Defaults to \code{FALSE}.}
31 | }
32 | \value{
33 | Invisibly returns the path to the Java home directory. If quiet is set to \code{FALSE}, also prints a message indicating that Java was installed and set in the current working/project directory.
34 | }
35 | \description{
36 | Download and install and set Java in current working/project directory
37 | }
38 | \examples{
39 | \dontrun{
40 |
41 | # quick download, unpack, install and set in current working directory default Java version (21)
42 | java_quick_install(17, temp_dir = TRUE)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/vignettes/bibliography.bib:
--------------------------------------------------------------------------------
1 | @article{pereira_r5r_2021,
2 | title = {r5r: Rapid Realistic Routing on Multimodal Transport Networks with {R}$^{\textrm{5}}$ in R},
3 | shorttitle = {r5r},
4 | url = {https://findingspress.org/article/21262-r5r-rapid-realistic-routing-on-multimodal-transport-networks-with-r-5-in-r},
5 | doi = {10.32866/001c.21262},
6 | language = {en},
7 | urldate = {2021-03-04},
8 | journal = {Findings},
9 | author = {Pereira, Rafael H. M. and Saraiva, Marcus and Herszenhut, Daniel and Braga, Carlos Kaue Vieira and Conway, Matthew Wigginton},
10 | month = mar,
11 | year = {2021},
12 | note = {Publisher: Network Design Lab}
13 | }
14 |
15 | ,
16 |
17 | @Manual{rjdbc,
18 | title = {RJDBC: Provides Access to Databases Through the JDBC Interface},
19 | author = {Simon Urbanek},
20 | year = {2022},
21 | note = {R package version 0.2-10},
22 | url = {https://CRAN.R-project.org/package=RJDBC},
23 | }
24 | ,
25 |
26 | @Manual{mailr,
27 | title = {mailR: A Utility to Send Emails from R},
28 | author = {Rahul Premraj},
29 | year = {2021},
30 | note = {R package version 0.8},
31 | url = {https://CRAN.R-project.org/package=mailR},
32 | }
33 |
34 | ,
35 |
36 |
37 | @Article{rweka,
38 | title = {Open-Source Machine Learning: {R} Meets {Weka}},
39 | author = {Kurt Hornik and Christian Buchta and Achim Zeileis},
40 | journal = {Computational Statistics},
41 | year = {2009},
42 | volume = {24},
43 | number = {2},
44 | pages = {225--232},
45 | doi = {10.1007/s00180-008-0119-7},
46 | }
47 |
48 | ,
49 |
50 | @Manual{opennlp,
51 | title = {openNLP: Apache OpenNLP Tools Interface},
52 | author = {Kurt Hornik},
53 | year = {2019},
54 | note = {R package version 0.2-7},
55 | url = {https://CRAN.R-project.org/package=openNLP},
56 | }
57 |
58 | ,
59 |
60 | @Manual{xlsx,
61 | title = {xlsx: Read, Write, Format Excel 2007 and Excel 97/2000/XP/2003 Files},
62 | author = {Adrian Dragulescu and Cole Arendt},
63 | year = {2020},
64 | note = {R package version 0.6.5},
65 | url = {https://CRAN.R-project.org/package=xlsx},
66 | }
67 |
68 | @Manual{rjava,
69 | title = {rJava: Low-Level R to Java Interface},
70 | author = {Simon Urbanek},
71 | year = {2024},
72 | note = {R package version 1.0-11},
73 | url = {https://CRAN.R-project.org/package=rJava},
74 | }
75 |
--------------------------------------------------------------------------------
/R/use_java.R:
--------------------------------------------------------------------------------
1 | #' Install specified Java version and set the `JAVA_HOME` and `PATH` environment variables in current R session
2 | #'
3 | #' @description
4 | #' Using specified Java version, set the `JAVA_HOME` and `PATH` environment variables in the current R session. If Java distribtuion has not been downloaded yet, download it. If it was not installed into cache directory yet, install it there and then set the environment variables. This is intended as a quick and easy way to use different Java versions in R scripts that are in the same project, but require different Java versions. For example, one could use this in scripts that are called by `targets` package or `callr` package.
5 | #' @inheritParams java_download
6 | #' @inheritParams java_install
7 | #' @inheritParams global_quiet_param
8 | #' @return `NULL`. Prints the message that Java was set in the current R session if `quiet` is set to `FALSE`.
9 | #'
10 | #' @export
11 | #'
12 | #' @examples
13 | #' \dontrun{
14 | #'
15 | #' # set cache directory for Java to be in temporary directory
16 | #' options(rJavaEnv.cache_path = tempdir())
17 | #'
18 | #' # install and set Java 8 in current R session
19 | #' use_java(8)
20 | #' # check Java version
21 | #' "8" == java_check_version_cmd(quiet = TRUE)
22 | #' "8" == java_check_version_rjava(quiet = TRUE)
23 | #'
24 | #' # install and set Java 17 in current R session
25 | #' use_java(17)
26 | #' # check Java version
27 | #' "17" == java_check_version_cmd(quiet = TRUE)
28 | #' "17" == java_check_version_rjava(quiet = TRUE)
29 | #'
30 | #' }
31 | #'
32 | use_java <- function(
33 | version = NULL,
34 | distribution = "Corretto",
35 | cache_path = getOption("rJavaEnv.cache_path"),
36 | platform = platform_detect()$os,
37 | arch = platform_detect()$arch,
38 | quiet = TRUE
39 | ) {
40 | checkmate::check_vector(version, len = 1)
41 | version <- as.character(version)
42 | checkmate::assert_choice(version, java_valid_versions())
43 |
44 | java_distrib_path <- java_download(
45 | version = version,
46 | distribution = distribution,
47 | cache_path = cache_path,
48 | platform = platform,
49 | arch = arch,
50 | quiet = quiet
51 | )
52 |
53 | java_cached_install_path <- java_unpack(
54 | java_distrib_path = java_distrib_path,
55 | quiet = quiet
56 | )
57 |
58 | java_env_set(
59 | where = "session",
60 | java_home = java_cached_install_path,
61 | quiet = quiet
62 | )
63 |
64 | if (!quiet) {
65 | cli::cli_alert_success(
66 | "Java version {version} was set in the current R session"
67 | )
68 | }
69 | invisible()
70 | }
71 |
--------------------------------------------------------------------------------
/tests/testthat/helper-mocks.R:
--------------------------------------------------------------------------------
1 | # Helper function to mock global dependencies for java_install tests
2 | mock_java_globals <- function(env = parent.frame()) {
3 | # We use assignInNamespace because local_mocked_bindings was failing to mock
4 | # the functions in the package namespace reliably in this context.
5 |
6 | # Mock java_valid_versions
7 | # It is internal, but assignInNamespace handles it.
8 | if (exists("java_valid_versions", envir = asNamespace("rJavaEnv"))) {
9 | original_java_valid_versions <- get(
10 | "java_valid_versions",
11 | envir = asNamespace("rJavaEnv")
12 | )
13 | assignInNamespace(
14 | "java_valid_versions",
15 | function(...) c("8", "11", "17", "21"),
16 | ns = "rJavaEnv"
17 | )
18 | withr::defer(
19 | assignInNamespace(
20 | "java_valid_versions",
21 | original_java_valid_versions,
22 | ns = "rJavaEnv"
23 | ),
24 | envir = env
25 | )
26 | }
27 |
28 | # Mock rje_consent_check
29 | if (exists("rje_consent_check", envir = asNamespace("rJavaEnv"))) {
30 | original_rje_consent_check <- get(
31 | "rje_consent_check",
32 | envir = asNamespace("rJavaEnv")
33 | )
34 | assignInNamespace("rje_consent_check", function() TRUE, ns = "rJavaEnv")
35 | withr::defer(
36 | assignInNamespace(
37 | "rje_consent_check",
38 | original_rje_consent_check,
39 | ns = "rJavaEnv"
40 | ),
41 | envir = env
42 | )
43 | }
44 |
45 | # Mock java_unpack
46 | if (exists("java_unpack", envir = asNamespace("rJavaEnv"))) {
47 | original_java_unpack <- get("java_unpack", envir = asNamespace("rJavaEnv"))
48 |
49 | mock_unpack <- function(java_distrib_path, ...) {
50 | filename <- basename(java_distrib_path)
51 | parts <- strsplit(gsub("\\.tar\\.gz|\\.zip", "", filename), "-")[[1]]
52 | version <- parts[parts %in% c("8", "11", "17", "21")][1]
53 | arch <- parts[parts %in% c("x64", "aarch64")][1]
54 | platform <- parts[parts %in% c("linux", "windows", "macos")][1]
55 |
56 | # Use a generic, hardcoded root path instead of calling getOption().
57 | # This makes the mock independent of the state being tested.
58 | file.path(
59 | "/mock/cache/path",
60 | "installed",
61 | platform,
62 | arch,
63 | version
64 | )
65 | }
66 |
67 | assignInNamespace("java_unpack", mock_unpack, ns = "rJavaEnv")
68 | withr::defer(
69 | assignInNamespace("java_unpack", original_java_unpack, ns = "rJavaEnv"),
70 | envir = env
71 | )
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/R/onLoad.R:
--------------------------------------------------------------------------------
1 | .onLoad <- function(libname, pkgname) {
2 | op <- options()
3 | op.rJavaEnv <- list(
4 | # Default folder choice (in line with renv package)
5 | rJavaEnv.cache_path = tools::R_user_dir("rJavaEnv", which = "cache"),
6 | rJavaEnv.valid_versions_cache = NULL,
7 | rJavaEnv.valid_versions_timestamp = NULL,
8 | # Fallback lists for various platforms
9 | rJavaEnv.fallback_valid_versions_macos_aarch64 = c(
10 | "8",
11 | "11",
12 | "17",
13 | "18",
14 | "19",
15 | "20",
16 | "21",
17 | "22",
18 | "23",
19 | "24",
20 | "25"
21 | ),
22 | rJavaEnv.fallback_valid_versions_macos_x64 = c(
23 | "8",
24 | "11",
25 | "15",
26 | "16",
27 | "17",
28 | "18",
29 | "19",
30 | "20",
31 | "21",
32 | "22",
33 | "23",
34 | "24",
35 | "25"
36 | ),
37 | rJavaEnv.fallback_valid_versions_linux_aarch64 = c(
38 | "8",
39 | "11",
40 | "15",
41 | "16",
42 | "17",
43 | "18",
44 | "19",
45 | "20",
46 | "21",
47 | "22",
48 | "23",
49 | "24",
50 | "25"
51 | ),
52 | rJavaEnv.fallback_valid_versions_linux_x64 = c(
53 | "8",
54 | "11",
55 | "15",
56 | "16",
57 | "17",
58 | "18",
59 | "19",
60 | "20",
61 | "21",
62 | "22",
63 | "23",
64 | "24",
65 | "25"
66 | ),
67 | rJavaEnv.fallback_valid_versions_windows_x64 = c(
68 | "8",
69 | "11",
70 | "15",
71 | "16",
72 | "17",
73 | "18",
74 | "19",
75 | "20",
76 | "21",
77 | "22",
78 | "23",
79 | "24",
80 | "25"
81 | ),
82 | rJavaEnv.fallback_valid_versions_windows_x86 = c(
83 | "8",
84 | "11"
85 | )
86 | )
87 |
88 | # Only set the options that haven't been defined yet
89 | toset <- !(names(op.rJavaEnv) %in% names(op))
90 | if (any(toset)) {
91 | options(op.rJavaEnv[toset])
92 | }
93 |
94 | # Now, detect the current platform (OS and architecture)
95 | platform <- platform_detect(quiet = TRUE)
96 |
97 | # Build the option name dynamically based on platform$os and platform$arch.
98 | # For example, for macOS on x64, this results in "rJavaEnv.fallback_valid_versions_macos_x64"
99 | fallback_option_name <- paste0(
100 | "rJavaEnv.fallback_valid_versions_",
101 | platform$os,
102 | "_",
103 | platform$arch
104 | )
105 |
106 | # Retrieve the corresponding fallback list using getOption()
107 | fallback_current <- getOption(fallback_option_name)
108 |
109 | # Set the current platform valid versions option
110 | options(rJavaEnv.fallback_valid_versions_current_platform = fallback_current)
111 |
112 | invisible()
113 | }
114 |
--------------------------------------------------------------------------------
/man/use_java.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/use_java.R
3 | \name{use_java}
4 | \alias{use_java}
5 | \title{Install specified Java version and set the \code{JAVA_HOME} and \code{PATH} environment variables in current R session}
6 | \usage{
7 | use_java(
8 | version = NULL,
9 | distribution = "Corretto",
10 | cache_path = getOption("rJavaEnv.cache_path"),
11 | platform = platform_detect()$os,
12 | arch = platform_detect()$arch,
13 | quiet = TRUE
14 | )
15 | }
16 | \arguments{
17 | \item{version}{\code{Integer} or \code{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 \code{integer}) or any newer version if it is available for the selected distribution. For \code{macOS} on \code{aarch64} architecture (Apple Silicon) certain \code{Java} versions are not available.}
18 |
19 | \item{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.}
20 |
21 | \item{cache_path}{The destination directory to download the Java distribution to. Defaults to a user-specific data directory.}
22 |
23 | \item{platform}{The platform for which to download the Java distribution. Defaults to the current platform.}
24 |
25 | \item{arch}{The architecture for which to download the Java distribution. Defaults to the current architecture.}
26 |
27 | \item{quiet}{A \code{logical} value indicating whether to suppress messages. Can be \code{TRUE} or \code{FALSE}.}
28 | }
29 | \value{
30 | \code{NULL}. Prints the message that Java was set in the current R session if \code{quiet} is set to \code{FALSE}.
31 | }
32 | \description{
33 | Using specified Java version, set the \code{JAVA_HOME} and \code{PATH} environment variables in the current R session. If Java distribtuion has not been downloaded yet, download it. If it was not installed into cache directory yet, install it there and then set the environment variables. This is intended as a quick and easy way to use different Java versions in R scripts that are in the same project, but require different Java versions. For example, one could use this in scripts that are called by \code{targets} package or \code{callr} package.
34 | }
35 | \examples{
36 | \dontrun{
37 |
38 | # set cache directory for Java to be in temporary directory
39 | options(rJavaEnv.cache_path = tempdir())
40 |
41 | # install and set Java 8 in current R session
42 | use_java(8)
43 | # check Java version
44 | "8" == java_check_version_cmd(quiet = TRUE)
45 | "8" == java_check_version_rjava(quiet = TRUE)
46 |
47 | # install and set Java 17 in current R session
48 | use_java(17)
49 | # check Java version
50 | "17" == java_check_version_cmd(quiet = TRUE)
51 | "17" == java_check_version_rjava(quiet = TRUE)
52 |
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | url: https://www.ekotov.pro/rJavaEnv/
2 | template:
3 | bootstrap: 5
4 | bootswatch: flatly
5 | includes:
6 | in_header: |
7 |
8 |
9 |
10 |
11 |
21 | opengraph:
22 | image:
23 | src: man/figures/card.png
24 | alt: "rJavaEnv: Java Environments for R Projects. Install and manage Java environments using R"
25 | twitter:
26 | creator: "@EgorKotov"
27 | card: summary_large_image
28 |
29 | authors:
30 | Egor Kotov:
31 | href: "https://www.ekotov.pro"
32 |
33 | navbar:
34 | structure:
35 | left: [intro, reference, articles, tutorials, news]
36 | right: [search, github, lightswitch]
37 |
38 | home:
39 | title: 'rJavaEnv: `Java` Environments for R Projects'
40 | description: 'Install and manage `Java` environments using R'
41 |
42 |
43 | reference:
44 | - title: "Quick Install"
45 | desc: >
46 | Just quickly install `Java` in the current project
47 | contents:
48 | - java_quick_install
49 | - title: "Quick Set"
50 | desc: >
51 | Just quickly set `Java` in the current project (for use with `targets`/`callr`)
52 | contents:
53 | - use_java
54 | - title: "Check `Java` version"
55 | desc: >
56 | Check `Java` version with currently set environment
57 | contents:
58 | - java_check_version_cmd
59 | - java_check_version_rjava
60 | - java_get_home
61 | - title: "Fine-grained Control"
62 | desc: >
63 | Control every step of `Java` download, unpacking and installation
64 | contents:
65 | - java_download
66 | - java_unpack
67 | - java_install
68 | - java_env_set
69 | - java_env_unset
70 | - java_build_env_set
71 | - java_build_env_unset
72 | - title: "Manage files"
73 | desc: >
74 | Manage downloads, installs, and project-linked `Java` versions
75 | contents:
76 | - java_list
77 | - java_clear
78 | - title: "Other commands"
79 | contents:
80 | - java_valid_versions
81 | - rje_consent
82 |
83 |
84 |
85 | articles:
86 | - title: Documentation
87 | navbar: ~
88 | contents:
89 | - rJavaEnv-step-by-step
90 | - multiple-java-with-targets-callr
91 | - why-rJavaEnv
92 | - install-rjava-from-source
93 |
--------------------------------------------------------------------------------
/man/rJavaEnv-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/rJavaEnv-package.R
3 | \docType{package}
4 | \name{rJavaEnv-package}
5 | \alias{rJavaEnv}
6 | \alias{rJavaEnv-package}
7 | \title{rJavaEnv: 'Java' Environments for R Projects}
8 | \description{
9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
10 |
11 | Quickly install 'Java Development Kit (JDK)' without administrative privileges and set environment variables in current R session or project to solve common issues with 'Java' environment management in 'R'. Recommended to users of 'Java'/'rJava'-dependent 'R' packages such as 'r5r', 'opentripplanner', 'xlsx', 'openNLP', 'rWeka', 'RJDBC', 'tabulapdf', and many more. 'rJavaEnv' prevents common problems like 'Java' not found, 'Java' version conflicts, missing 'Java' installations, and the inability to install 'Java' due to lack of administrative privileges. 'rJavaEnv' automates the download, installation, and setup of the 'Java' on a per-project basis by setting the relevant 'JAVA_HOME' in the current 'R' session or the current working directory (via '.Rprofile', with the user's consent). Similar to what 'renv' does for 'R' packages, 'rJavaEnv' allows different 'Java' versions to be used across different projects, but can also be configured to allow multiple versions within the same project (e.g. with the help of 'targets' package). For users who need to install 'rJava' or other 'Java'-dependent packages from source, 'rJavaEnv' will display a message with instructions on how to run 'R CMD javareconf' to make the 'Java' configuration permanent, but also provides a function 'java_build_env_set' that sets the environment variables in the current R session temporarily to allow installation of 'rJava' from source without 'R CMD javareconf'. On 'Linux', in addition to setting environment variables, 'rJavaEnv' also dynamically loads 'libjvm.so' to ensure 'rJava' works correctly. See documentation for more details.
12 | }
13 | \seealso{
14 | Useful links:
15 | \itemize{
16 | \item \url{https://github.com/e-kotov/rJavaEnv}
17 | \item \url{https://www.ekotov.pro/rJavaEnv/}
18 | \item Report bugs at \url{https://github.com/e-kotov/rJavaEnv/issues}
19 | }
20 |
21 | }
22 | \author{
23 | \strong{Maintainer}: Egor Kotov \email{kotov.egor@gmail.com} (\href{https://orcid.org/0000-0001-6690-5345}{ORCID}) [copyright holder]
24 |
25 | Authors:
26 | \itemize{
27 | \item Chung-hong Chan \email{chainsawtiney@gmail.com} (\href{https://orcid.org/0000-0002-6232-7530}{ORCID})
28 | }
29 |
30 | Other contributors:
31 | \itemize{
32 | \item Mauricio Vargas \email{mavargas11@uc.cl} (\href{https://orcid.org/0000-0003-1017-7574}{ORCID}) [contributor]
33 | \item Hadley Wickham \email{hadley@posit.co} (use_java feature suggestion and PR review) [contributor]
34 | \item Enrique Mondragon-Estrada \email{enriquemondragon@proton.me} (\href{https://orcid.org/0009-0004-5592-1728}{ORCID}) [contributor]
35 | \item Jonas Lieth \email{jonas.lieth@gesis.org} (\href{https://orcid.org/0000-0002-3451-3176}{ORCID}) [contributor]
36 | }
37 |
38 | }
39 | \keyword{internal}
40 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to rJavaEnv
2 |
3 | This outlines how to propose a change to rJavaEnv.
4 | For a detailed discussion on contributing to this and other tidyverse packages, please see the [development contributing guide](https://rstd.io/tidy-contrib) and [code review principles](https://code-review.tidyverse.org/).
5 |
6 | ## Fixing typos
7 |
8 | You can fix typos, spelling mistakes, or grammatical errors in the documentation directly using the GitHub web interface, as long as the changes are made in the _source_ file.
9 | This generally means you'll need to edit [roxygen2 comments](https://roxygen2.r-lib.org/articles/roxygen2.html) in an `.R`, not a `.Rd` file.
10 | You can find the `.R` file that generates the `.Rd` by reading the comment in the first line.
11 |
12 | ## Bigger changes
13 |
14 | If you want to make a bigger change, it's a good idea to first file an issue and make sure someone from the team agrees that it’s needed.
15 | If you’ve found a bug, please file an issue that illustrates the bug with a minimal
16 | [reprex](https://www.tidyverse.org/help/#reprex) (this will also help you write a unit test, if needed).
17 | See the guide on [how to create a great issue](https://code-review.tidyverse.org/issues/) for more advice.
18 |
19 | ### Pull request process
20 |
21 | * Fork the package and clone onto your computer. If you haven't done this before, we recommend using `usethis::create_from_github("e-kotov/rJavaEnv", fork = TRUE)`.
22 |
23 | * Install all development dependencies with `devtools::install_dev_deps()`, and then make sure the package passes R CMD check by running `devtools::check()`.
24 | If R CMD check doesn't pass cleanly, it's a good idea to ask for help before continuing.
25 | * Create a Git branch for your pull request (PR). We recommend using `usethis::pr_init("brief-description-of-change")`.
26 |
27 | * Make your changes, commit to git, and then create a PR by running `usethis::pr_push()`, and following the prompts in your browser.
28 | The title of your PR should briefly describe the change.
29 | The body of your PR should contain `Fixes #issue-number`.
30 |
31 | * For user-facing changes, add a bullet to the top of `NEWS.md` (i.e. just below the first header). Follow the style described in .
32 |
33 | ### Code style
34 |
35 | * New code should follow the tidyverse [style guide](https://style.tidyverse.org).
36 | You can use the [styler](https://CRAN.R-project.org/package=styler) package to apply these styles, but please don't restyle code that has nothing to do with your PR.
37 |
38 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2), with [Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/rd-formatting.html), for documentation.
39 |
40 | * We use [testthat](https://cran.r-project.org/package=testthat) for unit tests.
41 | Contributions with test cases included are easier to accept.
42 |
43 | ## Code of Conduct
44 |
45 | Please note that the rJavaEnv project is released with a
46 | [Contributor Code of Conduct](.github/CODE_OF_CONDUCT.md). By contributing to this
47 | project you agree to abide by its terms.
48 |
--------------------------------------------------------------------------------
/.github/workflows/rhub.yaml:
--------------------------------------------------------------------------------
1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at
2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml
3 | # You can update this file to a newer version using the rhub2 package:
4 | #
5 | # rhub::rhub_setup()
6 | #
7 | # It is unlikely that you need to modify this file manually.
8 |
9 | name: R-hub
10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}"
11 |
12 | on:
13 | workflow_dispatch:
14 | inputs:
15 | config:
16 | description: 'A comma separated list of R-hub platforms to use.'
17 | type: string
18 | default: 'linux,windows,macos'
19 | name:
20 | description: 'Run name. You can leave this empty now.'
21 | type: string
22 | id:
23 | description: 'Unique ID. You can leave this empty now.'
24 | type: string
25 |
26 | jobs:
27 |
28 | setup:
29 | runs-on: ubuntu-latest
30 | outputs:
31 | containers: ${{ steps.rhub-setup.outputs.containers }}
32 | platforms: ${{ steps.rhub-setup.outputs.platforms }}
33 |
34 | steps:
35 | # NO NEED TO CHECKOUT HERE
36 | - uses: r-hub/actions/setup@v1
37 | with:
38 | config: ${{ github.event.inputs.config }}
39 | id: rhub-setup
40 |
41 | linux-containers:
42 | needs: setup
43 | if: ${{ needs.setup.outputs.containers != '[]' }}
44 | runs-on: ubuntu-latest
45 | name: ${{ matrix.config.label }}
46 | strategy:
47 | fail-fast: false
48 | matrix:
49 | config: ${{ fromJson(needs.setup.outputs.containers) }}
50 | container:
51 | image: ${{ matrix.config.container }}
52 |
53 | steps:
54 | - uses: r-hub/actions/checkout@v1
55 | - uses: r-hub/actions/platform-info@v1
56 | with:
57 | token: ${{ secrets.RHUB_TOKEN }}
58 | job-config: ${{ matrix.config.job-config }}
59 | - uses: r-hub/actions/setup-deps@v1
60 | with:
61 | token: ${{ secrets.RHUB_TOKEN }}
62 | job-config: ${{ matrix.config.job-config }}
63 | - uses: r-hub/actions/run-check@v1
64 | with:
65 | token: ${{ secrets.RHUB_TOKEN }}
66 | job-config: ${{ matrix.config.job-config }}
67 |
68 | other-platforms:
69 | needs: setup
70 | if: ${{ needs.setup.outputs.platforms != '[]' }}
71 | runs-on: ${{ matrix.config.os }}
72 | name: ${{ matrix.config.label }}
73 | strategy:
74 | fail-fast: false
75 | matrix:
76 | config: ${{ fromJson(needs.setup.outputs.platforms) }}
77 |
78 | steps:
79 | - uses: r-hub/actions/checkout@v1
80 | - uses: r-hub/actions/setup-r@v1
81 | with:
82 | job-config: ${{ matrix.config.job-config }}
83 | token: ${{ secrets.RHUB_TOKEN }}
84 | - uses: r-hub/actions/platform-info@v1
85 | with:
86 | token: ${{ secrets.RHUB_TOKEN }}
87 | job-config: ${{ matrix.config.job-config }}
88 | - uses: r-hub/actions/setup-deps@v1
89 | with:
90 | job-config: ${{ matrix.config.job-config }}
91 | token: ${{ secrets.RHUB_TOKEN }}
92 | - uses: r-hub/actions/run-check@v1
93 | with:
94 | job-config: ${{ matrix.config.job-config }}
95 | token: ${{ secrets.RHUB_TOKEN }}
96 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: rJavaEnv
2 | Title: 'Java' Environments for R Projects
3 | Version: 0.3.0.9000
4 | Authors@R: c(
5 | person("Egor", "Kotov", , "kotov.egor@gmail.com", role = c("aut", "cre", "cph"),
6 | comment = c(ORCID = "0000-0001-6690-5345")),
7 | person("Chung-hong", "Chan", , "chainsawtiney@gmail.com", role = "aut",
8 | comment = c(ORCID = "0000-0002-6232-7530")),
9 | person("Mauricio", "Vargas", , "mavargas11@uc.cl", role = "ctb",
10 | comment = c(ORCID = "0000-0003-1017-7574")),
11 | person("Hadley", "Wickham", , "hadley@posit.co", role = "ctb",
12 | comment = "use_java feature suggestion and PR review"),
13 | person("Enrique", "Mondragon-Estrada", , "enriquemondragon@proton.me", role = "ctb",
14 | comment = c(ORCID = "0009-0004-5592-1728")),
15 | person("Jonas", "Lieth", , "jonas.lieth@gesis.org", role = "ctb",
16 | comment = c(ORCID = "0000-0002-3451-3176"))
17 | )
18 | Description: Quickly install 'Java Development Kit (JDK)' without
19 | administrative privileges and set environment variables in current R
20 | session or project to solve common issues with 'Java' environment
21 | management in 'R'. Recommended to users of 'Java'/'rJava'-dependent
22 | 'R' packages such as 'r5r', 'opentripplanner', 'xlsx', 'openNLP',
23 | 'rWeka', 'RJDBC', 'tabulapdf', and many more. 'rJavaEnv' prevents
24 | common problems like 'Java' not found, 'Java' version conflicts,
25 | missing 'Java' installations, and the inability to install 'Java' due
26 | to lack of administrative privileges. 'rJavaEnv' automates the
27 | download, installation, and setup of the 'Java' on a per-project basis
28 | by setting the relevant 'JAVA_HOME' in the current 'R' session or the
29 | current working directory (via '.Rprofile', with the user's consent).
30 | Similar to what 'renv' does for 'R' packages, 'rJavaEnv' allows
31 | different 'Java' versions to be used across different projects, but
32 | can also be configured to allow multiple versions within the same
33 | project (e.g. with the help of 'targets' package). For users who need
34 | to install 'rJava' or other 'Java'-dependent packages from source,
35 | 'rJavaEnv' will display a message with instructions on how to run 'R
36 | CMD javareconf' to make the 'Java' configuration permanent, but also
37 | provides a function 'java_build_env_set' that sets the environment
38 | variables in the current R session temporarily to allow installation
39 | of 'rJava' from source without 'R CMD javareconf'. On 'Linux', in
40 | addition to setting environment variables, 'rJavaEnv' also dynamically
41 | loads 'libjvm.so' to ensure 'rJava' works correctly. See
42 | documentation for more details.
43 | License: MIT + file LICENSE
44 | URL: https://github.com/e-kotov/rJavaEnv, https://www.ekotov.pro/rJavaEnv/
45 | BugReports: https://github.com/e-kotov/rJavaEnv/issues
46 | Depends:
47 | R (>= 4.0)
48 | Imports:
49 | checkmate,
50 | cli,
51 | curl,
52 | jsonlite,
53 | rlang,
54 | utils
55 | Suggests:
56 | quarto,
57 | rJava,
58 | testthat (>= 3.0.0),
59 | withr
60 | VignetteBuilder:
61 | quarto
62 | Config/testthat/edition: 3
63 | Encoding: UTF-8
64 | Language: en-US
65 | Roxygen: list(markdown = TRUE)
66 | RoxygenNote: 7.3.3
67 |
--------------------------------------------------------------------------------
/R/java_manage.R:
--------------------------------------------------------------------------------
1 | #' List the contents of the Java versions installed or cached
2 | #'
3 | #' @description
4 | #' This function lists one of the following:
5 | #'
6 | #' * `project` - list the contents of the Java symlinked/copied in the current project or directory specified by `target_dir`
7 | #'
8 | #' * `distrib` - list the contents of the downloaded Java distributions cache in default location or specified by `target_dir`
9 | #'
10 | #' * `installed` - list the contents of the Java installations cache (unpacked distributions) in default location or specified by `target_dir`
11 | #'
12 | #' @param type The type of cache to list: "distrib", "installed", or "project". Defaults to "project".
13 | #' @param output The format of the output: `data.frame`` or `vector``. Defaults to `data.frame`.
14 | #' @inheritParams global_quiet_param
15 | #' @param target_dir The cache directory to list. Defaults to the user-specific data directory for "distrib" and "installed", and the current working directory for "project".
16 | #' @return A `dataframe` or `character` `vector` with the contents of the specified cache or project directory.
17 | #' @export
18 | #'
19 | #' @examples
20 | #' \dontrun{
21 | #' java_list("project")
22 | #' java_list("installed")
23 | #' java_list("distrib")
24 | #'}
25 | #'
26 | java_list <- function(
27 | type = c("project", "installed", "distrib"),
28 | output = c("data.frame", "vector"),
29 | quiet = TRUE,
30 | target_dir = NULL) {
31 | type <- match.arg(type)
32 | output <- match.arg(output)
33 |
34 | if (is.null(target_dir)) {
35 | if (type == "project") {
36 | target_dir <- getwd()
37 | } else {
38 | target_dir <- getOption("rJavaEnv.cache_path")
39 | }
40 | }
41 |
42 | if (type == "distrib") {
43 | return(java_list_distrib_cache(output = output, quiet = quiet, cache_path = target_dir))
44 | } else if (type == "installed") {
45 | return(java_list_installed_cache(output = output, quiet = quiet, cache_path = target_dir))
46 | } else if (type == "project") {
47 | return(java_list_in_project(output = output, quiet = quiet, project_path = target_dir))
48 | }
49 | }
50 |
51 | #' Manage Java installations and distributions caches
52 | #'
53 | #' Wrapper function to clear the Java symlinked in the current project, installed, or distributions caches.
54 | #'
55 | #' @param type What to clear: "project" - remove symlinks to install cache in the current project, "installed" - remove installed Java versions, "distrib" - remove downloaded Java distributions.
56 | #' @param check Whether to list the contents of the cache directory before clearing it. Defaults to TRUE.
57 | #' @param delete_all Whether to delete all items without prompting. Defaults to FALSE.
58 | #' @param target_dir The directory to clear. Defaults to current working directory for "project" and user-specific data directory for "installed" and "distrib". Not recommended to change.
59 | #' @return A message indicating whether the cache was cleared or not.
60 | #' @export
61 | #'
62 | #' @examples
63 | #' \dontrun{
64 | #' java_clear("project", target_dir = tempdir())
65 | #' java_clear("installed", target_dir = tempdir())
66 | #' java_clear("distrib", target_dir = tempdir())
67 | #' }
68 | #'
69 | java_clear <- function(
70 | type = c("project", "installed", "distrib"),
71 | target_dir = NULL,
72 | check = TRUE,
73 | delete_all = FALSE) {
74 | rje_consent_check()
75 |
76 | type <- match.arg(type)
77 |
78 | if (is.null(target_dir)) {
79 | if (type == "project") {
80 | target_dir <- getwd()
81 | } else {
82 | target_dir <- getOption("rJavaEnv.cache_path")
83 | }
84 | }
85 |
86 | if (type == "distrib") {
87 | java_clear_distrib_cache(cache_path = target_dir, check = check, delete_all = delete_all)
88 | } else if (type == "installed") {
89 | java_clear_installed_cache(cache_path = target_dir, check = check, delete_all = delete_all)
90 | } else if (type == "project") {
91 | java_clear_in_project(project_path = target_dir, check = check, delete_all = delete_all)
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/R/java_manage_distrib_cache.R:
--------------------------------------------------------------------------------
1 | #' List the contents of the Java distributions cache folder
2 | #'
3 | #' @param output The format of the output: "data.frame" or "vector". Defaults to "data.frame".
4 | #' @inheritParams java_list
5 | #' @inheritParams java_download
6 | #' @inheritParams global_quiet_param
7 | #' @return A character vector with the contents of the cache directory.
8 | #'
9 | #' @keywords internal
10 | java_list_distrib_cache <- function(
11 | cache_path = getOption("rJavaEnv.cache_path"),
12 | output = c("data.frame", "vector"),
13 | quiet = TRUE
14 | ) {
15 | output <- match.arg(output)
16 |
17 | cache_path <- file.path(cache_path, "distrib")
18 |
19 | if (!dir.exists(cache_path)) {
20 | cli::cli_alert_danger("No Java distributions have been downloaded.")
21 | return(character(0))
22 | }
23 | if (!quiet) cli::cli_inform("Contents of the Java distributions cache folder:")
24 |
25 | java_distrs <- grep(
26 | "md5$",
27 | list.files(cache_path, full.names = TRUE),
28 | invert = TRUE,
29 | value = TRUE
30 | )
31 |
32 | if (output == "vector") {
33 | return(java_distrs)
34 | } else if (output == "data.frame") {
35 | java_distrs <- data.frame(java_distr_path = java_distrs)
36 | return(java_distrs)
37 | }
38 | }
39 |
40 | #' Clear the Java distributions cache folder
41 | #'
42 | #' @param cache_path The cache directory to clear. Defaults to the user-specific data directory.
43 | #' @inheritParams java_clear
44 | #' @inheritParams java_download
45 | #' @return A message indicating whether the cache was cleared or not.
46 | #'
47 | #' @keywords internal
48 | java_clear_distrib_cache <- function(
49 | cache_path = getOption("rJavaEnv.cache_path"),
50 | check = TRUE,
51 | delete_all = FALSE
52 | ) {
53 | rje_consent_check()
54 |
55 | distrib_cache_path <- file.path(cache_path, "distrib")
56 |
57 | if (!dir.exists(distrib_cache_path)) {
58 | if (length(list.files(distrib_cache_path)) == 0) {
59 | cli::cli_inform("Java distributions cache is already empty.")
60 | return(invisible(NULL))
61 | }
62 | }
63 |
64 | if (delete_all) {
65 | unlink(file.path(distrib_cache_path, "*"), recursive = TRUE)
66 | cli::cli_inform("Java distributions cache cleared.")
67 | return(invisible(NULL))
68 | }
69 |
70 | if (check) {
71 | distributions <- java_list_distrib_cache(output = "vector", cache_path = cache_path)
72 | if (length(distributions) == 0) {
73 | cli::cli_inform("No Java distributions found to clear.")
74 | return(invisible(NULL))
75 | }
76 |
77 | cli::cli_alert_info("Existing Java distributions:")
78 | for (i in seq_along(distributions)) {
79 | cli::cli_inform("{i}: {distributions[i]}")
80 | }
81 |
82 | cli::cli_alert_info("Enter the number of the distribution to delete, 'all' to delete all, or '0' or any other character to cancel:")
83 | response <- readline()
84 |
85 | if (tolower(response) == "all") {
86 | unlink(file.path(distrib_cache_path, "*"), recursive = TRUE)
87 | cli::cli_inform("All Java distributions have been cleared.")
88 | } else {
89 | choice <- suppressWarnings(as.integer(response))
90 | if (is.na(choice) || choice == 0 || choice > length(distributions)) {
91 | cli::cli_inform("No distributions were cleared.")
92 | } else {
93 | unlink(distributions[choice], recursive = TRUE)
94 | md5_file <- paste0(distributions[choice], "md5")
95 | if(file.exists(md5_file)) unlink(md5_file)
96 | cli::cli_inform("Java distribution {choice} has been cleared.")
97 | }
98 | }
99 | } else {
100 | cli::cli_alert_info("Are you sure you want to clear the Java distributions cache? (yes/no)")
101 | response <- readline()
102 | if (tolower(response) == "yes") {
103 | unlink(file.path(distrib_cache_path, "*"), recursive = TRUE)
104 | cli::cli_inform("Java distributions cache cleared.")
105 | } else {
106 | cli::cli_inform("Java distributions cache was not cleared.")
107 | }
108 | }
109 |
110 | return(invisible(NULL))
111 | }
112 |
--------------------------------------------------------------------------------
/vignettes/multiple-java-with-targets-callr.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Multiple `Java` environments in one project with `targets` and `callr`"
3 | vignette: >
4 | %\VignetteIndexEntry{Multiple `Java` environments in one project with `targets` and `callr`}
5 | %\VignetteEngine{quarto::html}
6 | %\VignetteEncoding{UTF-8}
7 | execute:
8 | eval: false
9 | format:
10 | html:
11 | toc: true
12 | toc-depth: 2
13 | code-overflow: wrap
14 | ---
15 |
16 | If you need to use multiple `Java` distribution versions in a single project, you can use a handy shortcut function `use_java()` kindly [suggested by Hadley Wickham](https://github.com/e-kotov/rJavaEnv/issues/44){target='_blank'}.
17 |
18 | Essentialy, `use_java()` does the same thing as `java_quick_install()`, but in a less intrusive way. It downloads the distribution of the user requested major version of `Java`, unpacks it, also to the cache folder, but unlike `java_quick_install()`, it does not copy or link the `Java` installation folder from cache into the project directory and does not create or edit your `.Rprofile` file. Instead, it just sets the environment in the current R script to the requested `Java` binaries in the cache folder. The download and unpacking only happens once, so each next run is practically instant, as the function only needs to set the environment in the current R script.
19 |
20 | # How to use `use_java()`
21 |
22 | Let's illustrate this with a simple example.
23 |
24 | First, load the package and check the valid major versions of `Java`:
25 |
26 | ```{r}
27 | library(rJavaEnv)
28 | java_valid_versions()
29 | ```
30 |
31 |
32 | ```
33 | [1] "8" "11" "15" "16" "17" "18" "19" "20" "21" "22" "23" "24"
34 | ```
35 |
36 | ::: {.callout-note}
37 | The available versions of `Java` depend on your OS and architecture, so you might see a shorter list on your system.
38 | :::
39 |
40 | Now select any two or three versions and run `use_java()`, checking every time that correct java was set in the current environment.
41 |
42 | ```{r}
43 | use_java("8")
44 | "8" == java_check_version_cmd(quiet = TRUE)
45 | "8" == java_check_version_rjava(quiet = TRUE)
46 | ```
47 |
48 | ```
49 | [1] TRUE
50 | [1] TRUE
51 | ```
52 |
53 | ```{r}
54 | use_java(17)
55 | "17" == java_check_version_cmd(quiet = TRUE)
56 | "17" == java_check_version_rjava(quiet = TRUE)
57 | ```
58 |
59 | ```
60 | [1] TRUE
61 | [1] TRUE
62 | ```
63 |
64 | ```{r}
65 | use_java(21)
66 | "21" == java_check_version_cmd(quiet = TRUE)
67 | "21" == java_check_version_rjava(quiet = TRUE)
68 | ```
69 |
70 |
71 | ```
72 | [1] TRUE
73 | [1] TRUE
74 | ```
75 |
76 | You probably had to wait for a bit for the Java distribution to be downloaded and unpacked.
77 |
78 | However, now if you repeat the same commands, you will see that the correct `Java` version is set instantly, as downloading and unpacking are skipped.
79 |
80 | # How to use with `targets` and `callr`
81 |
82 | Both [`{targets}`](https://docs.ropensci.org/targets/){target="_blank"} and [`{callr}`](https://callr.r-lib.org/){target="_blank"} packages allow the user to run any R scripts in clean separate R sessions. This essentially allows the user to run multiple versions of `Java` in one project with `targets` and `callr`, mostly overcoming the issue of manually switching between `Java` versions in one project.
83 |
84 | One simple thing you can do if one of the scripts needs Java 8, and another one needs Java 17, is to insert `use_java()` in beginning of the scripts that you run through `targets` or `callr` like so:
85 |
86 | ```{r}
87 | library(rJavaEnv)
88 | use_java("17")
89 | ```
90 |
91 | Or:
92 |
93 | ```{r}
94 | rJavaEnv::use_java("17")
95 | ```
96 |
97 |
98 | The first run of such script will have to go through the the process of downloading and unpacking the `Java` distribution. The second run will not need to download and unpacking and will be instant.
99 |
100 | If you need the runs to be instant from the first attempt, you can pre-download and pre-install `Java` into cache folders using:
101 |
102 | ```{r}
103 | java_17_distrib <- java_download("17")
104 | java_unpack(java_17_distrib)
105 | ```
106 |
--------------------------------------------------------------------------------
/vignettes/install-rjava-from-source.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Install `rJava` from source"
3 | vignette: >
4 | %\VignetteIndexEntry{Install `rJava` from source}
5 | %\VignetteEngine{quarto::html}
6 | %\VignetteEncoding{UTF-8}
7 | execute:
8 | eval: false
9 | format:
10 | html:
11 | toc: true
12 | toc-depth: 2
13 | code-overflow: wrap
14 | ---
15 |
16 | The basics of using `rJavaEnv` are covered in the [Quick Start Guide](rJavaEnv.qmd), which demonstrates how to install Java in one line of code. This tutorial will show you how to install `rJava` packag from source if you want to or have to.
17 |
18 | ```{r}
19 | library(rJavaEnv)
20 | ```
21 |
22 | Assume your project directory is currently in a temporary directory. Feel free to skip that, if you are already working in a desired project directory where you would like to install `Java`. In the example outputs below you will see paths that point to a temporary directory, but in a real project you would see your project directory instead.
23 |
24 | ```{r}
25 | project_dir <- tempdir()
26 | setwd(project_dir)
27 | ```
28 |
29 |
30 | # 1. Install Java
31 |
32 | You can use detailed step-by-step process from the [step-by-step vignette](rJavaEnv-step-by-step.qmd) to download, unpack, install and link `Java` JDK of your desired version, but for simplicity, let's use shortcut functions
33 |
34 | Either quick install Java into current project directory:
35 |
36 | ```{r}
37 | java_quick_install(version = 21)
38 | ```
39 |
40 | ::: callout-note
41 | You might also do `java_home <- java_quick_install(version = 21)`, as this will save the path to the installed Java home directory into `java_home` variable for later use, but the function to set the build environment actually uses the `JAVA_HOME` environment variable set by `java_quick_install()` by default, so it's not necessary.
42 | :::
43 |
44 |
45 | Or you can simply do:
46 |
47 | ```{r}
48 | use_java(21)
49 | ```
50 |
51 | This will essentially do the same as `java_quick_install()`, but only sets the `JAVA_HOME` and `PATH` environment variables in the current R session, without modifying your `.Rprofile` file or copying/linking the installation folder into your project directory.
52 |
53 | # 2. Set the environment for building `rJava`
54 |
55 |
56 | Now simply use:
57 |
58 |
59 | ```{r}
60 | java_build_env_set()
61 | ```
62 |
63 | That is it, `java_build_env_set` will detect your platform and architecture and set the correct environment variables. If you want advanced control, you can use `java_home` to set custom `JAVA_HOME` path, or use `where='project'` to set the environment variables in your `.Rprofile` file in the current project directory. See `?java_build_env_set` for details.
64 |
65 | Once `java_build_env_set()` completes, it will print out OS-specific notes. In summary,
66 |
67 | - **On Linux**, you may need to install several system dependencies. For Debian/Ubuntu, this can be done with:
68 | ```bash
69 | sudo apt-get update && sudo apt-get install -y --no-install-recommends libpcre2-dev libdeflate-dev libzstd-dev liblzma-dev libbz2-dev zlib1g-dev libicu-dev && sudo rm -rf /var/lib/apt/lists/*
70 | ```
71 |
72 | - **On Windows**, `Rtools` is required. You can download it from [https://cran.r-project.org/bin/windows/Rtools/](https://cran.r-project.org/bin/windows/Rtools/){target="_blank"}.
73 |
74 | - **On macOS**, you'll need the Xcode Command Line Tools. Install them by running:
75 | ```bash
76 | xcode-select --install
77 | ```
78 |
79 | # 3. Install `rJava` from source
80 |
81 | Now you are ready to install `rJava` from source:
82 |
83 | ```{r}
84 | install.packages("rJava", type = "source")
85 | ```
86 |
87 | If you are on a Linux distribution with pre-configured [`Posit Package Manager` (PPM)](https://packagemanager.posit.co/) repository that serves pre-compiled binaries even if `type="source"` (or in a similar situation on `Windows` or `macOS`), you can use `repos = "https://cloud.r-project.org"` to force installation from source:
88 |
89 | ```{r}
90 | install.packages("rJava", type = "source", repos = "https://cloud.r-project.org")
91 | ```
92 |
93 | And that is it. You have successfully installed `rJava` from source. If you restart the R session, the build-related environment variables will be reset. To use your newly installed `rJava` package just do:
94 |
95 | ```{r}
96 | library(rJavaEnv)
97 | use_java(21) # or whatever version you installed
98 | library(rJava)
99 | ```
100 |
--------------------------------------------------------------------------------
/R/consent.R:
--------------------------------------------------------------------------------
1 | #' Obtain User Consent for rJavaEnv
2 | #'
3 | #' Get user consent for rJavaEnv to write and update files on the file system.
4 | #' rJavaEnv needs permission to manage files in your project and cache directories
5 | #' to function correctly.
6 | #'
7 | #' In line with [CRAN policies](https://cran.r-project.org/web/packages/policies.html), explicit user consent is required before making these changes.
8 | #' Please call `rJavaEnv::consent()` to provide consent.
9 | #'
10 | #' Alternatively, you can set the following \R option
11 | #' (especially useful for non-interactive R sessions):
12 | #'
13 | #' ```
14 | #' options(rJavaEnv.consent = TRUE)
15 | #' ```
16 | #' The function is based on the code of the `renv` package.
17 | #' Copyright 2023 Posit Software, PBC
18 | #' License: https://github.com/rstudio/renv/blob/main/LICENSE
19 | #'
20 | #' @param provided Logical indicating if consent is already provided.
21 | #' To provide consent in non-interactive \R sessions
22 | #' use `rJavaEnv::rje_consent(provided = TRUE)`. Default is `FALSE`.
23 | #'
24 | #' @return `TRUE` if consent is given, otherwise an error is raised.
25 | #'
26 | #' @export
27 | #' @examples
28 | #' \dontrun{
29 | #'
30 | #' # to provide consent and prevent other functions from interrupting to get the consent
31 | #' rje_consent(provided = TRUE)
32 | #' }
33 | #'
34 | rje_consent <- function(provided = FALSE) {
35 |
36 | # Check if consent is already given via environment variable
37 | if (getOption("rJavaEnv.consent", default = FALSE)) {
38 | cli::cli_inform("Consent for using rJavaEnv has already been provided.")
39 | return(invisible(TRUE))
40 | }
41 |
42 | # Check if consent is already given via cache directory
43 | user_package_cache_path <- getOption("rJavaEnv.cache_path")
44 | user_package_cache_path <- normalizePath(user_package_cache_path, winslash = "/", mustWork = FALSE)
45 | if (dir.exists(user_package_cache_path)) {
46 | cli::cli_inform("Consent for using rJavaEnv has already been provided.")
47 | return(invisible(TRUE))
48 | }
49 |
50 | # write welcome message
51 | template <- system.file("resources/consent-info", package = "rJavaEnv")
52 | contents <- readLines(template)
53 | contents <- gsub("\\$\\{rJavaEnv_CACHE\\}", user_package_cache_path, contents)
54 | cli::cli_inform(contents)
55 |
56 | # Request user consent if not already provided
57 | if (!provided) {
58 | response <- readline(prompt = "Your response: (yes/no) ")
59 | provided <- tolower(response) %in% c("y", "yes", "yes.")
60 | }
61 |
62 | if (!provided) {
63 | cli::cli_abort("Consent was not provided; operation aborted.")
64 | }
65 |
66 | # Save user consent
67 | options(rJavaEnv.consent = TRUE)
68 | dir.create(user_package_cache_path, recursive = TRUE, showWarnings = FALSE)
69 | cli::cli_inform("Consent has been granted and recorded.")
70 |
71 | invisible(TRUE)
72 | }
73 |
74 | #' Verify User Consent for rJavaEnv
75 | #'
76 | #' Ensure that the user has granted permission for rJavaEnv to manage files on their file system.
77 | #'
78 | #' The function is based on the code of the `renv` package.
79 | #' Copyright 2023 Posit Software, PBC
80 | #' License: https://github.com/rstudio/renv/blob/main/LICENSE
81 | #'
82 | #' @return `TRUE` if consent is verified, otherwise an error is raised.
83 | #' @keywords internal
84 | rje_consent_check <- function() {
85 |
86 | # Check if explicit consent is given
87 | if (getOption("rJavaEnv.consent", FALSE)) {
88 | return(TRUE)
89 | }
90 | if (dir.exists(getOption("rJavaEnv.cache_path"))) {
91 | return(TRUE)
92 | }
93 |
94 | # Check for implicit consent
95 | consented <-
96 | !interactive() ||
97 | rje_envvar_exists("CI") ||
98 | rje_envvar_exists("GITHUB_ACTION") ||
99 | rje_envvar_exists("RENV_PATHS_ROOT") ||
100 | file.exists("/.singularity.d")
101 |
102 | if (consented) {
103 | options(rJavaEnv.consent = TRUE)
104 | return(TRUE)
105 | }
106 |
107 | # Prompt for explicit consent
108 | rje_consent()
109 | }
110 |
111 |
112 | #' Helper for clean env var check
113 | #'
114 | #' #' The function is based on the code of the `renv` package.
115 | #' Copyright 2023 Posit Software, PBC
116 | #' License: https://github.com/rstudio/renv/blob/main/LICENSE
117 | #' @param key The environment variable key to check.
118 | #' @keywords internal
119 | rje_envvar_exists <- function(key) {
120 | !is.na(Sys.getenv(key, unset = NA))
121 | }
122 |
--------------------------------------------------------------------------------
/R/java_unpack.R:
--------------------------------------------------------------------------------
1 | #' Unpack a Java distribution file into cache directory
2 | #'
3 | #' @description
4 | #' Unpack the Java distribution file into cache directory and return the path to the unpacked Java directory with Java binaries.
5 | #'
6 | #'
7 | #' @inheritParams java_install
8 | #' @param force A logical. Whether to overwrite an existing installation. Defaults to `FALSE`.
9 | #' @inheritParams global_quiet_param
10 | #' @return A `character` vector containing of length 1 containing the path to the unpacked Java directory.
11 | #' @export
12 | #' @examples
13 | #' \dontrun{
14 | #'
15 | #' # set cache dir to temporary directory
16 | #' options(rJavaEnv.cache_path = tempdir())
17 | #'
18 | #' # download Java 17 distrib and unpack it into cache dir
19 | #' java_17_distrib <- java_download(version = "17")
20 | #' java_home <- java_unpack(java_distrib_path = java_17_distrib)
21 | #'
22 | #' # set the JAVA_HOME environment variable in the current session
23 | #' # to the cache dir without touching any files in the current project directory
24 | #' java_env_set(where = "session", java_home = java_home)
25 | #' }
26 | #'
27 | java_unpack <- function(
28 | java_distrib_path,
29 | quiet = FALSE,
30 | force = FALSE
31 | ) {
32 | platforms <- c("windows", "linux", "macos")
33 | architectures <- c("x64", "aarch64", "arm64")
34 | java_versions <- java_valid_versions()
35 |
36 | # Extract information from the file name
37 | filename <- basename(java_distrib_path)
38 | parts <- strsplit(gsub("\\.tar\\.gz|\\.zip", "", filename), "-")[[1]]
39 |
40 | # Guess the version, architecture, and platform
41 | version <- parts[parts %in% java_versions][1]
42 | arch <- parts[parts %in% architectures][1]
43 | platform <- parts[parts %in% platforms][1]
44 |
45 | if (is.na(version)) {
46 | cli::cli_abort("Unable to detect Java version from filename.")
47 | }
48 | if (is.na(arch)) {
49 | cli::cli_abort("Unable to detect architecture from filename.")
50 | }
51 | if (is.na(platform)) {
52 | cli::cli_abort("Unable to detect platform from filename.")
53 | }
54 |
55 | # Create the installation path in the package cache
56 | cache_path <- getOption("rJavaEnv.cache_path")
57 | installed_path <- file.path(cache_path, "installed", platform, arch, version)
58 |
59 | if (dir.exists(installed_path) && force) {
60 | if (!quiet) {
61 | cli::cli_inform(
62 | "Forced re-installation. Removing existing installation at {.path {installed_path}}"
63 | )
64 | }
65 | unlink(installed_path, recursive = TRUE)
66 | }
67 |
68 | # Check if the distribution has already been unpacked
69 | if (!dir.exists(installed_path) || length(list.files(installed_path)) == 0) {
70 | # Create the directories if they don't exist
71 | if (!dir.exists(installed_path)) {
72 | dir.create(installed_path, recursive = TRUE)
73 | }
74 |
75 | # Determine extraction path based on platform
76 | if (platform == "macos") {
77 | extract_subdir <- "Contents/Home"
78 | } else {
79 | extract_subdir <- "."
80 | }
81 |
82 | # Extract the files
83 | temp_dir <- file.path(tempdir(), "java_temp")
84 | if (dir.exists(temp_dir)) {
85 | unlink(temp_dir, recursive = TRUE)
86 | }
87 |
88 | dir.create(temp_dir, recursive = TRUE)
89 |
90 | if (grepl("\\.tar\\.gz$", java_distrib_path)) {
91 | utils::untar(java_distrib_path, exdir = temp_dir)
92 | } else if (grepl("\\.zip$", java_distrib_path)) {
93 | utils::unzip(java_distrib_path, exdir = temp_dir)
94 | } else {
95 | stop(cli::cli_abort("Unsupported file format", .envir = environment()))
96 | }
97 |
98 | # Safely find the extracted directory
99 | extracted_root_dir <- list.files(temp_dir, full.names = TRUE)[1]
100 | if (platform == "macos") {
101 | extracted_dir <- file.path(extracted_root_dir, "Contents", "Home")
102 | } else {
103 | extracted_dir <- extracted_root_dir
104 | }
105 |
106 | # Move the extracted files to the installation path
107 | file.copy(
108 | list.files(extracted_dir, full.names = TRUE),
109 | installed_path,
110 | recursive = TRUE
111 | )
112 |
113 | # Clean up temporary directory
114 | unlink(temp_dir, recursive = TRUE)
115 | } else {
116 | if (!quiet) {
117 | cli::cli_inform(
118 | "Java distribution {filename} already unpacked at {.path {installed_path}}"
119 | )
120 | }
121 | }
122 | return(installed_path)
123 | }
124 |
--------------------------------------------------------------------------------
/inst/schemaorg.json:
--------------------------------------------------------------------------------
1 | {
2 | "@context": "https://schema.org",
3 | "@graph": [
4 | {
5 | "type": "SoftwareSourceCode",
6 | "author": [
7 | {
8 | "id": "https://orcid.org/0000-0002-6232-7530",
9 | "type": "Person",
10 | "email": "chainsawtiney@gmail.com",
11 | "familyName": "Chan",
12 | "givenName": "Chung-hong"
13 | },
14 | {
15 | "id": "https://orcid.org/0000-0001-6690-5345"
16 | }
17 | ],
18 | "codeRepository": "https://github.com/e-kotov/rJavaEnv",
19 | "contributor": [
20 | {
21 | "id": "https://orcid.org/0000-0003-1017-7574",
22 | "type": "Person",
23 | "email": "mavargas11@uc.cl",
24 | "familyName": "Vargas",
25 | "givenName": "Mauricio"
26 | },
27 | {
28 | "type": "Person",
29 | "email": "hadley@posit.co",
30 | "familyName": "Wickham",
31 | "givenName": "Hadley"
32 | },
33 | {
34 | "id": "https://orcid.org/0009-0004-5592-1728",
35 | "type": "Person",
36 | "email": "enriquemondragon@proton.me",
37 | "familyName": "Mondragon-Estrada",
38 | "givenName": "Enrique"
39 | },
40 | {
41 | "id": "https://orcid.org/0000-0002-3451-3176",
42 | "type": "Person",
43 | "email": "jonas.lieth@gesis.org",
44 | "familyName": "Lieth",
45 | "givenName": "Jonas"
46 | }
47 | ],
48 | "copyrightHolder": {
49 | "id": "https://orcid.org/0000-0001-6690-5345",
50 | "type": "Person",
51 | "email": "kotov.egor@gmail.com",
52 | "familyName": "Kotov",
53 | "givenName": "Egor"
54 | },
55 | "description": "Quickly install 'Java Development Kit (JDK)' without administrative privileges and set environment variables in current R session or project to solve common issues with 'Java' environment management in 'R'. Recommended to users of 'Java'/'rJava'-dependent 'R' packages such as 'r5r', 'opentripplanner', 'xlsx', 'openNLP', 'rWeka', 'RJDBC', 'tabulapdf', and many more. 'rJavaEnv' prevents common problems like 'Java' not found, 'Java' version conflicts, missing 'Java' installations, and the inability to install 'Java' due to lack of administrative privileges. 'rJavaEnv' automates the download, installation, and setup of the 'Java' on a per-project basis by setting the relevant 'JAVA_HOME' in the current 'R' session or the current working directory (via '.Rprofile', with the user's consent). Similar to what 'renv' does for 'R' packages, 'rJavaEnv' allows different 'Java' versions to be used across different projects, but can also be configured to allow multiple versions within the same project (e.g. with the help of 'targets' package). For users who need to install 'rJava' or other 'Java'-dependent packages from source, 'rJavaEnv' will display a message with instructions on how to run 'R CMD javareconf' to make the 'Java' configuration permanent, but also provides a function 'java_build_env_set' that sets the environment variables in the current R session temporarily to allow installation of 'rJava' from source without 'R CMD javareconf'. On 'Linux', in addition to setting environment variables, 'rJavaEnv' also dynamically loads 'libjvm.so' to ensure 'rJava' works correctly. See documentation for more details.",
56 | "license": "https://spdx.org/licenses/MIT",
57 | "name": "rJavaEnv: 'Java' Environments for R Projects",
58 | "programmingLanguage": {
59 | "type": "ComputerLanguage",
60 | "name": "R",
61 | "url": "https://r-project.org"
62 | },
63 | "provider": {
64 | "id": "https://cran.r-project.org",
65 | "type": "Organization",
66 | "name": "Comprehensive R Archive Network (CRAN)",
67 | "url": "https://cran.r-project.org"
68 | },
69 | "runtimePlatform": "R version 4.5.1 (2025-06-13)",
70 | "version": "0.3.0.9000"
71 | },
72 | {
73 | "id": "https://doi.org/10.32614/CRAN.package.rJavaEnv",
74 | "type": "SoftwareSourceCode",
75 | "author": [
76 | {
77 | "id": "https://orcid.org/0000-0001-6690-5345",
78 | "type": "Person",
79 | "email": "kotov.egor@gmail.com",
80 | "familyName": "Kotov",
81 | "givenName": "Egor"
82 | },
83 | {
84 | "id": "https://orcid.org/0000-0002-6232-7530",
85 | "type": "Person",
86 | "email": "chainsawtiney@gmail.com",
87 | "familyName": "Chan",
88 | "givenName": "Chung-hong"
89 | }
90 | ],
91 | "name": "rJavaEnv: Java Environments for R Projects"
92 | }
93 | ]
94 | }
95 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | # rJavaEnv (development version)
2 |
3 | ## New features
4 |
5 | - Linux support. On Linux, `libjvm.so` location is automatically detected and force-loaded via `dyn.load()`. Thanks to that, `rJava` and any depenent R packages can be installed and loaded, if repositories with pre-built packages, such as `Posit Package Manager`, is used or if you build `rJava` from source, see the `java_build_env_set()` function.
6 |
7 | - New function `java_build_env_set()` that sets the environment (either temporarily in the current session or in `./.Rprofile` file of the current working directory) to build `rJava` from source on `macOS`, `Linux` and `Windows` platforms. It uses the current value of `JAVA_HOME` environment variable by default, so that it is more convenient to use after `java_quick_install()` or `use_java()` commands. After running `java_build_env_set()`, users can install `rJava` from source with `install.packages("rJava", type = "source")` without any additional configuration. However, users will still need some system dependencies, e.g. on Linux they will need: libpcre2-dev, libdeflate-dev, libzstd-dev, liblzma-dev, libbz2-dev, zlib1g-dev, libicu-dev. A system message with a suggested `apt-get` command is printed. On Windows, `Rtools` must be installed. On `macOS`, `Xcode Command Line Tools` must be installed. See the new vignette `Install 'rJava' from source` for more details.
8 |
9 | - New function `java_get_home()` to get currently set `JAVA_HOME`. This is just a shortcut to `Sys.getenv("JAVA_HOME")`, as it is faster to type and can be even faster then used with autocomplete.
10 |
11 | ## Improvements
12 |
13 | - Download progress printing in `java_download()` respects the `quiet` argument now (internally passing the value to `curl::curl_download()`).
14 |
15 | - More robust Java version detection in `java_check_version_cmd()`.
16 |
17 | - `java_quick_install()` now also invisibly returns the path to `JAVA_HOME`.
18 |
19 | - Added `{rlang}` as a dependency, as `{cli}` uses it anyway for the functions that we use in `{rJavaEnv}`, but does not declare it as a dependency. Therefore this previously might have caused annoyances to the users, as after installing `{rJavaEnv}` they could not use any of the functions until they installed `{rlang}` manually.
20 |
21 | # rJavaEnv 0.3.0
22 |
23 | ## New features
24 |
25 | - `Java` version (currently still only for `Amazon Corretto`) is now determined dynamically using the official GitHub `json` with releases, so when new `Java` version becomes available, you will not be depenent on `rJavaEnv` to be updated. As a fallback, versions up to 24 are hardcoded.
26 |
27 | - Added `force` argument to `java_download()`. When set to `TRUE`, allows to overwrite the distribution file if it already exist in the cache. This save the trouble of deleting the cached file with `java_clear()` before re-downloading.
28 |
29 | - Added a new function `java_valid_versions()` allows to retrieve a list of all available `Java` versions for the current automatically detected OS and CPU architecture, or user-specified platform and architecture.
30 |
31 | ## Improvements
32 |
33 | - Better command line `Java` detection (thanks to Jonas Lieth)
34 |
35 | - Test coverage is now 7.2%
36 |
37 | # rJavaEnv 0.2.2 (2024-09-13)
38 |
39 | * Hot fix: improve robustness of setting `Java` environment in the current session with either `use_java()` or `java_quick_install()`. See bug fix below.
40 |
41 | * Bug fix: Setting Java environment via `rJava::.jniInitialized()` rendered impossible changing Java version for `rJava`-dependent packages, because it somehow pre-initialised `rJava`
42 |
43 | # rJavaEnv 0.2.1 (2024-09-03)
44 |
45 | * Documentation and description clean-up
46 |
47 | # rJavaEnv 0.2.0 (2024-08-28)
48 |
49 | * Breaking change: `java_check_version_cmd()` and `java_check_version_rjava()` now return detected `Java` version instead of `TRUE`/`FALSE`
50 |
51 | * New function `use_java()` to download, install and set `Java` from cache for the current sesssion, without touching the current project/working directory. This is intended for use with `targets` and `callr`.
52 |
53 | * New vignette on using the package with `targets' and 'callr`
54 |
55 | * Updated documentation with clearer instructions on cache folder cleanup before removing the package
56 |
57 | * Depends on `R` > 4.0 to be able to write to the package cache directory without extra user warning. Cache cleanup and management functions are provided, as well as the documentation in both README and vignettes.
58 |
59 | # rJavaEnv 0.1.2
60 |
61 | * Fixed broken links in README.md
62 |
63 | # rJavaEnv 0.1.1
64 |
65 | * Improved documentation
66 |
67 | * Better handling of cache directory
68 |
69 | * Bug fixes and changes to address CRAN reviewer's comments to the first submission
70 |
71 | # rJavaEnv 0.1.0
72 |
73 | * Initial release
74 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_download-mocked.R:
--------------------------------------------------------------------------------
1 | # Mocked unit tests for java_download()
2 | test_that("java_download handles successful download and checksum", {
3 | local_cache_path <- withr::local_tempdir()
4 |
5 | # MOCK THE SLOW NETWORK CALL
6 | local_mocked_bindings(
7 | java_valid_versions = function(...) c("8", "11", "17", "21")
8 | )
9 |
10 | local_mocked_bindings(
11 | curl_download = function(url, destfile, ...) {
12 | if (grepl("\\.md5$", destfile)) {
13 | writeLines("dummymd5checksum", destfile)
14 | } else {
15 | writeLines("dummy content", destfile)
16 | }
17 | },
18 | .package = "curl"
19 | )
20 |
21 | local_mocked_bindings(
22 | md5sum = function(files) setNames("dummymd5checksum", files),
23 | .package = "tools"
24 | )
25 |
26 | expect_silent(
27 | result_path <- java_download(
28 | version = "21",
29 | cache_path = local_cache_path,
30 | quiet = TRUE
31 | )
32 | )
33 | expect_true(file.exists(result_path))
34 | })
35 |
36 | test_that("java_download aborts on MD5 checksum mismatch", {
37 | local_cache_path <- withr::local_tempdir()
38 |
39 | # MOCK THE SLOW NETWORK CALL
40 | local_mocked_bindings(
41 | java_valid_versions = function(...) c("8", "11", "17", "21")
42 | )
43 |
44 | local_mocked_bindings(
45 | curl_download = function(url, destfile, ...) {
46 | if (grepl("\\.md5$", destfile)) {
47 | writeLines("expected_checksum", destfile)
48 | } else {
49 | writeLines("some content", destfile)
50 | }
51 | },
52 | .package = "curl"
53 | )
54 |
55 | local_mocked_bindings(
56 | md5sum = function(files) setNames("actual_checksum_mismatch", files),
57 | .package = "tools"
58 | )
59 |
60 | expect_error(
61 | java_download(version = "21", cache_path = local_cache_path, quiet = TRUE),
62 | "MD5 checksum mismatch"
63 | )
64 | })
65 |
66 | test_that("java_download skips download if file exists and force is FALSE", {
67 | local_cache_path <- withr::local_tempdir()
68 | dest_dir <- file.path(local_cache_path, "distrib")
69 | dir.create(dest_dir, recursive = TRUE)
70 |
71 | # MOCK THE SLOW NETWORK CALL
72 | local_mocked_bindings(
73 | java_valid_versions = function(...) c("8", "11", "17", "21")
74 | )
75 |
76 | platform <- platform_detect()$os
77 | arch <- platform_detect()$arch
78 | java_urls <- java_urls_load()
79 | url_template <- java_urls[["Corretto"]][[platform]][[arch]]
80 | url <- gsub("\\{version\\}", "21", url_template)
81 | expected_file_path <- file.path(dest_dir, basename(url))
82 | file.create(expected_file_path)
83 |
84 | local_mocked_bindings(
85 | curl_download = function(...) {
86 | stop("curl_download should not have been called!")
87 | },
88 | .package = "curl"
89 | )
90 |
91 | result <- java_download(
92 | version = "21",
93 | cache_path = local_cache_path,
94 | platform = platform,
95 | arch = arch,
96 | quiet = TRUE,
97 | force = FALSE
98 | )
99 |
100 | expect_equal(normalizePath(result), normalizePath(expected_file_path))
101 | })
102 |
103 |
104 | test_that("java_download overwrites if file exists and force is TRUE", {
105 | local_cache_path <- withr::local_tempdir()
106 | dest_dir <- file.path(local_cache_path, "distrib")
107 | dir.create(dest_dir, recursive = TRUE)
108 |
109 | # MOCK THE SLOW NETWORK CALL
110 | local_mocked_bindings(
111 | java_valid_versions = function(...) c("8", "11", "17", "21")
112 | )
113 |
114 | platform <- platform_detect()$os
115 | arch <- platform_detect()$arch
116 | java_urls <- java_urls_load()
117 | url_template <- java_urls[["Corretto"]][[platform]][[arch]]
118 | url <- gsub("\\{version\\}", "21", url_template)
119 | expected_file_path <- file.path(dest_dir, basename(url))
120 | writeLines("old content", expected_file_path)
121 |
122 | curl_call_count <- 0
123 | local_mocked_bindings(
124 | curl_download = function(url, destfile, ...) {
125 | curl_call_count <<- curl_call_count + 1
126 | if (grepl("\\.md5$", destfile)) {
127 | writeLines("new_checksum", destfile)
128 | } else {
129 | writeLines("new content", destfile)
130 | }
131 | },
132 | .package = "curl"
133 | )
134 |
135 | local_mocked_bindings(
136 | md5sum = function(files) setNames("new_checksum", files),
137 | .package = "tools"
138 | )
139 |
140 | java_download(
141 | version = "21",
142 | cache_path = local_cache_path,
143 | platform = platform,
144 | arch = arch,
145 | quiet = TRUE,
146 | force = TRUE
147 | )
148 |
149 | expect_equal(curl_call_count, 2)
150 | expect_equal(readLines(expected_file_path), "new content")
151 | })
152 |
--------------------------------------------------------------------------------
/tests/testthat/test-internal_utilities_version.R:
--------------------------------------------------------------------------------
1 | # Unit tests for parsing Java version output
2 | # These tests focus on verifying that Java version strings are parsed correctly
3 |
4 | test_that("java_check_version_system regex extracts OpenJDK 17 version correctly", {
5 | # We test the regex parsing logic that java_check_version_system uses
6 | # by simulating what it does with the java version output
7 |
8 | java_ver_string <- 'openjdk version "17.0.1" 2021-10-19'
9 | matches <- regexec(
10 | '(openjdk|java) (version )?(\\\")?([0-9]{1,2})',
11 | java_ver_string
12 | )
13 | major_java_ver <- regmatches(java_ver_string, matches)[[1]][5]
14 |
15 | expect_equal(major_java_ver, "17")
16 | })
17 |
18 | test_that("java_check_version_system regex extracts Java 11 version correctly", {
19 | java_ver_string <- 'openjdk version "11.0.13" 2021-10-19'
20 | matches <- regexec(
21 | '(openjdk|java) (version )?(\\\")?([0-9]{1,2})',
22 | java_ver_string
23 | )
24 | major_java_ver <- regmatches(java_ver_string, matches)[[1]][5]
25 |
26 | expect_equal(major_java_ver, "11")
27 | })
28 |
29 | test_that("java_check_version_system regex extracts Java 8 version correctly", {
30 | java_ver_string <- 'java version "1.8.0_292"'
31 | matches <- regexec(
32 | '(openjdk|java) (version )?(\\\")?([0-9]{1,2})',
33 | java_ver_string
34 | )
35 | major_java_ver <- regmatches(java_ver_string, matches)[[1]][5]
36 |
37 | # Java 8 returns "1", which should be converted to "8"
38 | expect_equal(major_java_ver, "1")
39 |
40 | # The function then converts "1" to "8"
41 | if (major_java_ver == "1") {
42 | major_java_ver <- "8"
43 | }
44 | expect_equal(major_java_ver, "8")
45 | })
46 |
47 | test_that("java_check_version_system regex extracts Java 21 version correctly", {
48 | java_ver_string <- 'openjdk version "21.0.1" 2023-10-17'
49 | matches <- regexec(
50 | '(openjdk|java) (version )?(\\\")?([0-9]{1,2})',
51 | java_ver_string
52 | )
53 | major_java_ver <- regmatches(java_ver_string, matches)[[1]][5]
54 |
55 | expect_equal(major_java_ver, "21")
56 | })
57 |
58 | test_that("java_version_check_rscript output parsing for version 17", {
59 | # Test the parsing of output from java_version_check_rscript
60 | output <- c("rJava and other rJava/Java-based packages will use Java version: \"17.0.1\"")
61 | cleaned_output <- cli::ansi_strip(output[1])
62 | major_java_ver <- sub('.*version: \\"([0-9]+).*', '\\1', cleaned_output)
63 |
64 | if (major_java_ver == "1") {
65 | major_java_ver <- "8"
66 | }
67 |
68 | expect_equal(major_java_ver, "17")
69 | })
70 |
71 | test_that("java_version_check_rscript output parsing for version 1.8", {
72 | output <- c("rJava and other rJava/Java-based packages will use Java version: \"1.8.0\"")
73 | cleaned_output <- cli::ansi_strip(output[1])
74 | major_java_ver <- sub('.*version: \\"([0-9]+).*', '\\1', cleaned_output)
75 |
76 | # For Java 8, version string starts with "1"
77 | expect_equal(major_java_ver, "1")
78 |
79 | if (major_java_ver == "1") {
80 | major_java_ver <- "8"
81 | }
82 | expect_equal(major_java_ver, "8")
83 | })
84 |
85 | test_that("java_check_version_rjava silent behavior", {
86 | # This test verifies that when rJava is not installed, the function returns FALSE
87 | local_mocked_bindings(
88 | find.package = function(package, quiet = TRUE) {
89 | # Simulate rJava not being found
90 | character(0)
91 | },
92 | .package = "base"
93 | )
94 |
95 | result <- java_check_version_rjava(java_home = "/mock/java", quiet = TRUE)
96 | expect_false(result)
97 | })
98 |
99 | test_that("java_check_version_cmd with quiet = TRUE doesn't throw", {
100 | # When JAVA_HOME is not set and we don't provide a java_home
101 | withr::local_envvar(c("JAVA_HOME" = NA))
102 |
103 | result <- java_check_version_cmd(java_home = NULL, quiet = TRUE)
104 | # Should return FALSE gracefully without errors
105 | expect_false(result)
106 | })
107 |
108 | test_that("Sys.which mock works correctly", {
109 | # Verify our mocking approach works
110 | local_mocked_bindings(
111 | Sys.which = function(x) {
112 | if (x == "java") "/usr/bin/java" else ""
113 | },
114 | .package = "base"
115 | )
116 |
117 | expect_equal(Sys.which("java"), "/usr/bin/java")
118 | expect_equal(Sys.which("nonexistent"), "")
119 | })
120 |
121 | test_that("system2 mock can return version output", {
122 | # Verify our mocking approach works for system2
123 | local_mocked_bindings(
124 | system2 = function(cmd, args = NULL, ...) {
125 | c('openjdk version "11.0.1"')
126 | },
127 | .package = "base"
128 | )
129 |
130 | result <- system2("java", args = "-version")
131 | expect_equal(result[1], 'openjdk version "11.0.1"')
132 | })
133 |
--------------------------------------------------------------------------------
/R/java_manage_installed_cache.R:
--------------------------------------------------------------------------------
1 | #' List the contents of the Java installations cache folder
2 | #'
3 | #' @param output The format of the output: "data.frame" or "vector". Defaults to "data.frame".
4 | #' @param cache_path The cache directory to list. Defaults to the user-specific data directory. Not recommended to change.
5 | #' @inheritParams global_quiet_param
6 | #' @return A data frame or character vector with the contents of the cache directory.
7 | #' @keywords internal
8 | java_list_installed_cache <- function(
9 | output = c("data.frame", "vector"),
10 | quiet = TRUE,
11 | cache_path = getOption("rJavaEnv.cache_path")
12 | ) {
13 | output <- match.arg(output)
14 | installed_cache_path <- file.path(cache_path, "installed")
15 |
16 | if (!dir.exists(installed_cache_path)) {
17 | cli::cli_alert_danger("No Java distributions have been installed yet.")
18 | return(character(0))
19 | }
20 |
21 | if (!quiet) cli::cli_inform("Contents of the Java installations cache folder:")
22 |
23 | # List directories up to the specified depth
24 | java_paths <- list.dirs(installed_cache_path, recursive = TRUE, full.names = TRUE)
25 |
26 | java_paths <- java_paths[vapply(java_paths, function(x) {
27 | length(strsplit(x, .Platform$file.sep)[[1]]) == length(strsplit(installed_cache_path, .Platform$file.sep)[[1]]) + 3
28 | }, logical(1))]
29 |
30 | if (length(java_paths) == 0) {
31 | return(character(0))
32 | }
33 |
34 | if (output == "vector") {
35 | return(unname(java_paths))
36 | } else if (output == "data.frame") {
37 | java_info <- lapply(java_paths, function(path) {
38 | parts <- strsplit(path, .Platform$file.sep)[[1]]
39 | parts <- parts[(length(parts) - 2):length(parts)]
40 | names(parts) <- c("platform", "arch", "version")
41 | parts <- c(path = path, parts)
42 | return(parts)
43 | })
44 | java_info_df <- do.call(rbind, lapply(java_info, function(info) as.data.frame(t(info), stringsAsFactors = FALSE)))
45 | rownames(java_info_df) <- NULL
46 | return(java_info_df)
47 | }
48 | }
49 |
50 | #' Clear the Java installations cache folder
51 | #'
52 | #' @param cache_path The cache directory to clear. Defaults to the user-specific data directory.
53 | #' @param check Whether to list the contents of the cache directory before clearing it. Defaults to TRUE.
54 | #' @param delete_all Whether to delete all installations without prompting. Defaults to FALSE.
55 | #' @return A message indicating whether the cache was cleared or not.
56 | #'
57 | #' @keywords internal
58 | java_clear_installed_cache <- function(
59 | check = TRUE,
60 | delete_all = FALSE,
61 | cache_path = getOption("rJavaEnv.cache_path")
62 | ) {
63 | rje_consent_check()
64 |
65 | installed_cache_path <- file.path(cache_path, "installed")
66 |
67 | if (!dir.exists(installed_cache_path)) {
68 | cli::cli_inform("Java installations cache is already empty.")
69 | return(invisible(NULL))
70 | }
71 |
72 | if (delete_all) {
73 | unlink(file.path(installed_cache_path, "*"), recursive = TRUE)
74 | cli::cli_inform("Java installations cache cleared.")
75 | return(invisible(NULL))
76 | }
77 |
78 | if (check) {
79 | installations <- java_list_installed_cache(cache_path, quiet = FALSE, output = "vector")
80 | if (length(installations) == 0) {
81 | cli::cli_inform("No Java installations found to clear.")
82 | return(invisible(NULL))
83 | }
84 |
85 | cli::cli_alert_info("Existing Java installations:")
86 | for (i in seq_along(installations)) {
87 | cli::cli_inform("{i}: {installations[i]}")
88 | }
89 |
90 | cli::cli_alert_info("Enter the number of the installation to delete, 'all' to delete all, or '0' or any other character to cancel:")
91 | response <- readline()
92 |
93 | if (tolower(response) == "all") {
94 | unlink(file.path(installed_cache_path, "*"), recursive = TRUE)
95 | cli::cli_inform("All Java installations have been cleared.")
96 | } else {
97 | choice <- suppressWarnings(as.integer(response))
98 | if (is.na(choice) || choice == 0 || choice > length(installations)) {
99 | cli::cli_inform("No installations were cleared.")
100 | } else {
101 | unlink(installations[choice], recursive = TRUE)
102 | cli::cli_inform("Java installation {choice} has been cleared.")
103 | }
104 | }
105 | } else {
106 | cli::cli_alert_info("Are you sure you want to clear the Java installations cache? (yes/no)")
107 | response <- readline()
108 | if (tolower(response) == "yes") {
109 | unlink(file.path(installed_cache_path, "*"), recursive = TRUE)
110 | cli::cli_inform("Java installations cache cleared.")
111 | } else {
112 | cli::cli_inform("Java installations cache was not cleared.")
113 | }
114 | }
115 |
116 | return(invisible(NULL))
117 | }
118 |
--------------------------------------------------------------------------------
/vignettes/data-for-vignettes/rJava_dlstats.csv:
--------------------------------------------------------------------------------
1 | start;end;downloads;package
2 | 2014-01-01;2014-01-31;21206;rJava
3 | 2014-02-01;2014-02-28;20698;rJava
4 | 2014-03-01;2014-03-31;22972;rJava
5 | 2014-04-01;2014-04-30;30754;rJava
6 | 2014-05-01;2014-05-31;27456;rJava
7 | 2014-06-01;2014-06-30;79683;rJava
8 | 2014-07-01;2014-07-31;68628;rJava
9 | 2014-08-01;2014-08-31;53476;rJava
10 | 2014-09-01;2014-09-30;43039;rJava
11 | 2014-10-01;2014-10-31;42962;rJava
12 | 2014-11-01;2014-11-30;44860;rJava
13 | 2014-12-01;2014-12-31;43873;rJava
14 | 2015-01-01;2015-01-31;47579;rJava
15 | 2015-02-01;2015-02-28;45369;rJava
16 | 2015-03-01;2015-03-31;55592;rJava
17 | 2015-04-01;2015-04-30;59371;rJava
18 | 2015-05-01;2015-05-31;58762;rJava
19 | 2015-06-01;2015-06-30;70761;rJava
20 | 2015-07-01;2015-07-31;77745;rJava
21 | 2015-08-01;2015-08-31;93620;rJava
22 | 2015-09-01;2015-09-30;98996;rJava
23 | 2015-10-01;2015-10-31;105546;rJava
24 | 2015-11-01;2015-11-30;113165;rJava
25 | 2015-12-01;2015-12-31;92368;rJava
26 | 2016-01-01;2016-01-31;116670;rJava
27 | 2016-02-01;2016-02-29;105817;rJava
28 | 2016-03-01;2016-03-31;104942;rJava
29 | 2016-04-01;2016-04-30;91556;rJava
30 | 2016-05-01;2016-05-31;118943;rJava
31 | 2016-06-01;2016-06-30;117215;rJava
32 | 2016-07-01;2016-07-31;106574;rJava
33 | 2016-08-01;2016-08-31;108471;rJava
34 | 2016-09-01;2016-09-30;120946;rJava
35 | 2016-10-01;2016-10-31;134884;rJava
36 | 2016-11-01;2016-11-30;147999;rJava
37 | 2016-12-01;2016-12-31;118118;rJava
38 | 2017-01-01;2017-01-31;123550;rJava
39 | 2017-02-01;2017-02-28;138221;rJava
40 | 2017-03-01;2017-03-31;162562;rJava
41 | 2017-04-01;2017-04-30;153474;rJava
42 | 2017-05-01;2017-05-31;164487;rJava
43 | 2017-06-01;2017-06-30;153560;rJava
44 | 2017-07-01;2017-07-31;143023;rJava
45 | 2017-08-01;2017-08-31;128602;rJava
46 | 2017-09-01;2017-09-30;140409;rJava
47 | 2017-10-01;2017-10-31;177898;rJava
48 | 2017-11-01;2017-11-30;193822;rJava
49 | 2017-12-01;2017-12-31;155733;rJava
50 | 2018-01-01;2018-01-31;165852;rJava
51 | 2018-02-01;2018-02-28;147561;rJava
52 | 2018-03-01;2018-03-31;159540;rJava
53 | 2018-04-01;2018-04-30;159216;rJava
54 | 2018-05-01;2018-05-31;162024;rJava
55 | 2018-06-01;2018-06-30;177379;rJava
56 | 2018-07-01;2018-07-31;158981;rJava
57 | 2018-08-01;2018-08-31;146357;rJava
58 | 2018-09-01;2018-09-30;178890;rJava
59 | 2018-10-01;2018-10-31;222617;rJava
60 | 2018-11-01;2018-11-30;185174;rJava
61 | 2018-12-01;2018-12-31;140504;rJava
62 | 2019-01-01;2019-01-31;171958;rJava
63 | 2019-02-01;2019-02-28;157729;rJava
64 | 2019-03-01;2019-03-31;180216;rJava
65 | 2019-04-01;2019-04-30;226195;rJava
66 | 2019-05-01;2019-05-31;234531;rJava
67 | 2019-06-01;2019-06-30;187438;rJava
68 | 2019-07-01;2019-07-31;193139;rJava
69 | 2019-08-01;2019-08-31;181692;rJava
70 | 2019-09-01;2019-09-30;218554;rJava
71 | 2019-10-01;2019-10-31;224568;rJava
72 | 2019-11-01;2019-11-30;211361;rJava
73 | 2019-12-01;2019-12-31;191373;rJava
74 | 2020-01-01;2020-01-31;188198;rJava
75 | 2020-02-01;2020-02-29;177194;rJava
76 | 2020-03-01;2020-03-31;278531;rJava
77 | 2020-04-01;2020-04-30;235117;rJava
78 | 2020-05-01;2020-05-31;216240;rJava
79 | 2020-06-01;2020-06-30;209888;rJava
80 | 2020-07-01;2020-07-31;234058;rJava
81 | 2020-08-01;2020-08-31;194163;rJava
82 | 2020-09-01;2020-09-30;222106;rJava
83 | 2020-10-01;2020-10-31;241788;rJava
84 | 2020-11-01;2020-11-30;215793;rJava
85 | 2020-12-01;2020-12-31;180348;rJava
86 | 2021-01-01;2021-01-31;168354;rJava
87 | 2021-02-01;2021-02-28;155617;rJava
88 | 2021-03-01;2021-03-31;183883;rJava
89 | 2021-04-01;2021-04-30;178903;rJava
90 | 2021-05-01;2021-05-31;178902;rJava
91 | 2021-06-01;2021-06-30;173072;rJava
92 | 2021-07-01;2021-07-31;141658;rJava
93 | 2021-08-01;2021-08-31;170959;rJava
94 | 2021-09-01;2021-09-30;254287;rJava
95 | 2021-10-01;2021-10-31;274728;rJava
96 | 2021-11-01;2021-11-30;223077;rJava
97 | 2021-12-01;2021-12-31;210562;rJava
98 | 2022-01-01;2022-01-31;192186;rJava
99 | 2022-02-01;2022-02-28;154710;rJava
100 | 2022-03-01;2022-03-31;255524;rJava
101 | 2022-04-01;2022-04-30;571935;rJava
102 | 2022-05-01;2022-05-31;852808;rJava
103 | 2022-06-01;2022-06-30;725289;rJava
104 | 2022-07-01;2022-07-31;639130;rJava
105 | 2022-08-01;2022-08-31;712597;rJava
106 | 2022-09-01;2022-09-30;633770;rJava
107 | 2022-10-01;2022-10-31;433795;rJava
108 | 2022-11-01;2022-11-30;337744;rJava
109 | 2022-12-01;2022-12-31;319878;rJava
110 | 2023-01-01;2023-01-31;403060;rJava
111 | 2023-02-01;2023-02-28;361259;rJava
112 | 2023-03-01;2023-03-31;475392;rJava
113 | 2023-04-01;2023-04-30;442267;rJava
114 | 2023-05-01;2023-05-31;400598;rJava
115 | 2023-06-01;2023-06-30;318804;rJava
116 | 2023-07-01;2023-07-31;176955;rJava
117 | 2023-08-01;2023-08-31;139944;rJava
118 | 2023-09-01;2023-09-30;137718;rJava
119 | 2023-10-01;2023-10-31;280514;rJava
120 | 2023-11-01;2023-11-30;285721;rJava
121 | 2023-12-01;2023-12-31;302552;rJava
122 | 2024-01-01;2024-01-31;328002;rJava
123 | 2024-02-01;2024-02-29;228557;rJava
124 | 2024-03-01;2024-03-31;194654;rJava
125 | 2024-04-01;2024-04-30;187262;rJava
126 | 2024-05-01;2024-05-31;198761;rJava
127 | 2024-06-01;2024-06-30;169666;rJava
128 | 2024-07-01;2024-07-31;148789;rJava
129 | 2024-08-01;2024-08-31;135307;rJava
130 | 2024-09-01;2024-09-26;107725;rJava
131 |
--------------------------------------------------------------------------------
/R/java_manage_project.R:
--------------------------------------------------------------------------------
1 | #' List the Java versions symlinked in the current project
2 | #'
3 | #' @param project_path The project directory to list. Defaults to the current working directory.
4 | #' @param output The format of the output: "data.frame" or "vector". Defaults to "data.frame".
5 | #' @inheritParams global_quiet_param
6 | #' @return A data frame or character vector with the symlinked Java versions in the project directory.
7 | #' @keywords internal
8 | java_list_in_project <- function(
9 | project_path = NULL,
10 | output = c("data.frame", "vector"),
11 | quiet = TRUE
12 | ) {
13 |
14 | # Resolve the project path
15 | # consistent with renv behavior
16 | # https://github.com/rstudio/renv/blob/d6bced36afa0ad56719ca78be6773e9b4bbb078f/R/init.R#L69-L86
17 | project_path <- ifelse(is.null(project_path), getwd(), project_path)
18 |
19 | output <- match.arg(output)
20 | java_symlink_dir <- file.path(project_path, "rjavaenv")
21 |
22 | if (!dir.exists(java_symlink_dir)) {
23 | cli::cli_alert_danger("No Java has been installed in the project.")
24 | return(invisible(NULL))
25 | }
26 |
27 |
28 | # List directories up to the specified depth
29 | java_paths <- list.dirs(java_symlink_dir, recursive = TRUE, full.names = TRUE)
30 |
31 | java_paths <- java_paths[vapply(java_paths, function(x) {
32 | length(strsplit(x, .Platform$file.sep)[[1]]) == length(strsplit(java_symlink_dir, .Platform$file.sep)[[1]]) + 3
33 | }, logical(1))]
34 |
35 | if (length(java_paths) == 0) {
36 | cli::cli_alert_danger("No Java has been installed in the project.")
37 | return(invisible(NULL))
38 | }
39 |
40 | if (!quiet) cli::cli_inform("Contents of the Java symlinks in the project folder:")
41 |
42 | if (output == "vector") {
43 | return(unname(java_paths))
44 | } else if (output == "data.frame") {
45 | java_info <- lapply(java_paths, function(path) {
46 | parts <- strsplit(path, .Platform$file.sep)[[1]]
47 | parts <- parts[(length(parts) - 2):length(parts)]
48 | names(parts) <- c("platform", "arch", "version")
49 | parts <- c(path = path, parts)
50 | return(parts)
51 | })
52 | java_info_df <- do.call(rbind, lapply(java_info, function(info) as.data.frame(t(info), stringsAsFactors = FALSE)))
53 | rownames(java_info_df) <- NULL
54 | return(java_info_df)
55 | }
56 | }
57 |
58 | #' Clear the Java versions symlinked in the current project
59 | #'
60 | #' @param project_path The project directory to clear. Defaults to the current working directory.
61 | #' @param check Whether to list the symlinked Java versions before clearing them. Defaults to TRUE.
62 | #' @param delete_all Whether to delete all symlinks without prompting. Defaults to FALSE.
63 | #' @return A message indicating whether the symlinks were cleared or not.
64 | #'
65 | #' @keywords internal
66 | java_clear_in_project <- function(
67 | project_path = NULL,
68 | check = TRUE,
69 | delete_all = FALSE
70 | ) {
71 | rje_consent_check()
72 |
73 | # Resolve the project path
74 | # consistent with renv behavior
75 | # https://github.com/rstudio/renv/blob/d6bced36afa0ad56719ca78be6773e9b4bbb078f/R/init.R#L69-L86
76 | project_path <- ifelse(is.null(project_path), getwd(), project_path)
77 |
78 | java_symlink_dir <- file.path(project_path, "rjavaenv")
79 |
80 | if (!dir.exists(java_symlink_dir)) {
81 | cli::cli_inform("Java symlink directory does not exist in the project.")
82 | return(invisible(NULL))
83 | }
84 |
85 | if (delete_all) {
86 | unlink(file.path(java_symlink_dir), recursive = TRUE)
87 | cli::cli_inform("All Java symlinks in the project have been cleared.")
88 | return(invisible(NULL))
89 | }
90 |
91 | if (check) {
92 | symlinks <- java_list_in_project(project_path = project_path, output = "vector")
93 | if (length(symlinks) == 0) {
94 | cli::cli_inform("No Java symlinks found to clear.")
95 | return(invisible(NULL))
96 | }
97 |
98 | cli::cli_alert_info("Existing Java symlinks:")
99 | for (i in seq_along(symlinks)) {
100 | cli::cli_inform("{i}: {symlinks[i]}")
101 | }
102 |
103 | cli::cli_alert_info("Enter the number of the symlink to delete, 'all' to delete all, or '0' or any other character to cancel:")
104 | response <- readline()
105 |
106 | if (tolower(response) == "all") {
107 | unlink(file.path(java_symlink_dir, "*"), recursive = TRUE)
108 | cli::cli_inform("All Java symlinks in the project have been cleared.")
109 | } else {
110 | choice <- suppressWarnings(as.integer(response))
111 | if (is.na(choice) || choice == 0 || choice > length(symlinks)) {
112 | cli::cli_inform("No symlinks were cleared.")
113 | } else {
114 | unlink(symlinks[choice], recursive = TRUE)
115 | cli::cli_inform("Java symlink {choice} has been cleared.")
116 | }
117 | }
118 | } else {
119 | cli::cli_alert_info("Are you sure you want to clear all Java symlinks in the project? (yes/no)")
120 | response <- readline()
121 | if (tolower(response) == "yes") {
122 | unlink(file.path(java_symlink_dir, "*"), recursive = TRUE)
123 | cli::cli_inform("All Java symlinks in the project have been cleared.")
124 | } else {
125 | cli::cli_inform("No Java symlinks were cleared.")
126 | }
127 | }
128 |
129 | return(invisible(NULL))
130 | }
131 |
--------------------------------------------------------------------------------
/vignettes/data-for-vignettes/ggplot2_dlstats.csv:
--------------------------------------------------------------------------------
1 | start;end;downloads;package
2 | 2014-01-01;2014-01-31;33457;ggplot2
3 | 2014-02-01;2014-02-28;36817;ggplot2
4 | 2014-03-01;2014-03-31;47652;ggplot2
5 | 2014-04-01;2014-04-30;55404;ggplot2
6 | 2014-05-01;2014-05-31;54371;ggplot2
7 | 2014-06-01;2014-06-30;201761;ggplot2
8 | 2014-07-01;2014-07-31;92133;ggplot2
9 | 2014-08-01;2014-08-31;56890;ggplot2
10 | 2014-09-01;2014-09-30;70136;ggplot2
11 | 2014-10-01;2014-10-31;82817;ggplot2
12 | 2014-11-01;2014-11-30;79063;ggplot2
13 | 2014-12-01;2014-12-31;65079;ggplot2
14 | 2015-01-01;2015-01-31;85349;ggplot2
15 | 2015-02-01;2015-02-28;95591;ggplot2
16 | 2015-03-01;2015-03-31;140066;ggplot2
17 | 2015-04-01;2015-04-30;146008;ggplot2
18 | 2015-05-01;2015-05-31;142558;ggplot2
19 | 2015-06-01;2015-06-30;134730;ggplot2
20 | 2015-07-01;2015-07-31;126061;ggplot2
21 | 2015-08-01;2015-08-31;136617;ggplot2
22 | 2015-09-01;2015-09-30;176111;ggplot2
23 | 2015-10-01;2015-10-31;195243;ggplot2
24 | 2015-11-01;2015-11-30;198381;ggplot2
25 | 2015-12-01;2015-12-31;181234;ggplot2
26 | 2016-01-01;2016-01-31;228779;ggplot2
27 | 2016-02-01;2016-02-29;247028;ggplot2
28 | 2016-03-01;2016-03-31;262481;ggplot2
29 | 2016-04-01;2016-04-30;219765;ggplot2
30 | 2016-05-01;2016-05-31;249214;ggplot2
31 | 2016-06-01;2016-06-30;236981;ggplot2
32 | 2016-07-01;2016-07-31;210707;ggplot2
33 | 2016-08-01;2016-08-31;226941;ggplot2
34 | 2016-09-01;2016-09-30;294401;ggplot2
35 | 2016-10-01;2016-10-31;326941;ggplot2
36 | 2016-11-01;2016-11-30;435630;ggplot2
37 | 2016-12-01;2016-12-31;335209;ggplot2
38 | 2017-01-01;2017-01-31;411301;ggplot2
39 | 2017-02-01;2017-02-28;407285;ggplot2
40 | 2017-03-01;2017-03-31;464633;ggplot2
41 | 2017-04-01;2017-04-30;433774;ggplot2
42 | 2017-05-01;2017-05-31;420708;ggplot2
43 | 2017-06-01;2017-06-30;359623;ggplot2
44 | 2017-07-01;2017-07-31;318111;ggplot2
45 | 2017-08-01;2017-08-31;311367;ggplot2
46 | 2017-09-01;2017-09-30;389654;ggplot2
47 | 2017-10-01;2017-10-31;450465;ggplot2
48 | 2017-11-01;2017-11-30;454752;ggplot2
49 | 2017-12-01;2017-12-31;351634;ggplot2
50 | 2018-01-01;2018-01-31;419372;ggplot2
51 | 2018-02-01;2018-02-28;415838;ggplot2
52 | 2018-03-01;2018-03-31;495357;ggplot2
53 | 2018-04-01;2018-04-30;511879;ggplot2
54 | 2018-05-01;2018-05-31;507604;ggplot2
55 | 2018-06-01;2018-06-30;439156;ggplot2
56 | 2018-07-01;2018-07-31;552553;ggplot2
57 | 2018-08-01;2018-08-31;497218;ggplot2
58 | 2018-09-01;2018-09-30;647281;ggplot2
59 | 2018-10-01;2018-10-31;822873;ggplot2
60 | 2018-11-01;2018-11-30;809889;ggplot2
61 | 2018-12-01;2018-12-31;585313;ggplot2
62 | 2019-01-01;2019-01-31;726400;ggplot2
63 | 2019-02-01;2019-02-28;720326;ggplot2
64 | 2019-03-01;2019-03-31;771832;ggplot2
65 | 2019-04-01;2019-04-30;830500;ggplot2
66 | 2019-05-01;2019-05-31;830059;ggplot2
67 | 2019-06-01;2019-06-30;702976;ggplot2
68 | 2019-07-01;2019-07-31;712857;ggplot2
69 | 2019-08-01;2019-08-31;719862;ggplot2
70 | 2019-09-01;2019-09-30;988740;ggplot2
71 | 2019-10-01;2019-10-31;1058606;ggplot2
72 | 2019-11-01;2019-11-30;958562;ggplot2
73 | 2019-12-01;2019-12-31;869022;ggplot2
74 | 2020-01-01;2020-01-31;990079;ggplot2
75 | 2020-02-01;2020-02-29;1021046;ggplot2
76 | 2020-03-01;2020-03-31;1743064;ggplot2
77 | 2020-04-01;2020-04-30;1788712;ggplot2
78 | 2020-05-01;2020-05-31;1688318;ggplot2
79 | 2020-06-01;2020-06-30;1653368;ggplot2
80 | 2020-07-01;2020-07-31;1455078;ggplot2
81 | 2020-08-01;2020-08-31;1400458;ggplot2
82 | 2020-09-01;2020-09-30;1585801;ggplot2
83 | 2020-10-01;2020-10-31;1696668;ggplot2
84 | 2020-11-01;2020-11-30;1801691;ggplot2
85 | 2020-12-01;2020-12-31;905064;ggplot2
86 | 2021-01-01;2021-01-31;1128155;ggplot2
87 | 2021-02-01;2021-02-28;946051;ggplot2
88 | 2021-03-01;2021-03-31;1851241;ggplot2
89 | 2021-04-01;2021-04-30;1900989;ggplot2
90 | 2021-05-01;2021-05-31;1983929;ggplot2
91 | 2021-06-01;2021-06-30;1957952;ggplot2
92 | 2021-07-01;2021-07-31;1948565;ggplot2
93 | 2021-08-01;2021-08-31;2072506;ggplot2
94 | 2021-09-01;2021-09-30;2971064;ggplot2
95 | 2021-10-01;2021-10-31;3298060;ggplot2
96 | 2021-11-01;2021-11-30;3162372;ggplot2
97 | 2021-12-01;2021-12-31;2376174;ggplot2
98 | 2022-01-01;2022-01-31;2091880;ggplot2
99 | 2022-02-01;2022-02-28;2077216;ggplot2
100 | 2022-03-01;2022-03-31;2422703;ggplot2
101 | 2022-04-01;2022-04-30;2689183;ggplot2
102 | 2022-05-01;2022-05-31;3113536;ggplot2
103 | 2022-06-01;2022-06-30;2849346;ggplot2
104 | 2022-07-01;2022-07-31;2676911;ggplot2
105 | 2022-08-01;2022-08-31;2594350;ggplot2
106 | 2022-09-01;2022-09-30;2754884;ggplot2
107 | 2022-10-01;2022-10-31;2905716;ggplot2
108 | 2022-11-01;2022-11-30;2930801;ggplot2
109 | 2022-12-01;2022-12-31;2351346;ggplot2
110 | 2023-01-01;2023-01-31;2356847;ggplot2
111 | 2023-02-01;2023-02-28;2307038;ggplot2
112 | 2023-03-01;2023-03-31;2484066;ggplot2
113 | 2023-04-01;2023-04-30;1966351;ggplot2
114 | 2023-05-01;2023-05-31;2502717;ggplot2
115 | 2023-06-01;2023-06-30;2507430;ggplot2
116 | 2023-07-01;2023-07-31;2430173;ggplot2
117 | 2023-08-01;2023-08-31;2534005;ggplot2
118 | 2023-09-01;2023-09-30;2655965;ggplot2
119 | 2023-10-01;2023-10-31;2917801;ggplot2
120 | 2023-11-01;2023-11-30;3000819;ggplot2
121 | 2023-12-01;2023-12-31;2225776;ggplot2
122 | 2024-01-01;2024-01-31;2248917;ggplot2
123 | 2024-02-01;2024-02-29;2289545;ggplot2
124 | 2024-03-01;2024-03-31;2469492;ggplot2
125 | 2024-04-01;2024-04-30;1932736;ggplot2
126 | 2024-05-01;2024-05-31;1891742;ggplot2
127 | 2024-06-01;2024-06-30;1599144;ggplot2
128 | 2024-07-01;2024-07-31;1536478;ggplot2
129 | 2024-08-01;2024-08-31;1458005;ggplot2
130 | 2024-09-01;2024-09-26;1329676;ggplot2
131 |
--------------------------------------------------------------------------------
/R/java_valid_versions.R:
--------------------------------------------------------------------------------
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 | #' @inheritParams java_download
8 | #'
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 | #'
24 | java_valid_versions <- function(
25 | distribution = "Corretto",
26 | platform = platform_detect()$os,
27 | arch = platform_detect()$arch,
28 | force = FALSE
29 | ) {
30 | # Define cache expiry time (in hours)
31 | expiry_hours <- 8
32 |
33 | # Retrieve cached values from options
34 | valid_versions_cache <- getOption("rJavaEnv.valid_versions_cache")
35 | valid_versions_timestamp <- getOption("rJavaEnv.valid_versions_timestamp")
36 |
37 | # Return cached value if available and not expired, unless force is TRUE.
38 | if (
39 | !force &&
40 | !is.null(valid_versions_cache) &&
41 | !is.null(valid_versions_timestamp) &&
42 | as.numeric(difftime(
43 | Sys.time(),
44 | valid_versions_timestamp,
45 | units = "hours"
46 | )) <
47 | expiry_hours
48 | ) {
49 | return(valid_versions_cache)
50 | }
51 |
52 | # Select helper based on distribution value.
53 | new_versions <- switch(
54 | distribution,
55 | # "Oracle" = java_valid_versions_oracle(),
56 | "Corretto" = java_valid_major_versions_corretto(
57 | platform = platform,
58 | arch = arch
59 | ),
60 | stop("Unsupported distribution")
61 | )
62 |
63 | # Update the cache options with the new values and current timestamp.
64 | options(
65 | rJavaEnv.valid_versions_cache = new_versions,
66 | rJavaEnv.valid_versions_timestamp = Sys.time()
67 | )
68 |
69 | return(new_versions)
70 | }
71 |
72 | #' Get Available Online Versions of Amazon Corretto
73 | #'
74 | #' This function downloads the latest Amazon Corretto version information from the
75 | #' Corretto GitHub endpoint and returns a data frame with details for all eligible releases.
76 | #'
77 | #' It leverages the existing \code{platform_detect()} function to infer the current operating
78 | #' system and architecture if these are not provided.
79 | #'
80 | #' @param arch Optional character string for the target architecture (e.g., "x64").
81 | #' If \code{NULL}, it is inferred using \code{platform_detect()}.
82 | #' @param platform Optional character string for the operating system (e.g., "windows", "macos", "linux").
83 | #' If \code{NULL}, it is inferred using \code{platform_detect()}.
84 | #' @param imageType Optional character string to filter on; defaults to \code{"jdk"}. Can be set to \code{"jre"} for Windows Java Runtime Environment.
85 | #'
86 | #' @return A `character` vector of available major Corretto versions.
87 | #'
88 | #' @keywords internal
89 | #'
90 | java_valid_major_versions_corretto <- function(
91 | arch = NULL,
92 | platform = NULL,
93 | imageType = "jdk"
94 | ) {
95 | # If platform or arch are not provided, detect them using the existing function.
96 | if (is.null(platform) || is.null(arch)) {
97 | plat <- platform_detect(quiet = TRUE)
98 | if (is.null(platform)) platform <- plat$os
99 | if (is.null(arch)) arch <- plat$arch
100 | }
101 |
102 | # URL for the Corretto version information.
103 | availableVersionsUrl <- "https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json"
104 |
105 | # Fetch and parse the JSON using httr.
106 | corretto_versions <- tryCatch(
107 | {
108 | json_data <- jsonlite::read_json(availableVersionsUrl)
109 | eligible <- json_data[[platform]][[arch]][[imageType]]
110 | if (is.null(eligible)) {
111 | stop(
112 | "No eligible versions found for the specified platform, architecture, and image type."
113 | )
114 | }
115 | names(eligible)
116 | },
117 | error = function(e) {
118 | platform_arch <- paste(platform, arch, sep = "_")
119 | getOption(paste0("rJavaEnv.fallback_valid_versions_", platform_arch))
120 | }
121 | )
122 |
123 | corretto_versions <- as.character(sort(as.numeric(corretto_versions)))
124 | return(corretto_versions)
125 | }
126 |
127 | # Helper function for Oracle distribution
128 | # java_valid_versions_oracle <- function() {
129 | # oracle_api_url <- "https://java.oraclecloud.com/javaVersions"
130 | # tryCatch(
131 | # {
132 | # oracle_java_versions <- jsonlite::fromJSON(
133 | # oracle_api_url,
134 | # simplifyDataFrame = TRUE
135 | # )
136 | # # Combine "8" and "11" with the sorted versions from the API
137 | # c("8", "11", sort(as.character(oracle_java_versions$items$jdkVersion)))
138 | # },
139 | # error = function(e) {
140 | # # If the API call fails, use the fallback list stored in options.
141 | # getOption("rJavaEnv.fallback_valid_versions_current_platform")
142 | # }
143 | # )
144 | # }
145 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_env_unit.R:
--------------------------------------------------------------------------------
1 | # Unit tests for java_env.R functions
2 | # Tests java_env_set and java_env_unset with mocked system calls
3 |
4 | test_that("java_env_set (session) sets JAVA_HOME in the environment", {
5 | # Mock rje_consent_check to avoid interactive prompts
6 | local_mocked_bindings(
7 | rje_consent_check = function() TRUE,
8 | .package = "rJavaEnv"
9 | )
10 |
11 | # Mock installed.packages to avoid rJava check
12 | local_mocked_bindings(
13 | installed.packages = function(...) matrix(character(0), nrow = 0, ncol = 2),
14 | .package = "utils"
15 | )
16 |
17 | # Mock loadedNamespaces to say rJava is not loaded
18 | local_mocked_bindings(
19 | loadedNamespaces = function() character(0),
20 | .package = "base"
21 | )
22 |
23 | # Mock Sys.info to return non-Linux system
24 | local_mocked_bindings(
25 | Sys.info = function() c(sysname = "Darwin"),
26 | .package = "base"
27 | )
28 |
29 | java_home_mock <- "/mock/java/home"
30 |
31 | # Use withr to temporarily capture original PATH
32 | withr::with_envvar(c("PATH" = "/usr/bin:/bin"), {
33 | java_env_set(where = "session", java_home = java_home_mock, quiet = TRUE)
34 |
35 | # Check that JAVA_HOME was set
36 | expect_equal(Sys.getenv("JAVA_HOME"), java_home_mock)
37 | # Check that PATH was modified to include java bin dir
38 | expect_true(grepl("/mock/java/home/bin", Sys.getenv("PATH")))
39 | })
40 | })
41 |
42 | test_that("java_env_set (project) writes to .Rprofile", {
43 | proj_dir <- withr::local_tempdir()
44 |
45 | local_mocked_bindings(
46 | rje_consent_check = function() TRUE,
47 | .package = "rJavaEnv"
48 | )
49 |
50 | local_mocked_bindings(
51 | installed.packages = function(...) matrix(character(0), nrow = 0, ncol = 2),
52 | .package = "utils"
53 | )
54 |
55 | local_mocked_bindings(
56 | loadedNamespaces = function() character(0),
57 | .package = "base"
58 | )
59 |
60 | local_mocked_bindings(
61 | Sys.info = function() c(sysname = "Darwin"),
62 | .package = "base"
63 | )
64 |
65 | java_env_set(where = "project", java_home = "/mock/java", project_path = proj_dir, quiet = TRUE)
66 |
67 | rprof <- file.path(proj_dir, ".Rprofile")
68 | expect_true(file.exists(rprof))
69 |
70 | content <- readLines(rprof)
71 | # Check that .Rprofile contains the rJavaEnv markers
72 | expect_true(any(grepl("# rJavaEnv begin", content)))
73 | expect_true(any(grepl("# rJavaEnv end", content)))
74 | # Check that it sets JAVA_HOME
75 | expect_true(any(grepl("Sys.setenv\\(JAVA_HOME", content)))
76 | })
77 |
78 | test_that("java_env_set (both) sets session and project", {
79 | proj_dir <- withr::local_tempdir()
80 |
81 | local_mocked_bindings(
82 | rje_consent_check = function() TRUE,
83 | .package = "rJavaEnv"
84 | )
85 |
86 | local_mocked_bindings(
87 | installed.packages = function(...) matrix(character(0), nrow = 0, ncol = 2),
88 | .package = "utils"
89 | )
90 |
91 | local_mocked_bindings(
92 | loadedNamespaces = function() character(0),
93 | .package = "base"
94 | )
95 |
96 | local_mocked_bindings(
97 | Sys.info = function() c(sysname = "Darwin"),
98 | .package = "base"
99 | )
100 |
101 | java_home_mock <- "/mock/java"
102 | withr::with_envvar(c("PATH" = "/usr/bin"), {
103 | java_env_set(where = "both", java_home = java_home_mock, project_path = proj_dir, quiet = TRUE)
104 |
105 | # Check .Rprofile was created
106 | rprof <- file.path(proj_dir, ".Rprofile")
107 | expect_true(file.exists(rprof))
108 |
109 | # Check that session env was set
110 | expect_equal(Sys.getenv("JAVA_HOME"), java_home_mock)
111 | })
112 | })
113 |
114 | test_that("java_env_unset removes settings from .Rprofile", {
115 | proj_dir <- withr::local_tempdir()
116 | rprof <- file.path(proj_dir, ".Rprofile")
117 |
118 | # Create a .Rprofile with rJavaEnv markers
119 | writeLines(
120 | c(
121 | "# Some other config",
122 | "# rJavaEnv begin: Manage JAVA_HOME",
123 | "Sys.setenv(JAVA_HOME = '/path/to/java')",
124 | "# rJavaEnv end: Manage JAVA_HOME",
125 | "# More config"
126 | ),
127 | rprof
128 | )
129 |
130 | local_mocked_bindings(
131 | rje_consent_check = function() TRUE,
132 | .package = "rJavaEnv"
133 | )
134 |
135 | java_env_unset(project_path = proj_dir, quiet = TRUE)
136 |
137 | content <- readLines(rprof)
138 | # rJavaEnv lines should be removed
139 | expect_false(any(grepl("# rJavaEnv", content)))
140 | # Other content should remain
141 | expect_true(any(grepl("Some other config", content)))
142 | expect_true(any(grepl("More config", content)))
143 | })
144 |
145 | test_that("java_env_unset handles missing .Rprofile gracefully", {
146 | proj_dir <- withr::local_tempdir()
147 |
148 | local_mocked_bindings(
149 | rje_consent_check = function() TRUE,
150 | .package = "rJavaEnv"
151 | )
152 |
153 | # Should not error when .Rprofile doesn't exist
154 | expect_silent(
155 | java_env_unset(project_path = proj_dir, quiet = TRUE)
156 | )
157 | })
158 |
159 | test_that("java_env_set validates input", {
160 | local_mocked_bindings(
161 | rje_consent_check = function() TRUE,
162 | .package = "rJavaEnv"
163 | )
164 |
165 | # Should error on invalid 'where' argument
166 | expect_error(
167 | java_env_set(where = "invalid", java_home = "/mock/java"),
168 | "should be one of"
169 | )
170 |
171 | # Should error on non-string java_home
172 | expect_error(
173 | java_env_set(where = "session", java_home = 123),
174 | "Assertion on 'java_home' failed"
175 | )
176 | })
177 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_full-cycle-live.R:
--------------------------------------------------------------------------------
1 | test_that("full download, install, check, and clear cycle works for all versions", {
2 | # --- Test Configuration ---
3 | testthat::skip_on_cran()
4 | # Sys.setenv("RUN_JAVA_DOWNLOAD_TESTS" = "TRUE")
5 | # Sys.setenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET" = "FALSE")
6 | # Sys.setenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET" = "TRUE")
7 | # Sys.setenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD" = "FALSE")
8 | # Sys.setenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD" = "TRUE")
9 | skip_if_not(
10 | Sys.getenv("RUN_JAVA_DOWNLOAD_TESTS") == "TRUE",
11 | "Skipping real download test. Set RUN_JAVA_DOWNLOAD_TESTS='TRUE' to run."
12 | )
13 | if (Sys.getenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET") == "TRUE") {
14 | rj_quiet <- TRUE
15 | } else {
16 | rj_quiet <- FALSE
17 | }
18 | if (Sys.getenv("RUN_JAVA_DOWNLOAD_TESTS_QUIET_DOWNLOAD") == "TRUE") {
19 | rj_dl_quiet <- TRUE
20 | } else {
21 | rj_dl_quiet <- FALSE
22 | }
23 |
24 | # --- 1. Setup a Self-Cleaning Temporary Environment ---
25 | main_temp_dir <- tempfile(pattern = "rJavaEnv-full-test-")
26 | dir.create(main_temp_dir, recursive = TRUE)
27 |
28 | # The on.exit() call is the final safety net, ensuring everything is deleted
29 | # at the end, even if the test or the in-loop java_clear() fails.
30 | on.exit(unlink(main_temp_dir, recursive = TRUE, force = TRUE), add = TRUE)
31 |
32 | temp_cache_dir <- file.path(main_temp_dir, "cache")
33 | temp_project_dir <- file.path(main_temp_dir, "project")
34 | dir.create(temp_cache_dir, recursive = TRUE)
35 | dir.create(temp_project_dir, recursive = TRUE)
36 |
37 | withr::local_options(list(
38 | rJavaEnv.cache_path = temp_cache_dir,
39 | rJavaEnv.consent = TRUE
40 | ))
41 |
42 | # --- 2. Get the list of Java versions to test ---
43 | java_versions <- tryCatch(
44 | {
45 | java_valid_versions(force = TRUE)
46 | },
47 | error = function(e) {
48 | getOption("rJavaEnv.fallback_valid_versions_current_platform")
49 | }
50 | )
51 | cli::cli_inform(
52 | "Found {length(java_versions)} Java versions to test: {java_versions}"
53 | )
54 |
55 | # --- 3. Loop through each version and perform the full workflow ---
56 | for (java_version in java_versions) {
57 | context_info <- paste("Testing Java version:", java_version)
58 | cli::cli_h2(context_info)
59 |
60 | # --- Step A: Download ---
61 | cli::cli_inform("-> Step 1: Downloading Java {java_version}...")
62 | downloaded_file <- java_download(
63 | version = java_version,
64 | quiet = rj_dl_quiet,
65 | force = FALSE,
66 | )
67 | testthat::expect_true(file.exists(downloaded_file), info = context_info)
68 |
69 | # --- Step B: Install ---
70 | cli::cli_inform("-> Step 2: Installing Java {java_version}...")
71 | java_home_path <- java_install(
72 | java_distrib_path = downloaded_file,
73 | project_path = temp_project_dir,
74 | autoset_java_env = TRUE,
75 | quiet = rj_quiet,
76 | force = FALSE
77 | )
78 | testthat::expect_true(dir.exists(java_home_path), info = context_info)
79 |
80 | # --- Step C: Check and Verify ---
81 | cli::cli_inform("-> Step 3: Verifying with java_check_version_cmd()...")
82 | cmd_version_result <- java_check_version_cmd(
83 | java_home = java_home_path,
84 | quiet = rj_quiet
85 | )
86 | testthat::expect_equal(
87 | cmd_version_result,
88 | java_version,
89 | info = context_info
90 | )
91 | if (cmd_version_result == java_version) {
92 | cli::cli_inform(
93 | "Successfully verified Java {java_version} with command line."
94 | )
95 | } else {
96 | cli::cli_alert_danger(
97 | "Command line verification failed for Java {java_version}."
98 | )
99 | }
100 |
101 | cli::cli_inform("-> Step 4: Verifying with java_check_version_rjava()...")
102 | rjava_version_result <- java_check_version_rjava(
103 | java_home = java_home_path,
104 | quiet = rj_quiet
105 | )
106 | testthat::expect_equal(
107 | rjava_version_result,
108 | java_version,
109 | info = context_info
110 | )
111 | if (rjava_version_result == java_version) {
112 | cli::cli_inform("Successfully verified Java {java_version} with rJava.")
113 | } else {
114 | cli::cli_alert_danger(
115 | "rJava verification failed for Java {java_version}."
116 | )
117 | }
118 |
119 | # --- Step D: Clean up within the loop to test java_clear() ---
120 | cli::cli_inform("-> Step 5: Clearing caches with java_clear()...")
121 |
122 | # Clear the downloaded distribution files
123 | java_clear(
124 | type = "distrib",
125 | target_dir = temp_cache_dir,
126 | check = FALSE, # Must be FALSE for non-interactive use
127 | delete_all = TRUE # Must be TRUE for non-interactive use
128 | )
129 |
130 | # Clear the unpacked installation files
131 | java_clear(
132 | type = "installed",
133 | target_dir = temp_cache_dir,
134 | check = FALSE,
135 | delete_all = TRUE
136 | )
137 |
138 | # Verify that the cleanup was successful
139 | distrib_dir <- file.path(temp_cache_dir, "distrib")
140 | installed_dir <- file.path(temp_cache_dir, "installed")
141 |
142 | testthat::expect_equal(
143 | length(list.files(distrib_dir)),
144 | 0,
145 | info = context_info
146 | )
147 | testthat::expect_equal(
148 | length(list.files(installed_dir)),
149 | 0,
150 | info = context_info
151 | )
152 |
153 | cli::cli_alert_success(
154 | "Successfully processed and cleared Java version: {java_version}"
155 | )
156 | }
157 | })
158 |
--------------------------------------------------------------------------------
/tests/testthat/test-internal_utilities.R:
--------------------------------------------------------------------------------
1 | # Tests for platform_detect() and rje_consent()
2 |
3 | test_that("platform_detect returns correct structure", {
4 | res <- platform_detect(quiet = TRUE)
5 |
6 | expect_type(res, "list")
7 | expect_named(res, c("os", "arch"))
8 | expect_true(res$os %in% c("linux", "windows", "macos"))
9 | expect_true(res$arch %in% c("x64", "x86", "aarch64"))
10 | })
11 |
12 | test_that("platform_detect returns correct OS for current platform", {
13 | res <- platform_detect(quiet = TRUE)
14 | sys_info <- Sys.info()
15 |
16 | expected_os <- switch(
17 | tolower(sys_info["sysname"]),
18 | "windows" = "windows",
19 | "linux" = "linux",
20 | "darwin" = "macos"
21 | )
22 |
23 | expect_equal(res$os, expected_os)
24 | })
25 |
26 | test_that("platform_detect respects R_ARCH for Windows architecture", {
27 | skip_on_os("mac")
28 | skip_on_os("linux")
29 |
30 | # Test x64 architecture via R_ARCH
31 | withr::local_envvar(R_ARCH = "/x64")
32 | res <- platform_detect(quiet = TRUE)
33 | expect_equal(res$arch, "x64")
34 |
35 | # Test x86 architecture via R_ARCH
36 | withr::local_envvar(R_ARCH = "/i386")
37 | res <- platform_detect(quiet = TRUE)
38 | expect_equal(res$arch, "x86")
39 | })
40 |
41 | test_that("platform_detect prints messages when not quiet", {
42 | expect_message(
43 | platform_detect(quiet = FALSE),
44 | "Detected platform"
45 | )
46 | })
47 |
48 | test_that("rje_consent returns TRUE when option is already set", {
49 | withr::local_options(list(rJavaEnv.consent = TRUE))
50 |
51 | expect_message(
52 | result <- rje_consent(),
53 | "already been provided"
54 | )
55 | expect_true(result)
56 | })
57 |
58 | test_that("rje_consent returns TRUE when cache directory exists", {
59 | cache_dir <- withr::local_tempdir()
60 | withr::local_options(list(
61 | rJavaEnv.consent = FALSE,
62 | rJavaEnv.cache_path = cache_dir
63 | ))
64 |
65 | expect_message(
66 | result <- rje_consent(),
67 | "already been provided"
68 | )
69 | expect_true(result)
70 | })
71 |
72 | test_that("rje_consent handles user typing 'yes'", {
73 | cache_dir <- file.path(withr::local_tempdir(), "nonexistent")
74 | withr::local_options(list(
75 | rJavaEnv.consent = FALSE,
76 | rJavaEnv.cache_path = cache_dir
77 | ))
78 |
79 | # Mock readline to return "yes"
80 | local_mocked_bindings(readline = function(...) "yes", .package = "base")
81 |
82 | expect_message(
83 | result <- rje_consent(),
84 | "Consent has been granted"
85 | )
86 | expect_true(getOption("rJavaEnv.consent"))
87 | })
88 |
89 | test_that("rje_consent handles user typing 'no'", {
90 | cache_dir <- file.path(withr::local_tempdir(), "nonexistent")
91 | withr::local_options(list(
92 | rJavaEnv.consent = FALSE,
93 | rJavaEnv.cache_path = cache_dir
94 | ))
95 |
96 | # Mock readline to return "no"
97 | local_mocked_bindings(readline = function(...) "no", .package = "base")
98 |
99 | expect_error(
100 | rje_consent(),
101 | "Consent was not provided"
102 | )
103 | })
104 |
105 | test_that("rje_consent accepts 'provided = TRUE' argument", {
106 | cache_dir <- file.path(withr::local_tempdir(), "nonexistent")
107 | withr::local_options(list(
108 | rJavaEnv.consent = FALSE,
109 | rJavaEnv.cache_path = cache_dir
110 | ))
111 |
112 | expect_message(
113 | result <- rje_consent(provided = TRUE),
114 | "Consent has been granted"
115 | )
116 | expect_true(getOption("rJavaEnv.consent"))
117 | })
118 |
119 | test_that("rje_consent_check returns TRUE when consent option is set", {
120 | withr::local_options(list(rJavaEnv.consent = TRUE))
121 |
122 | expect_true(rje_consent_check())
123 | })
124 |
125 | test_that("rje_consent_check returns TRUE when cache directory exists", {
126 | cache_dir <- withr::local_tempdir()
127 | withr::local_options(list(
128 | rJavaEnv.consent = FALSE,
129 | rJavaEnv.cache_path = cache_dir
130 | ))
131 |
132 | expect_true(rje_consent_check())
133 | })
134 |
135 | test_that("rje_consent_check grants implicit consent in CI environments", {
136 | cache_dir <- file.path(withr::local_tempdir(), "nonexistent")
137 | withr::local_options(list(
138 | rJavaEnv.consent = FALSE,
139 | rJavaEnv.cache_path = cache_dir
140 | ))
141 | withr::local_envvar(CI = "true")
142 |
143 | expect_true(rje_consent_check())
144 | expect_true(getOption("rJavaEnv.consent"))
145 | })
146 |
147 | test_that("rje_consent_check grants implicit consent in GitHub Actions", {
148 | cache_dir <- file.path(withr::local_tempdir(), "nonexistent")
149 | withr::local_options(list(
150 | rJavaEnv.consent = FALSE,
151 | rJavaEnv.cache_path = cache_dir
152 | ))
153 | withr::local_envvar(GITHUB_ACTION = "test-action")
154 |
155 | expect_true(rje_consent_check())
156 | expect_true(getOption("rJavaEnv.consent"))
157 | })
158 |
159 | test_that("rje_envvar_exists correctly detects environment variables", {
160 | withr::local_envvar(TEST_VAR_EXISTS = "value")
161 |
162 | expect_true(rje_envvar_exists("TEST_VAR_EXISTS"))
163 | expect_false(rje_envvar_exists("TEST_VAR_DOES_NOT_EXIST_12345"))
164 | })
165 |
166 | test_that("java_urls_load returns correct structure", {
167 | urls <- java_urls_load()
168 |
169 | expect_type(urls, "list")
170 | expect_true("Corretto" %in% names(urls))
171 | })
172 |
173 | test_that("platform_detect handles common architectures", {
174 | # This test verifies the current platform returns one of the known architectures
175 | res <- platform_detect(quiet = TRUE)
176 |
177 | # The function should not error on the current machine
178 |
179 | expect_true(length(res$arch) == 1)
180 | expect_true(nchar(res$arch) > 0)
181 | })
182 |
--------------------------------------------------------------------------------
/vignettes/data-for-vignettes/data_table_dlstats.csv:
--------------------------------------------------------------------------------
1 | start;end;downloads;package
2 | 2014-01-01;2014-01-31;5308;data.table
3 | 2014-02-01;2014-02-28;6363;data.table
4 | 2014-03-01;2014-03-31;9784;data.table
5 | 2014-04-01;2014-04-30;12796;data.table
6 | 2014-05-01;2014-05-31;12312;data.table
7 | 2014-06-01;2014-06-30;13502;data.table
8 | 2014-07-01;2014-07-31;14397;data.table
9 | 2014-08-01;2014-08-31;14224;data.table
10 | 2014-09-01;2014-09-30;14193;data.table
11 | 2014-10-01;2014-10-31;21691;data.table
12 | 2014-11-01;2014-11-30;19681;data.table
13 | 2014-12-01;2014-12-31;17256;data.table
14 | 2015-01-01;2015-01-31;19970;data.table
15 | 2015-02-01;2015-02-28;21808;data.table
16 | 2015-03-01;2015-03-31;26032;data.table
17 | 2015-04-01;2015-04-30;31241;data.table
18 | 2015-05-01;2015-05-31;32581;data.table
19 | 2015-06-01;2015-06-30;35062;data.table
20 | 2015-07-01;2015-07-31;36540;data.table
21 | 2015-08-01;2015-08-31;50404;data.table
22 | 2015-09-01;2015-09-30;61375;data.table
23 | 2015-10-01;2015-10-31;64900;data.table
24 | 2015-11-01;2015-11-30;67938;data.table
25 | 2015-12-01;2015-12-31;61084;data.table
26 | 2016-01-01;2016-01-31;66463;data.table
27 | 2016-02-01;2016-02-29;65813;data.table
28 | 2016-03-01;2016-03-31;63233;data.table
29 | 2016-04-01;2016-04-30;59395;data.table
30 | 2016-05-01;2016-05-31;117233;data.table
31 | 2016-06-01;2016-06-30;110241;data.table
32 | 2016-07-01;2016-07-31;104528;data.table
33 | 2016-08-01;2016-08-31;108044;data.table
34 | 2016-09-01;2016-09-30;127614;data.table
35 | 2016-10-01;2016-10-31;146051;data.table
36 | 2016-11-01;2016-11-30;183043;data.table
37 | 2016-12-01;2016-12-31;181973;data.table
38 | 2017-01-01;2017-01-31;168188;data.table
39 | 2017-02-01;2017-02-28;265672;data.table
40 | 2017-03-01;2017-03-31;236241;data.table
41 | 2017-04-01;2017-04-30;199142;data.table
42 | 2017-05-01;2017-05-31;192961;data.table
43 | 2017-06-01;2017-06-30;185656;data.table
44 | 2017-07-01;2017-07-31;161976;data.table
45 | 2017-08-01;2017-08-31;156174;data.table
46 | 2017-09-01;2017-09-30;188326;data.table
47 | 2017-10-01;2017-10-31;325890;data.table
48 | 2017-11-01;2017-11-30;289248;data.table
49 | 2017-12-01;2017-12-31;212365;data.table
50 | 2018-01-01;2018-01-31;214533;data.table
51 | 2018-02-01;2018-02-28;219905;data.table
52 | 2018-03-01;2018-03-31;244143;data.table
53 | 2018-04-01;2018-04-30;297276;data.table
54 | 2018-05-01;2018-05-31;412734;data.table
55 | 2018-06-01;2018-06-30;304389;data.table
56 | 2018-07-01;2018-07-31;297191;data.table
57 | 2018-08-01;2018-08-31;273482;data.table
58 | 2018-09-01;2018-09-30;403235;data.table
59 | 2018-10-01;2018-10-31;491636;data.table
60 | 2018-11-01;2018-11-30;424741;data.table
61 | 2018-12-01;2018-12-31;330548;data.table
62 | 2019-01-01;2019-01-31;668709;data.table
63 | 2019-02-01;2019-02-28;666770;data.table
64 | 2019-03-01;2019-03-31;668349;data.table
65 | 2019-04-01;2019-04-30;729934;data.table
66 | 2019-05-01;2019-05-31;618185;data.table
67 | 2019-06-01;2019-06-30;444470;data.table
68 | 2019-07-01;2019-07-31;495586;data.table
69 | 2019-08-01;2019-08-31;454263;data.table
70 | 2019-09-01;2019-09-30;515846;data.table
71 | 2019-10-01;2019-10-31;715833;data.table
72 | 2019-11-01;2019-11-30;566063;data.table
73 | 2019-12-01;2019-12-31;500906;data.table
74 | 2020-01-01;2020-01-31;525533;data.table
75 | 2020-02-01;2020-02-29;502941;data.table
76 | 2020-03-01;2020-03-31;571181;data.table
77 | 2020-04-01;2020-04-30;596472;data.table
78 | 2020-05-01;2020-05-31;594441;data.table
79 | 2020-06-01;2020-06-30;562159;data.table
80 | 2020-07-01;2020-07-31;548913;data.table
81 | 2020-08-01;2020-08-31;584097;data.table
82 | 2020-09-01;2020-09-30;660371;data.table
83 | 2020-10-01;2020-10-31;745488;data.table
84 | 2020-11-01;2020-11-30;711626;data.table
85 | 2020-12-01;2020-12-31;667454;data.table
86 | 2021-01-01;2021-01-31;684310;data.table
87 | 2021-02-01;2021-02-28;696210;data.table
88 | 2021-03-01;2021-03-31;814729;data.table
89 | 2021-04-01;2021-04-30;743535;data.table
90 | 2021-05-01;2021-05-31;719963;data.table
91 | 2021-06-01;2021-06-30;730959;data.table
92 | 2021-07-01;2021-07-31;636526;data.table
93 | 2021-08-01;2021-08-31;661484;data.table
94 | 2021-09-01;2021-09-30;835160;data.table
95 | 2021-10-01;2021-10-31;943031;data.table
96 | 2021-11-01;2021-11-30;850174;data.table
97 | 2021-12-01;2021-12-31;763067;data.table
98 | 2022-01-01;2022-01-31;799994;data.table
99 | 2022-02-01;2022-02-28;800786;data.table
100 | 2022-03-01;2022-03-31;911517;data.table
101 | 2022-04-01;2022-04-30;909134;data.table
102 | 2022-05-01;2022-05-31;958481;data.table
103 | 2022-06-01;2022-06-30;891046;data.table
104 | 2022-07-01;2022-07-31;816538;data.table
105 | 2022-08-01;2022-08-31;848647;data.table
106 | 2022-09-01;2022-09-30;855167;data.table
107 | 2022-10-01;2022-10-31;962825;data.table
108 | 2022-11-01;2022-11-30;1117776;data.table
109 | 2022-12-01;2022-12-31;821153;data.table
110 | 2023-01-01;2023-01-31;748596;data.table
111 | 2023-02-01;2023-02-28;789184;data.table
112 | 2023-03-01;2023-03-31;913025;data.table
113 | 2023-04-01;2023-04-30;775531;data.table
114 | 2023-05-01;2023-05-31;779533;data.table
115 | 2023-06-01;2023-06-30;676283;data.table
116 | 2023-07-01;2023-07-31;570552;data.table
117 | 2023-08-01;2023-08-31;586248;data.table
118 | 2023-09-01;2023-09-30;694988;data.table
119 | 2023-10-01;2023-10-31;696944;data.table
120 | 2023-11-01;2023-11-30;965821;data.table
121 | 2023-12-01;2023-12-31;638954;data.table
122 | 2024-01-01;2024-01-31;739831;data.table
123 | 2024-02-01;2024-02-29;821539;data.table
124 | 2024-03-01;2024-03-31;845520;data.table
125 | 2024-04-01;2024-04-30;886330;data.table
126 | 2024-05-01;2024-05-31;846726;data.table
127 | 2024-06-01;2024-06-30;677560;data.table
128 | 2024-07-01;2024-07-31;698441;data.table
129 | 2024-08-01;2024-08-31;749291;data.table
130 | 2024-09-01;2024-09-26;729796;data.table
131 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, caste, color, religion, or sexual
10 | identity and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or advances of
31 | any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email address,
35 | without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at kotov.egor@gmail.com.
63 | All complaints will be reviewed and investigated promptly and fairly.
64 |
65 | All community leaders are obligated to respect the privacy and security of the
66 | reporter of any incident.
67 |
68 | ## Enforcement Guidelines
69 |
70 | Community leaders will follow these Community Impact Guidelines in determining
71 | the consequences for any action they deem in violation of this Code of Conduct:
72 |
73 | ### 1. Correction
74 |
75 | **Community Impact**: Use of inappropriate language or other behavior deemed
76 | unprofessional or unwelcome in the community.
77 |
78 | **Consequence**: A private, written warning from community leaders, providing
79 | clarity around the nature of the violation and an explanation of why the
80 | behavior was inappropriate. A public apology may be requested.
81 |
82 | ### 2. Warning
83 |
84 | **Community Impact**: A violation through a single incident or series of
85 | actions.
86 |
87 | **Consequence**: A warning with consequences for continued behavior. No
88 | interaction with the people involved, including unsolicited interaction with
89 | those enforcing the Code of Conduct, for a specified period of time. This
90 | includes avoiding interactions in community spaces as well as external channels
91 | like social media. Violating these terms may lead to a temporary or permanent
92 | ban.
93 |
94 | ### 3. Temporary Ban
95 |
96 | **Community Impact**: A serious violation of community standards, including
97 | sustained inappropriate behavior.
98 |
99 | **Consequence**: A temporary ban from any sort of interaction or public
100 | communication with the community for a specified period of time. No public or
101 | private interaction with the people involved, including unsolicited interaction
102 | with those enforcing the Code of Conduct, is allowed during this period.
103 | Violating these terms may lead to a permanent ban.
104 |
105 | ### 4. Permanent Ban
106 |
107 | **Community Impact**: Demonstrating a pattern of violation of community
108 | standards, including sustained inappropriate behavior, harassment of an
109 | individual, or aggression toward or disparagement of classes of individuals.
110 |
111 | **Consequence**: A permanent ban from any sort of public interaction within the
112 | community.
113 |
114 | ## Attribution
115 |
116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117 | version 2.1, available at
118 | .
119 |
120 | Community Impact Guidelines were inspired by
121 | [Mozilla's code of conduct enforcement ladder][https://github.com/mozilla/inclusion].
122 |
123 | For answers to common questions about this code of conduct, see the FAQ at
124 | . Translations are available at .
125 |
126 | [homepage]: https://www.contributor-covenant.org
127 |
--------------------------------------------------------------------------------
/tests/testthat/test-java_manage.R:
--------------------------------------------------------------------------------
1 | # Tests for java_list() and java_clear()
2 |
3 | test_that("java_list dispatches correctly", {
4 | # Mock the specific list functions
5 | local_mocked_bindings(
6 | java_list_distrib_cache = function(...) "listed_distrib",
7 | java_list_installed_cache = function(...) "listed_installed",
8 | java_list_in_project = function(...) "listed_project",
9 | .package = "rJavaEnv"
10 | )
11 |
12 | expect_equal(java_list("distrib"), "listed_distrib")
13 | expect_equal(java_list("installed"), "listed_installed")
14 | expect_equal(java_list("project"), "listed_project")
15 | })
16 |
17 | test_that("java_clear (project) handles user input correctly", {
18 | # Setup fake project structure with proper depth
19 | proj_dir <- withr::local_tempdir()
20 | rjava_dir <- file.path(proj_dir, "rjavaenv", "linux", "x64", "17")
21 | dir.create(rjava_dir, recursive = TRUE)
22 | file.create(file.path(rjava_dir, "dummy_file"))
23 |
24 | # Mock consent
25 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
26 |
27 | # Case 1: User says "no" (check=FALSE triggers yes/no prompt)
28 | local_mocked_bindings(readline = function(...) "no", .package = "base")
29 |
30 | expect_message(
31 | java_clear("project", target_dir = proj_dir, check = FALSE),
32 | "No Java symlinks were cleared"
33 | )
34 | # The directory should still exist
35 | expect_true(dir.exists(rjava_dir))
36 |
37 | # Case 2: User says "yes"
38 | local_mocked_bindings(readline = function(...) "yes", .package = "base")
39 | expect_message(
40 | java_clear("project", target_dir = proj_dir, check = FALSE),
41 | "cleared"
42 | )
43 | # Contents should be cleared
44 | rjava_base <- file.path(proj_dir, "rjavaenv")
45 | expect_length(list.files(rjava_base, recursive = TRUE), 0)
46 | })
47 |
48 | test_that("java_clear (distrib) deletes specific files via menu", {
49 | cache_dir <- withr::local_tempdir()
50 | dist_dir <- file.path(cache_dir, "distrib")
51 | dir.create(dist_dir, recursive = TRUE)
52 |
53 | f1 <- file.path(dist_dir, "java1.tar.gz")
54 | f2 <- file.path(dist_dir, "java2.tar.gz")
55 | file.create(f1)
56 | file.create(f2)
57 |
58 | # Mock consent
59 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
60 |
61 | # User selects item "1" (check=TRUE triggers numbered menu)
62 | local_mocked_bindings(readline = function(...) "1", .package = "base")
63 |
64 | # We must mock java_list_distrib_cache to return vector so the index works
65 | local_mocked_bindings(
66 | java_list_distrib_cache = function(...) c(f1, f2),
67 | .package = "rJavaEnv"
68 | )
69 |
70 | java_clear("distrib", target_dir = cache_dir, check = TRUE)
71 |
72 | expect_false(file.exists(f1))
73 | expect_true(file.exists(f2))
74 | })
75 |
76 | test_that("java_clear deletes all when requested", {
77 | cache_dir <- withr::local_tempdir()
78 | inst_dir <- file.path(cache_dir, "installed")
79 | dir.create(inst_dir, recursive = TRUE)
80 | file.create(file.path(inst_dir, "folder1"))
81 |
82 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
83 |
84 | java_clear("installed", target_dir = cache_dir, delete_all = TRUE)
85 | expect_length(list.files(inst_dir), 0)
86 | })
87 |
88 | test_that("java_clear (installed) handles numbered selection", {
89 | cache_dir <- withr::local_tempdir()
90 | inst_dir <- file.path(cache_dir, "installed", "linux", "x64", "17")
91 | dir.create(inst_dir, recursive = TRUE)
92 | inst_dir2 <- file.path(cache_dir, "installed", "linux", "x64", "21")
93 | dir.create(inst_dir2, recursive = TRUE)
94 |
95 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
96 |
97 | # User selects item "1"
98 | local_mocked_bindings(readline = function(...) "1", .package = "base")
99 |
100 | # Mock java_list_installed_cache to return expected paths
101 | local_mocked_bindings(
102 | java_list_installed_cache = function(...) c(inst_dir, inst_dir2),
103 | .package = "rJavaEnv"
104 | )
105 |
106 | java_clear("installed", target_dir = cache_dir, check = TRUE)
107 |
108 | expect_false(dir.exists(inst_dir))
109 | expect_true(dir.exists(inst_dir2))
110 | })
111 |
112 | test_that("java_clear (project) handles 'all' option", {
113 | proj_dir <- withr::local_tempdir()
114 | rjava_dir1 <- file.path(proj_dir, "rjavaenv", "linux", "x64", "17")
115 | rjava_dir2 <- file.path(proj_dir, "rjavaenv", "linux", "x64", "21")
116 | dir.create(rjava_dir1, recursive = TRUE)
117 | dir.create(rjava_dir2, recursive = TRUE)
118 |
119 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
120 |
121 | # User types "all"
122 | local_mocked_bindings(readline = function(...) "all", .package = "base")
123 |
124 | java_clear("project", target_dir = proj_dir, check = TRUE)
125 |
126 | # All should be cleared
127 | rjava_base <- file.path(proj_dir, "rjavaenv")
128 | expect_length(list.files(rjava_base, recursive = TRUE), 0)
129 | })
130 |
131 | test_that("java_clear cancels on invalid input",
132 | {
133 | cache_dir <- withr::local_tempdir()
134 | dist_dir <- file.path(cache_dir, "distrib")
135 | dir.create(dist_dir, recursive = TRUE)
136 |
137 | f1 <- file.path(dist_dir, "java1.tar.gz")
138 | file.create(f1)
139 |
140 | local_mocked_bindings(rje_consent_check = function() TRUE, .package = "rJavaEnv")
141 |
142 | # User enters "0" to cancel
143 | local_mocked_bindings(readline = function(...) "0", .package = "base")
144 |
145 | local_mocked_bindings(
146 | java_list_distrib_cache = function(...) c(f1),
147 | .package = "rJavaEnv"
148 | )
149 |
150 | expect_message(
151 | java_clear("distrib", target_dir = cache_dir, check = TRUE),
152 | "No distributions were cleared"
153 | )
154 |
155 | # File should still exist
156 | expect_true(file.exists(f1))
157 | })
158 |
--------------------------------------------------------------------------------
/R/internal_utilities.R:
--------------------------------------------------------------------------------
1 | #' Detect platform and architecture
2 | #'
3 | #' @inheritParams global_quiet_param
4 | #' @keywords internal
5 | #' @return A list of length 2 with the detected platform and architecture.
6 | #'
7 | platform_detect <- function(quiet = TRUE) {
8 | sys_info <- tolower(Sys.info())
9 |
10 | os <- switch(
11 | sys_info["sysname"],
12 | "windows" = "windows",
13 | "linux" = "linux",
14 | "darwin" = "macos",
15 | stop(cli::cli_abort("Unsupported platform"))
16 | )
17 |
18 | # NEW: Check R_ARCH first, then fall back to Sys.info()
19 | r_arch_env <- Sys.getenv("R_ARCH")
20 |
21 | if (r_arch_env == "/i386") {
22 | arch <- "x86"
23 | } else if (r_arch_env == "/x64") {
24 | arch <- "x64"
25 | } else {
26 | # Fallback for non-Windows or when not in a build context
27 | arch <- switch(
28 | sys_info["machine"],
29 | "x86-64" = "x64",
30 | "x86_64" = "x64",
31 | "i386" = "x86",
32 | "i486" = "x86",
33 | "i586" = "x86",
34 | "i686" = "x86",
35 | "aarch64" = "aarch64",
36 | "arm64" = "aarch64",
37 | stop(cli::cli_abort("Unsupported architecture"))
38 | )
39 | }
40 |
41 | if (isFALSE(quiet)) {
42 | cli::cli_inform("Detected platform: {os}")
43 | cli::cli_inform("Detected architecture: {arch}")
44 | }
45 |
46 | return(list(os = os, arch = arch))
47 | }
48 |
49 | #' Load Java URLs from JSON file
50 | #'
51 | #' @keywords internal
52 | #'
53 | #' @return A list with the Java URLs structured as in the JSON file by distribution, platform, and architecture.
54 | #'
55 | java_urls_load <- function() {
56 | json_file <- system.file("extdata", "java_urls.json", package = "rJavaEnv")
57 | if (json_file == "") {
58 | cli::cli_abort("Configuration file not found")
59 | }
60 | jsonlite::fromJSON(json_file, simplifyVector = FALSE)
61 | }
62 |
63 | #' Test all Java URLs
64 | #'
65 | #' @keywords internal
66 | #'
67 | #' @return A list with the results of testing all Java URLs.
68 | #'
69 | urls_test_all <- function() {
70 | java_urls <- java_urls_load()
71 | results <- list()
72 |
73 | for (distribution in names(java_urls)) {
74 | for (platform in names(java_urls[[distribution]])) {
75 | for (arch in names(java_urls[[distribution]][[platform]])) {
76 | url_template <- java_urls[[distribution]][[platform]][[arch]]
77 |
78 | # Replace {version} with a placeholder version to test URL
79 | url <- gsub("\\{version\\}", "11", url_template)
80 |
81 | try(
82 | {
83 | response <- curl::curl_fetch_memory(
84 | url,
85 | handle = curl::new_handle(nobody = TRUE)
86 | )
87 | status <- response$status_code
88 | },
89 | silent = TRUE
90 | )
91 |
92 | if (!exists("status")) {
93 | status <- NA
94 | }
95 |
96 | results[[paste(distribution, platform, arch, sep = "-")]] <- list(
97 | url = url,
98 | status = status
99 | )
100 |
101 | # Clear status variable for next iteration
102 | rm(status)
103 | }
104 | }
105 | }
106 |
107 | return(results)
108 | }
109 |
110 |
111 | # Unexported function to initialize Java using rJava and check Java version
112 | # This is intended to be called from the exported function java_check_version_rjava
113 | # Updated java_version_check_rscript function with verbosity control
114 | #' Check Java version using rJava
115 | #'
116 | #' @keywords internal
117 | #'
118 | #' @param java_home
119 | #'
120 | #' @return A message with the Java version or an error message.
121 | #'
122 | java_version_check_rscript <- function(java_home) {
123 | result <- tryCatch(
124 | {
125 | Sys.setenv(JAVA_HOME = java_home)
126 |
127 | old_path <- Sys.getenv("PATH")
128 | new_path <- file.path(java_home, "bin")
129 | Sys.setenv(PATH = paste(new_path, old_path, sep = .Platform$path.sep))
130 |
131 | # On Linux, find and dynamically load libjvm.so
132 | if (Sys.info()["sysname"] == "Linux") {
133 | all_files <- list.files(
134 | path = java_home,
135 | pattern = "libjvm.so$",
136 | recursive = TRUE,
137 | full.names = TRUE
138 | )
139 |
140 | libjvm_path <- NULL
141 | if (length(all_files) > 0) {
142 | # Prefer the 'server' version if available
143 | server_files <- all_files[grepl("/server/libjvm.so$", all_files)]
144 | if (length(server_files) > 0) {
145 | libjvm_path <- server_files[1]
146 | } else {
147 | libjvm_path <- all_files[1]
148 | }
149 | }
150 |
151 | if (!is.null(libjvm_path) && file.exists(libjvm_path)) {
152 | tryCatch(
153 | dyn.load(libjvm_path),
154 | error = function(e) {
155 | # Use base message to avoid dependency issues in the isolated script
156 | message(sprintf(
157 | "Found libjvm.so at '%s' but failed to load it: %s",
158 | libjvm_path,
159 | e$message
160 | ))
161 | }
162 | )
163 | } else {
164 | message(sprintf(
165 | "Could not find libjvm.so within the provided JAVA_HOME: %s",
166 | java_home
167 | ))
168 | }
169 | }
170 |
171 | suppressWarnings(rJava::.jinit())
172 | suppressWarnings(
173 | java_version <- rJava::.jcall(
174 | "java.lang.System",
175 | "S",
176 | "getProperty",
177 | "java.version"
178 | )
179 | )
180 |
181 | message <- cli::format_message(
182 | "rJava and other rJava/Java-based packages will use Java version: {.val {java_version}}"
183 | )
184 |
185 | message
186 | },
187 | error = function(e) {
188 | cli::format_message("Error checking Java version: {e$message}")
189 | }
190 | )
191 |
192 | return(result)
193 | }
194 |
--------------------------------------------------------------------------------