├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
└── dictionaries
│ └── project.xml
├── .gitignore
├── src
├── main
│ └── kotlin
│ │ └── me
│ │ └── filippov
│ │ └── gradle
│ │ └── jvm
│ │ └── wrapper
│ │ ├── PluginExtension.kt
│ │ └── Plugin.kt
└── test
│ └── kotlin
│ └── me
│ └── filippov
│ └── gradle
│ └── jvm
│ └── wrapper
│ ├── Util.kt
│ └── PluginTest.kt
├── README.md
├── .github
└── workflows
│ └── ci.yml
├── gradlew.bat
├── LICENSE
└── gradlew
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mfilippov/gradle-jvm-wrapper/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/.idea/dictionaries/project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | alnum
5 | appname
6 | cdpath
7 | filippov
8 | javacmd
9 | readarray
10 | shellness
11 | ulimit
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | .gradle/
26 | build/
27 | .idea/
--------------------------------------------------------------------------------
/src/main/kotlin/me/filippov/gradle/jvm/wrapper/PluginExtension.kt:
--------------------------------------------------------------------------------
1 | package me.filippov.gradle.jvm.wrapper
2 |
3 | open class PluginExtension {
4 | var winJvmInstallDir: String = "%LOCALAPPDATA%\\gradle-jvm"
5 | var unixJvmInstallDir: String = "${"$"}{HOME}/.local/share/gradle-jvm"
6 | // https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-21
7 | var windowsAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.6-windows-aarch64.zip"
8 | // https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html
9 | var windowsX64JvmUrl = "https://download.oracle.com/java/21/archive/jdk-21.0.5_windows-x64_bin.zip"
10 | var linuxAarch64JvmUrl = "https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-aarch64_bin.tar.gz"
11 | var linuxX64JvmUrl = "https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-x64_bin.tar.gz"
12 | var macAarch64JvmUrl = "https://download.oracle.com/java/21/archive/jdk-21.0.5_macos-aarch64_bin.tar.gz"
13 | var macX64JvmUrl = "https://download.oracle.com/java/21/archive/jdk-21.0.5_macos-x64_bin.tar.gz"
14 | }
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gradle JVM Wrapper plugin
2 | To use it, you need to add the plugin to your Gradle file.
3 |
4 | Groovy edition:
5 | ```groovy
6 | plugins {
7 | id "me.filippov.gradle.jvm.wrapper" version "0.15.0"
8 | }
9 | ```
10 | Kotlin edition:
11 | ```kotlin
12 | plugins {
13 | id("me.filippov.gradle.jvm.wrapper") version "0.15.0"
14 | }
15 | ```
16 | After that you should call `wrapper` Gradle task to setup a wrapper and update the command-line scripts.
17 | By default the plugin uses Microsoft JDK 21. You can configure it for your JVM distribution:
18 |
19 | Groovy edition:
20 | ```groovy
21 | plugins {
22 | id "me.filippov.gradle.jvm.wrapper" version "0.15.0"
23 | }
24 |
25 | jvmWrapper {
26 | unixJvmInstallDir = "${"$"}{HOME}/my-custom-path/gradle-jvm"
27 | winJvmInstallDir = "%LOCALAPPDATA%\\gradle-jvm"
28 | linuxAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-aarch64.tar.gz"
29 | linuxX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-x64.tar.gz"
30 | macAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-aarch64.tar.gz"
31 | macX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-x64.tar.gz"
32 | windowsAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-windows-aarch64.zip"
33 | windowsX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-windows-x64.zip"
34 | }
35 | ```
36 | Kotlin edition:
37 | ```kotlin
38 | plugins {
39 | id("me.filippov.gradle.jvm.wrapper") version "0.15.0"
40 | }
41 |
42 | jvmWrapper {
43 | unixJvmInstallDir = "${"$"}{HOME}/my-custom-path/gradle-jvm"
44 | winJvmInstallDir = "%LOCALAPPDATA%\\gradle-jvm"
45 | linuxAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-aarch64.tar.gz"
46 | linuxX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-x64.tar.gz"
47 | macAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-aarch64.tar.gz"
48 | macX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-x64.tar.gz"
49 | windowsAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-windows-aarch64.zip"
50 | windowsX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-windows-x64.zip"
51 | }
52 | ```
53 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | windows:
13 | runs-on: windows-latest
14 | steps:
15 | - uses: actions/checkout@v4
16 | - name: Tests
17 | run: gradlew.bat build
18 | shell: cmd
19 | - uses: actions/upload-artifact@v4
20 | if: always()
21 | with:
22 | name: test-report-windows
23 | path: build/reports/tests/test
24 | windows-arm:
25 | runs-on: windows-11-arm
26 | steps:
27 | - uses: actions/checkout@v4
28 | - name: Tests
29 | run: gradlew.bat build
30 | shell: cmd
31 | - uses: actions/upload-artifact@v4
32 | if: always()
33 | with:
34 | name: test-report-windows-arm
35 | path: build/reports/tests/test
36 | linux:
37 | runs-on: ubuntu-latest
38 | steps:
39 | - uses: actions/checkout@v4
40 | - name: Tests
41 | run: ./gradlew build
42 | shell: bash
43 | - uses: actions/upload-artifact@v4
44 | if: always()
45 | with:
46 | name: test-report-linux
47 | path: build/reports/tests/test
48 | linux-arm:
49 | runs-on: ubuntu-24.04-arm
50 | steps:
51 | - uses: actions/checkout@v4
52 | - name: Tests
53 | run: ./gradlew build
54 | shell: bash
55 | - uses: actions/upload-artifact@v4
56 | if: always()
57 | with:
58 | name: test-report-linux-arm
59 | path: build/reports/tests/test
60 | macos:
61 | runs-on: macos-13
62 | steps:
63 | - uses: actions/checkout@v4
64 | - name: Tests
65 | run: ./gradlew build
66 | shell: bash
67 | - uses: actions/upload-artifact@v4
68 | if: always()
69 | with:
70 | name: test-report-macos
71 | path: build/reports/tests/test
72 | macos-arm:
73 | runs-on: macos-latest
74 | steps:
75 | - uses: actions/checkout@v4
76 | - name: Tests
77 | run: ./gradlew build
78 | shell: bash
79 | - uses: actions/upload-artifact@v4
80 | if: always()
81 | with:
82 | name: test-report-macos-arm
83 | path: build/reports/tests/test
84 |
--------------------------------------------------------------------------------
/src/test/kotlin/me/filippov/gradle/jvm/wrapper/Util.kt:
--------------------------------------------------------------------------------
1 | package me.filippov.gradle.jvm.wrapper
2 |
3 | import org.gradle.testkit.runner.GradleRunner
4 | import org.gradle.testkit.runner.TaskOutcome
5 | import org.junit.jupiter.api.Assertions.assertEquals
6 | import java.io.File
7 | import java.util.*
8 | import java.util.concurrent.TimeUnit
9 |
10 | val isWindows = System.getProperty("os.name").lowercase(Locale.ENGLISH).startsWith("windows")
11 | val isMac = System.getProperty("os.name").lowercase(Locale.ENGLISH).startsWith("mac")
12 | val isLinux = System.getProperty("os.name").lowercase(Locale.ENGLISH).startsWith("linux")
13 |
14 | val wrapperScriptFileName = when {
15 | isWindows -> "gradlew.bat"
16 | isLinux -> "gradlew"
17 | isMac -> "gradlew"
18 | else -> error("Unknown OS")
19 | }
20 |
21 | data class TaskResult(val exitCode: Int, val stdout: String, val stderr: String)
22 |
23 | fun gradlew(projectRoot: File, task: String): TaskResult {
24 | val workingDirectory = File(System.getProperty("user.dir"))
25 | val processBuilder = ProcessBuilder(
26 | projectRoot.resolve(wrapperScriptFileName).absolutePath, "--include-build",
27 | workingDirectory.absolutePath, "-Pkotlin.compiler.execution.strategy=in-process", "--no-daemon", ":$task")
28 | .directory(projectRoot)
29 | val process = processBuilder.start()
30 | val stdout = process.inputStream.bufferedReader().readText()
31 | val stderr = process.errorStream.bufferedReader().readText()
32 | if (!process.waitFor(5, TimeUnit.MINUTES)) error("Process timeout error")
33 | return TaskResult(process.exitValue(), stdout, stderr)
34 | }
35 |
36 | fun withBuildScript(projectRoot: File, withContent: () -> String) {
37 | projectRoot.resolve("build.gradle.kts").writeText(withContent().trimIndent())
38 | }
39 |
40 | fun prepareWrapper(projectRoot: File) {
41 | val wrapperResult = GradleRunner.create()
42 | .withProjectDir(projectRoot)
43 | .withArguments(":wrapper")
44 | .withPluginClasspath().build()
45 | val result = wrapperResult.task(":wrapper")?.outcome
46 | if (result != TaskOutcome.SUCCESS) {
47 | println("test")
48 | }
49 | }
50 |
51 | fun T.shouldBe(expectedValue: T, message: String? = null) {
52 | assertEquals(expectedValue, this, message)
53 | }
54 |
55 | fun String.shouldContain(expectedValue: String, message: String? = null) {
56 | assert(this.contains(expectedValue)){ message ?: "String '$this' not contains '$expectedValue'" }
57 | }
58 |
59 | fun String.shouldNotContain(expectedValue: String, message: String? = null) {
60 | assert(!this.contains(expectedValue)){ message ?: "String '$this' not contains '$expectedValue'" }
61 | }
62 |
63 | fun String.shouldBeEmpty(message: String? = null) {
64 | assert(this.isEmpty()) { message ?: "String '$this' is not empty" }
65 | }
66 |
67 | fun Boolean.shouldBeTrue(message: String? = null) {
68 | assert(this) { message ?: "Value should be true" }
69 | }
70 |
--------------------------------------------------------------------------------
/src/test/kotlin/me/filippov/gradle/jvm/wrapper/PluginTest.kt:
--------------------------------------------------------------------------------
1 | package me.filippov.gradle.jvm.wrapper
2 |
3 | import org.junit.jupiter.api.Test
4 | import org.junit.jupiter.api.io.TempDir
5 | import java.nio.file.Path
6 |
7 | class PluginTest {
8 | @Test
9 | fun smoke(@TempDir tempDir: Path) {
10 | doSmoke(tempDir, "https://download.oracle.com/java/18/archive/jdk-18.0.1.1_windows-x64_bin.zip")
11 | }
12 |
13 | @Test
14 | fun smokeWindowsTarGz(@TempDir tempDir: Path) {
15 | doSmoke(tempDir, "https://cache-redirector.jetbrains.com/intellij-jbr/jbr-17.0.3-windows-x64-b469.37.tar.gz")
16 | }
17 |
18 | private fun doSmoke(tempDir: Path, windowsX64Url: String) {
19 | val projectRoot = tempDir.resolve("folder with space").toFile()
20 | projectRoot.mkdirs()
21 | withBuildScript(projectRoot) { """
22 | plugins {
23 | id("me.filippov.gradle.jvm.wrapper")
24 | }
25 | jvmWrapper {
26 | winJvmInstallDir = "build\\test-temp-dir\\gradle-jvm"
27 | unixJvmInstallDir = "build/test-temp-dir/gradle-jvm"
28 | }
29 | tasks.register("hello") {
30 | doLast {
31 | println("Hello world!")
32 | }
33 | }
34 | """}
35 |
36 | prepareWrapper(projectRoot)
37 | val resultWhenJavaNotExists = gradlew(projectRoot, "hello")
38 |
39 | resultWhenJavaNotExists.stdout.shouldContain("Down",
40 | "'Down' not found in output:\nSTDOUT:\n${resultWhenJavaNotExists.stdout}\nSTDERR:\n${resultWhenJavaNotExists.stderr}\n"
41 | )
42 |
43 | resultWhenJavaNotExists.stdout.shouldContain("Hello world!",
44 | "'Hello world!' not found in output:\nSTDOUT:\n${resultWhenJavaNotExists.stdout}\nSTDERR:\n${resultWhenJavaNotExists.stderr}\n"
45 | )
46 | resultWhenJavaNotExists.stderr.shouldBeEmpty("Non empty stderr:\n" + resultWhenJavaNotExists.stderr)
47 | resultWhenJavaNotExists.exitCode.shouldBe(0)
48 |
49 | projectRoot.resolve("build").resolve("test-temp-dir").resolve("gradle-jvm").exists().shouldBeTrue()
50 |
51 | val resultWhenJavaExists = gradlew(projectRoot, "hello")
52 |
53 | resultWhenJavaExists.stdout.shouldContain("Hello world!",
54 | "'Hello world!' not found in output:\nSTDOUT:\n${resultWhenJavaExists.stdout}\nSTDERR:\n${resultWhenJavaExists.stderr}\n")
55 | resultWhenJavaExists.stdout.shouldNotContain("Down",
56 | "'Down' not found in output:\nSTDOUT:\n${resultWhenJavaExists.stdout}\nSTDERR:\n${resultWhenJavaExists.stderr}\n")
57 | resultWhenJavaExists.stderr.shouldBeEmpty("Non empty stderr:\n" + resultWhenJavaExists.stderr)
58 | resultWhenJavaExists.exitCode.shouldBe(0)
59 |
60 | val absJvmDir = projectRoot.resolve("build").resolve("test-temp-dir").resolve("gradle-jvm")
61 |
62 | withBuildScript(projectRoot) { """
63 | plugins {
64 | id("me.filippov.gradle.jvm.wrapper")
65 | }
66 |
67 | jvmWrapper {
68 | winJvmInstallDir = "${absJvmDir.canonicalPath.replace("\\", "\\\\")}"
69 | unixJvmInstallDir = "${absJvmDir.canonicalPath.replace("\\", "\\\\")}"
70 | linuxAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-aarch64.tar.gz"
71 | linuxX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-linux-x64.tar.gz"
72 | macAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-aarch64.tar.gz"
73 | macX64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-macos-x64.tar.gz"
74 | windowsAarch64JvmUrl = "https://aka.ms/download-jdk/microsoft-jdk-21.0.7-windows-aarch64.zip"
75 | windowsX64JvmUrl ="$windowsX64Url"
76 | }
77 |
78 | tasks.register("newHello") {
79 | doLast {
80 | println("Hello new world!")
81 | }
82 | }
83 | """}
84 | prepareWrapper(projectRoot)
85 |
86 | val resultAfterJavaUpdate = gradlew(projectRoot, "newHello")
87 | resultAfterJavaUpdate.stdout.shouldContain("Hello new world!",
88 | "'Hello new world!' not found in output:\nSTDOUT:\n${resultAfterJavaUpdate.stdout}\nSTDERR:\n${resultAfterJavaUpdate.stderr}\n")
89 | resultAfterJavaUpdate.stdout.shouldContain("Down",
90 | "'Down' not found in output:\nSTDOUT:\n${resultAfterJavaUpdate.stdout}\nSTDERR:\n${resultAfterJavaUpdate.stderr}\n")
91 | resultAfterJavaUpdate.stderr.shouldBeEmpty("Non empty stderr:\n" + resultAfterJavaUpdate.stderr)
92 | resultAfterJavaUpdate.exitCode.shouldBe(0)
93 |
94 | val jdkDirs = projectRoot.resolve("build").resolve("test-temp-dir").resolve("gradle-jvm").list()!!
95 | jdkDirs.size.shouldBe(2)
96 | repeat((0..30).count()) {
97 | if (!projectRoot.exists()) {
98 | return@repeat
99 | }
100 | Thread.sleep(1000)
101 | projectRoot.deleteRecursively()
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem GRADLE JVM WRAPPER START MARKER
42 |
43 | setlocal
44 | set BUILD_DIR=build\gradle-jvm
45 |
46 | for /f "tokens=3 delims= " %%A in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "PROCESSOR_ARCHITECTURE"') do set WIN_ARCH=%%A
47 | if "%WIN_ARCH%" equ "AMD64" (
48 | set JVM_TARGET_DIR=%BUILD_DIR%\jdk-21.0.5_windows-x64_bin-020647\
49 | set JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_windows-x64_bin.zip
50 | ) else if "%WIN_ARCH%" equ "ARM64" (
51 | set JVM_TARGET_DIR=%BUILD_DIR%\microsoft-jdk-21.0.6-windows-aarch64-351b9f\
52 | set JVM_URL=https://aka.ms/download-jdk/microsoft-jdk-21.0.6-windows-aarch64.zip
53 | ) else (
54 | echo Unknown architecture %WIN_ARCH%
55 | goto fail
56 | )
57 |
58 | set IS_TAR_GZ=0
59 | set JVM_TEMP_FILE=gradle-jvm.zip
60 |
61 | if /I "%JVM_URL:~-7%"==".tar.gz" (
62 | set IS_TAR_GZ=1
63 | set JVM_TEMP_FILE=gradle-jvm.tar.gz
64 | )
65 |
66 | set POWERSHELL=%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
67 |
68 | if not exist "%JVM_TARGET_DIR%" MD "%JVM_TARGET_DIR%"
69 |
70 | if not exist "%JVM_TARGET_DIR%.flag" goto downloadAndExtractJvm
71 |
72 | set /p CURRENT_FLAG=<"%JVM_TARGET_DIR%.flag"
73 | if "%CURRENT_FLAG%" == "%JVM_URL%" goto continueWithJvm
74 |
75 | :downloadAndExtractJvm
76 |
77 | PUSHD "%BUILD_DIR%"
78 | if errorlevel 1 goto fail
79 |
80 | echo Downloading %JVM_URL% to %BUILD_DIR%\%JVM_TEMP_FILE%
81 | if exist "%JVM_TEMP_FILE%" DEL /F "%JVM_TEMP_FILE%"
82 | "%POWERSHELL%" -nologo -noprofile -Command "Set-StrictMode -Version 3.0; $ErrorActionPreference = \"Stop\"; (New-Object Net.WebClient).DownloadFile('%JVM_URL%', '%JVM_TEMP_FILE%')"
83 | if errorlevel 1 goto fail
84 |
85 | POPD
86 |
87 | RMDIR /S /Q "%JVM_TARGET_DIR%"
88 | if errorlevel 1 goto fail
89 |
90 | MKDIR "%JVM_TARGET_DIR%"
91 | if errorlevel 1 goto fail
92 |
93 | PUSHD "%JVM_TARGET_DIR%"
94 | if errorlevel 1 goto fail
95 |
96 | echo Extracting %BUILD_DIR%\%JVM_TEMP_FILE% to %JVM_TARGET_DIR%
97 |
98 | if "%IS_TAR_GZ%"=="1" (
99 | tar xf "..\\%JVM_TEMP_FILE%"
100 | ) else (
101 | "%POWERSHELL%" -nologo -noprofile -command "Set-StrictMode -Version 3.0; $ErrorActionPreference = \"Stop\"; Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('..\\%JVM_TEMP_FILE%', '.');"
102 | )
103 | if errorlevel 1 goto fail
104 |
105 | DEL /F "..\%JVM_TEMP_FILE%"
106 | if errorlevel 1 goto fail
107 |
108 | POPD
109 |
110 | echo %JVM_URL%>"%JVM_TARGET_DIR%.flag"
111 | if errorlevel 1 goto fail
112 |
113 | :continueWithJvm
114 |
115 | set JAVA_HOME=
116 | for /d %%d in ("%JVM_TARGET_DIR%"*) do if exist "%%d\bin\java.exe" set JAVA_HOME=%%d
117 | if not exist "%JAVA_HOME%\bin\java.exe" (
118 | echo Unable to find java.exe under %JVM_TARGET_DIR%
119 | goto fail
120 | )
121 |
122 | endlocal & set JAVA_HOME=%JAVA_HOME%
123 |
124 | @rem GRADLE JVM WRAPPER END MARKER
125 |
126 | @rem Find java.exe
127 | if defined JAVA_HOME goto findJavaFromJavaHome
128 |
129 | set JAVA_EXE=java.exe
130 | %JAVA_EXE% -version >NUL 2>&1
131 | if %ERRORLEVEL% equ 0 goto execute
132 |
133 | echo. 1>&2
134 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
135 | echo. 1>&2
136 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
137 | echo location of your Java installation. 1>&2
138 |
139 | goto fail
140 |
141 | :findJavaFromJavaHome
142 | set JAVA_HOME=%JAVA_HOME:"=%
143 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
144 |
145 | if exist "%JAVA_EXE%" goto execute
146 |
147 | echo. 1>&2
148 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
149 | echo. 1>&2
150 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
151 | echo location of your Java installation. 1>&2
152 |
153 | goto fail
154 |
155 | :execute
156 | @rem Setup the command line
157 |
158 | set CLASSPATH=
159 |
160 |
161 | @rem Execute Gradle
162 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
163 |
164 | :end
165 | @rem End local scope for the variables with windows NT shell
166 | if %ERRORLEVEL% equ 0 goto mainEnd
167 |
168 | :fail
169 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
170 | rem the _cmd.exe /c_ return code!
171 | set EXIT_CODE=%ERRORLEVEL%
172 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
173 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
174 | exit /b %EXIT_CODE%
175 |
176 | :mainEnd
177 | if "%OS%"=="Windows_NT" endlocal
178 |
179 | :omega
180 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/filippov/gradle/jvm/wrapper/Plugin.kt:
--------------------------------------------------------------------------------
1 | package me.filippov.gradle.jvm.wrapper
2 |
3 | import org.gradle.api.Plugin
4 | import org.gradle.api.Project
5 | import org.gradle.api.tasks.wrapper.Wrapper
6 | import java.security.MessageDigest
7 |
8 | @Suppress("unused")
9 | class Plugin : Plugin {
10 | companion object {
11 | private const val patchedFileStartMarker = "GRADLE JVM WRAPPER START MARKER"
12 | private const val patchedFileEndMarker = "GRADLE JVM WRAPPER END MARKER"
13 | private const val unixPatchPlaceHolder = "# Determine the Java command to use to start the JVM."
14 | private const val winPatchPlaceHolder = "@rem Find java.exe"
15 | const val wrapperTaskName = "wrapper"
16 | const val extensionName = "jvmWrapper"
17 | }
18 |
19 | private fun String.sha256(): String {
20 | val md = MessageDigest.getInstance("SHA-256")
21 | val digest = md.digest(toByteArray())
22 | return digest.fold("") { str, it -> str + "%02x".format(it) }
23 | }
24 |
25 | private fun getJvmDirName(url: String) =
26 | url.substringAfterLast('/').removeSuffix(".zip").removeSuffix(".tar.gz") +
27 | "-" +
28 | url.sha256().take(6)
29 |
30 | override fun apply(project: Project) {
31 | val cfg = project.extensions.create(extensionName, PluginExtension::class.java)
32 | project.tasks.getByName(wrapperTaskName) {
33 | val task = it as Wrapper
34 | project.afterEvaluate {
35 | val unixJvmScript = """
36 | # $patchedFileStartMarker
37 | BUILD_DIR="${cfg.unixJvmInstallDir}"
38 | JVM_ARCH=${'$'}(uname -m)
39 | JVM_TEMP_FILE=${"$"}BUILD_DIR/gradle-jvm-temp.tar.gz
40 | if [ "${"$"}darwin" = "true" ]; then
41 | case ${"$"}JVM_ARCH in
42 | x86_64)
43 | JVM_URL=${cfg.macX64JvmUrl}
44 | JVM_TARGET_DIR=${"$"}BUILD_DIR/${getJvmDirName(cfg.macX64JvmUrl)}
45 | ;;
46 | arm64)
47 | JVM_URL=${cfg.macAarch64JvmUrl}
48 | JVM_TARGET_DIR=${"$"}BUILD_DIR/${getJvmDirName(cfg.macAarch64JvmUrl)}
49 | ;;
50 | *)
51 | die "Unknown architecture ${"$"}JVM_ARCH"
52 | ;;
53 | esac
54 | elif [ "${"$"}cygwin" = "true" ] || [ "${"$"}msys" = "true" ]; then
55 | JVM_URL=${cfg.windowsX64JvmUrl}
56 | JVM_TARGET_DIR=${"$"}BUILD_DIR/${getJvmDirName(cfg.windowsX64JvmUrl)}
57 | else
58 | JVM_ARCH=${'$'}(linux${'$'}(getconf LONG_BIT) uname -m)
59 | case ${"$"}JVM_ARCH in
60 | x86_64)
61 | JVM_URL=${cfg.linuxX64JvmUrl}
62 | JVM_TARGET_DIR=${"$"}BUILD_DIR/${getJvmDirName(cfg.linuxX64JvmUrl)}
63 | ;;
64 | aarch64)
65 | JVM_URL=${cfg.linuxAarch64JvmUrl}
66 | JVM_TARGET_DIR=${"$"}BUILD_DIR/${getJvmDirName(cfg.linuxAarch64JvmUrl)}
67 | ;;
68 | *)
69 | die "Unknown architecture ${"$"}JVM_ARCH"
70 | ;;
71 | esac
72 | fi
73 |
74 | set -e
75 |
76 | if [ -e "${"$"}JVM_TARGET_DIR/.flag" ] && [ -n "${'$'}(ls "${"$"}JVM_TARGET_DIR")" ] && [ "x${'$'}(cat "${"$"}JVM_TARGET_DIR/.flag")" = "x${"$"}{JVM_URL}" ]; then
77 | # Everything is up-to-date in ${"$"}JVM_TARGET_DIR, do nothing
78 | true
79 | else
80 | echo "Downloading ${"$"}JVM_URL to ${"$"}JVM_TEMP_FILE"
81 |
82 | rm -f "${"$"}JVM_TEMP_FILE"
83 | mkdir -p "${"$"}BUILD_DIR"
84 | if command -v curl >/dev/null 2>&1; then
85 | if [ -t 1 ]; then CURL_PROGRESS="--progress-bar"; else CURL_PROGRESS="--silent --show-error"; fi
86 | # shellcheck disable=SC2086
87 | curl ${"$"}CURL_PROGRESS -L --output "${"$"}{JVM_TEMP_FILE}" "${"$"}JVM_URL" 2>&1
88 | elif command -v wget >/dev/null 2>&1; then
89 | if [ -t 1 ]; then WGET_PROGRESS=""; else WGET_PROGRESS="-nv"; fi
90 | wget ${"$"}WGET_PROGRESS -O "${"$"}{JVM_TEMP_FILE}" "${"$"}JVM_URL" 2>&1
91 | else
92 | die "ERROR: Please install wget or curl"
93 | fi
94 |
95 | echo "Extracting ${"$"}JVM_TEMP_FILE to ${"$"}JVM_TARGET_DIR"
96 | rm -rf "${"$"}JVM_TARGET_DIR"
97 | mkdir -p "${"$"}JVM_TARGET_DIR"
98 |
99 | case "${'$'}JVM_URL" in
100 | *".zip") unzip "${"$"}JVM_TEMP_FILE" -d "${"$"}JVM_TARGET_DIR" ;;
101 | *) tar -x -f "${"$"}JVM_TEMP_FILE" -C "${"$"}JVM_TARGET_DIR" ;;
102 | esac
103 |
104 | rm -f "${"$"}JVM_TEMP_FILE"
105 |
106 | echo "${"$"}JVM_URL" >"${"$"}JVM_TARGET_DIR/.flag"
107 | fi
108 |
109 | JAVA_HOME=
110 | for d in "${"$"}JVM_TARGET_DIR" "${"$"}JVM_TARGET_DIR"/* "${"$"}JVM_TARGET_DIR"/Contents/Home "${"$"}JVM_TARGET_DIR"/*/Contents/Home; do
111 | if [ -e "${"$"}d/bin/java" ]; then
112 | JAVA_HOME="${"$"}d"
113 | fi
114 | done
115 |
116 | if [ '!' -e "${"$"}JAVA_HOME/bin/java" ]; then
117 | die "Unable to find bin/java under ${"$"}JVM_TARGET_DIR"
118 | fi
119 |
120 | # Make it available for child processes
121 | export JAVA_HOME
122 |
123 | set +e
124 |
125 | # $patchedFileEndMarker
126 | """.trimIndent() + "\n\n"
127 |
128 | val winJvmScript = """
129 | @rem $patchedFileStartMarker
130 |
131 | setlocal
132 | set BUILD_DIR=${cfg.winJvmInstallDir}
133 |
134 | for /f "tokens=3 delims= " %%A in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "PROCESSOR_ARCHITECTURE"') do set WIN_ARCH=%%A
135 | if "%WIN_ARCH%" equ "AMD64" (
136 | set JVM_TARGET_DIR=%BUILD_DIR%\${getJvmDirName(cfg.windowsX64JvmUrl)}\
137 | set JVM_URL=${cfg.windowsX64JvmUrl.replace("%", "%%")}
138 | ) else if "%WIN_ARCH%" equ "ARM64" (
139 | set JVM_TARGET_DIR=%BUILD_DIR%\${getJvmDirName(cfg.windowsAarch64JvmUrl)}\
140 | set JVM_URL=${cfg.windowsAarch64JvmUrl.replace("%", "%%")}
141 | ) else (
142 | echo Unknown architecture %WIN_ARCH%
143 | goto fail
144 | )
145 |
146 | set IS_TAR_GZ=0
147 | set JVM_TEMP_FILE=gradle-jvm.zip
148 |
149 | if /I "%JVM_URL:~-7%"==".tar.gz" (
150 | set IS_TAR_GZ=1
151 | set JVM_TEMP_FILE=gradle-jvm.tar.gz
152 | )
153 |
154 | set POWERSHELL=%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
155 |
156 | if not exist "%JVM_TARGET_DIR%" MD "%JVM_TARGET_DIR%"
157 |
158 | if not exist "%JVM_TARGET_DIR%.flag" goto downloadAndExtractJvm
159 |
160 | set /p CURRENT_FLAG=<"%JVM_TARGET_DIR%.flag"
161 | if "%CURRENT_FLAG%" == "%JVM_URL%" goto continueWithJvm
162 |
163 | :downloadAndExtractJvm
164 |
165 | PUSHD "%BUILD_DIR%"
166 | if errorlevel 1 goto fail
167 |
168 | echo Downloading %JVM_URL% to %BUILD_DIR%\%JVM_TEMP_FILE%
169 | if exist "%JVM_TEMP_FILE%" DEL /F "%JVM_TEMP_FILE%"
170 | "%POWERSHELL%" -nologo -noprofile -Command "Set-StrictMode -Version 3.0; ${"$"}ErrorActionPreference = \"Stop\"; (New-Object Net.WebClient).DownloadFile('%JVM_URL%', '%JVM_TEMP_FILE%')"
171 | if errorlevel 1 goto fail
172 |
173 | POPD
174 |
175 | RMDIR /S /Q "%JVM_TARGET_DIR%"
176 | if errorlevel 1 goto fail
177 |
178 | MKDIR "%JVM_TARGET_DIR%"
179 | if errorlevel 1 goto fail
180 |
181 | PUSHD "%JVM_TARGET_DIR%"
182 | if errorlevel 1 goto fail
183 |
184 | echo Extracting %BUILD_DIR%\%JVM_TEMP_FILE% to %JVM_TARGET_DIR%
185 |
186 | if "%IS_TAR_GZ%"=="1" (
187 | tar xf "..\\%JVM_TEMP_FILE%"
188 | ) else (
189 | "%POWERSHELL%" -nologo -noprofile -command "Set-StrictMode -Version 3.0; ${"$"}ErrorActionPreference = \"Stop\"; Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('..\\%JVM_TEMP_FILE%', '.');"
190 | )
191 | if errorlevel 1 goto fail
192 |
193 | DEL /F "..\%JVM_TEMP_FILE%"
194 | if errorlevel 1 goto fail
195 |
196 | POPD
197 |
198 | echo %JVM_URL%>"%JVM_TARGET_DIR%.flag"
199 | if errorlevel 1 goto fail
200 |
201 | :continueWithJvm
202 |
203 | set JAVA_HOME=
204 | for /d %%d in ("%JVM_TARGET_DIR%"*) do if exist "%%d\bin\java.exe" set JAVA_HOME=%%d
205 | if not exist "%JAVA_HOME%\bin\java.exe" (
206 | echo Unable to find java.exe under %JVM_TARGET_DIR%
207 | goto fail
208 | )
209 |
210 | endlocal & set JAVA_HOME=%JAVA_HOME%
211 |
212 | @rem $patchedFileEndMarker
213 | """.trimIndent() + "\n\n"
214 |
215 | task.inputs.property("unixJvmScript", unixJvmScript)
216 | task.inputs.property("winJvmScript", winJvmScript)
217 |
218 | task.doLast {
219 | val unixScriptFile = task.scriptFile
220 | val winScriptFile = task.batchScript
221 |
222 | val unixScriptFileContent = unixScriptFile.readText(Charsets.UTF_8)
223 | if (!unixScriptFileContent.contains(patchedFileStartMarker)) {
224 | project.logger.debug("Patch $unixScriptFile")
225 | val newUnixScriptFileContent = unixScriptFileContent.replace(unixPatchPlaceHolder, unixJvmScript + unixPatchPlaceHolder)
226 | unixScriptFile.writeText(newUnixScriptFileContent, Charsets.UTF_8)
227 | project.logger.debug("$unixScriptFile patched")
228 | } else {
229 | project.logger.debug("$unixScriptFile is up-to-date")
230 | }
231 | val winScriptFileContent = winScriptFile.readText(Charsets.UTF_8)
232 | if (!winScriptFileContent.contains(patchedFileStartMarker)) {
233 | project.logger.debug("Patch $winScriptFile")
234 | val newWinScriptFileContent = winScriptFileContent.replace(winPatchPlaceHolder,
235 | if (winScriptFileContent.contains("\r\n")) {
236 | winJvmScript.replace("\n", "\r\n")
237 | } else {
238 | winJvmScript
239 | } + winPatchPlaceHolder)
240 | winScriptFile.writeText(newWinScriptFileContent, Charsets.UTF_8)
241 | project.logger.debug("$winScriptFile patched")
242 | } else {
243 | project.logger.debug("$winScriptFile is up-to-date")
244 | }
245 | }
246 | }
247 | }
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # GRADLE JVM WRAPPER START MARKER
121 | BUILD_DIR="build/gradle-jvm"
122 | JVM_ARCH=$(uname -m)
123 | JVM_TEMP_FILE=$BUILD_DIR/gradle-jvm-temp.tar.gz
124 | if [ "$darwin" = "true" ]; then
125 | case $JVM_ARCH in
126 | x86_64)
127 | JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_macos-x64_bin.tar.gz
128 | JVM_TARGET_DIR=$BUILD_DIR/jdk-21.0.5_macos-x64_bin-2fbf6d
129 | ;;
130 | arm64)
131 | JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_macos-aarch64_bin.tar.gz
132 | JVM_TARGET_DIR=$BUILD_DIR/jdk-21.0.5_macos-aarch64_bin-d1143e
133 | ;;
134 | *)
135 | die "Unknown architecture $JVM_ARCH"
136 | ;;
137 | esac
138 | elif [ "$cygwin" = "true" ] || [ "$msys" = "true" ]; then
139 | JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_windows-x64_bin.zip
140 | JVM_TARGET_DIR=$BUILD_DIR/jdk-21.0.5_windows-x64_bin-020647
141 | else
142 | JVM_ARCH=$(linux$(getconf LONG_BIT) uname -m)
143 | case $JVM_ARCH in
144 | x86_64)
145 | JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-x64_bin.tar.gz
146 | JVM_TARGET_DIR=$BUILD_DIR/jdk-21.0.5_linux-x64_bin-aef79a
147 | ;;
148 | aarch64)
149 | JVM_URL=https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-aarch64_bin.tar.gz
150 | JVM_TARGET_DIR=$BUILD_DIR/jdk-21.0.5_linux-aarch64_bin-8db84d
151 | ;;
152 | *)
153 | die "Unknown architecture $JVM_ARCH"
154 | ;;
155 | esac
156 | fi
157 |
158 | set -e
159 |
160 | if [ -e "$JVM_TARGET_DIR/.flag" ] && [ -n "$(ls "$JVM_TARGET_DIR")" ] && [ "x$(cat "$JVM_TARGET_DIR/.flag")" = "x${JVM_URL}" ]; then
161 | # Everything is up-to-date in $JVM_TARGET_DIR, do nothing
162 | true
163 | else
164 | echo "Downloading $JVM_URL to $JVM_TEMP_FILE"
165 |
166 | rm -f "$JVM_TEMP_FILE"
167 | mkdir -p "$BUILD_DIR"
168 | if command -v curl >/dev/null 2>&1; then
169 | if [ -t 1 ]; then CURL_PROGRESS="--progress-bar"; else CURL_PROGRESS="--silent --show-error"; fi
170 | # shellcheck disable=SC2086
171 | curl $CURL_PROGRESS -L --output "${JVM_TEMP_FILE}" "$JVM_URL" 2>&1
172 | elif command -v wget >/dev/null 2>&1; then
173 | if [ -t 1 ]; then WGET_PROGRESS=""; else WGET_PROGRESS="-nv"; fi
174 | wget $WGET_PROGRESS -O "${JVM_TEMP_FILE}" "$JVM_URL" 2>&1
175 | else
176 | die "ERROR: Please install wget or curl"
177 | fi
178 |
179 | echo "Extracting $JVM_TEMP_FILE to $JVM_TARGET_DIR"
180 | rm -rf "$JVM_TARGET_DIR"
181 | mkdir -p "$JVM_TARGET_DIR"
182 |
183 | case "$JVM_URL" in
184 | *".zip") unzip "$JVM_TEMP_FILE" -d "$JVM_TARGET_DIR" ;;
185 | *) tar -x -f "$JVM_TEMP_FILE" -C "$JVM_TARGET_DIR" ;;
186 | esac
187 |
188 | rm -f "$JVM_TEMP_FILE"
189 |
190 | echo "$JVM_URL" >"$JVM_TARGET_DIR/.flag"
191 | fi
192 |
193 | JAVA_HOME=
194 | for d in "$JVM_TARGET_DIR" "$JVM_TARGET_DIR"/* "$JVM_TARGET_DIR"/Contents/Home "$JVM_TARGET_DIR"/*/Contents/Home; do
195 | if [ -e "$d/bin/java" ]; then
196 | JAVA_HOME="$d"
197 | fi
198 | done
199 |
200 | if [ '!' -e "$JAVA_HOME/bin/java" ]; then
201 | die "Unable to find bin/java under $JVM_TARGET_DIR"
202 | fi
203 |
204 | # Make it available for child processes
205 | export JAVA_HOME
206 |
207 | set +e
208 |
209 | # GRADLE JVM WRAPPER END MARKER
210 |
211 | # Determine the Java command to use to start the JVM.
212 | if [ -n "$JAVA_HOME" ] ; then
213 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
214 | # IBM's JDK on AIX uses strange locations for the executables
215 | JAVACMD=$JAVA_HOME/jre/sh/java
216 | else
217 | JAVACMD=$JAVA_HOME/bin/java
218 | fi
219 | if [ ! -x "$JAVACMD" ] ; then
220 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
221 |
222 | Please set the JAVA_HOME variable in your environment to match the
223 | location of your Java installation."
224 | fi
225 | else
226 | JAVACMD=java
227 | if ! command -v java >/dev/null 2>&1
228 | then
229 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
230 |
231 | Please set the JAVA_HOME variable in your environment to match the
232 | location of your Java installation."
233 | fi
234 | fi
235 |
236 | # Increase the maximum file descriptors if we can.
237 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
238 | case $MAX_FD in #(
239 | max*)
240 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
241 | # shellcheck disable=SC2039,SC3045
242 | MAX_FD=$( ulimit -H -n ) ||
243 | warn "Could not query maximum file descriptor limit"
244 | esac
245 | case $MAX_FD in #(
246 | '' | soft) :;; #(
247 | *)
248 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
249 | # shellcheck disable=SC2039,SC3045
250 | ulimit -n "$MAX_FD" ||
251 | warn "Could not set maximum file descriptor limit to $MAX_FD"
252 | esac
253 | fi
254 |
255 | # Collect all arguments for the java command, stacking in reverse order:
256 | # * args from the command line
257 | # * the main class name
258 | # * -classpath
259 | # * -D...appname settings
260 | # * --module-path (only if needed)
261 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
262 |
263 | # For Cygwin or MSYS, switch paths to Windows format before running java
264 | if "$cygwin" || "$msys" ; then
265 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
266 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
267 |
268 | JAVACMD=$( cygpath --unix "$JAVACMD" )
269 |
270 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
271 | for arg do
272 | if
273 | case $arg in #(
274 | -*) false ;; # don't mess with options #(
275 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
276 | [ -e "$t" ] ;; #(
277 | *) false ;;
278 | esac
279 | then
280 | arg=$( cygpath --path --ignore --mixed "$arg" )
281 | fi
282 | # Roll the args list around exactly as many times as the number of
283 | # args, so each arg winds up back in the position where it started, but
284 | # possibly modified.
285 | #
286 | # NB: a `for` loop captures its iteration list before it begins, so
287 | # changing the positional parameters here affects neither the number of
288 | # iterations, nor the values presented in `arg`.
289 | shift # remove old arg
290 | set -- "$@" "$arg" # push replacement arg
291 | done
292 | fi
293 |
294 |
295 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
296 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
297 |
298 | # Collect all arguments for the java command:
299 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
300 | # and any embedded shellness will be escaped.
301 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
302 | # treated as '${Hostname}' itself on the command line.
303 |
304 | set -- \
305 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
306 | -classpath "$CLASSPATH" \
307 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
308 | "$@"
309 |
310 | # Stop when "xargs" is not available.
311 | if ! command -v xargs >/dev/null 2>&1
312 | then
313 | die "xargs is not available"
314 | fi
315 |
316 | # Use "xargs" to parse quoted args.
317 | #
318 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
319 | #
320 | # In Bash we could simply go:
321 | #
322 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
323 | # set -- "${ARGS[@]}" "$@"
324 | #
325 | # but POSIX shell has neither arrays nor command substitution, so instead we
326 | # post-process each arg (as a line of input to sed) to backslash-escape any
327 | # character that might be a shell metacharacter, then use eval to reverse
328 | # that process (while maintaining the separation between arguments), and wrap
329 | # the whole thing up as a single "set" statement.
330 | #
331 | # This will of course break if any of these variables contains a newline or
332 | # an unmatched quote.
333 | #
334 |
335 | eval "set -- $(
336 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
337 | xargs -n1 |
338 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
339 | tr '\n' ' '
340 | )" '"$@"'
341 |
342 | exec "$JAVACMD" "$@"
343 |
--------------------------------------------------------------------------------