diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c479e54d58..66ff406d02 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,9 +22,9 @@ jobs:
- version: 17
toolchain: false
- version: 21
- toolchain: true
+ toolchain: false
- version: 22
- toolchain: true
+ toolchain: false
- version: 23
toolchain: true
exclude:
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 1acc7a6d9d..c4bf76bff5 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -10,8 +10,11 @@ repositories {
gradlePluginPortal()
}
-sourceCompatibility = 17
-targetCompatibility = 17
+java {
+ sourceCompatibility = 17
+ targetCompatibility = 17
+}
+
if ("${springFrameworkVersion}".contains("-")) {
repositories {
@@ -36,6 +39,7 @@ dependencies {
implementation("com.tngtech.archunit:archunit:1.3.0")
implementation("commons-codec:commons-codec:${commonsCodecVersion}")
implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0")
+ implementation("dev.adamko.dokkatoo:dokkatoo-plugin:2.3.1")
implementation("io.spring.gradle.antora:spring-antora-plugin:0.0.1")
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}")
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/KotlinConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/KotlinConventions.java
index 9975dcfca5..3848583218 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/KotlinConventions.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/KotlinConventions.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.List;
import dev.adamko.dokkatoo.DokkatooExtension;
-import dev.adamko.dokkatoo.formats.DokkatooHtmlPlugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
@@ -29,8 +28,8 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions;
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile;
/**
- * Conventions that are applied in the presence of the {@code org.jetbrains.kotlin.jvm}
- * plugin. When the plugin is applied:
+ * Conventions that are applied in the presence of the
+ * {@code org.jetbrains.kotlin.jvm} plugin. When the plugin is applied:
*
*
* - {@link KotlinCompile} tasks are configured to:
@@ -67,22 +66,18 @@ class KotlinConventions {
}
private void configureDokkatoo(Project project) {
- project.getPlugins().apply(DokkatooHtmlPlugin.class);
DokkatooExtension dokkatoo = project.getExtensions().getByType(DokkatooExtension.class);
dokkatoo.getDokkatooSourceSets().named(SourceSet.MAIN_SOURCE_SET_NAME).configure((sourceSet) -> {
sourceSet.getSourceRoots().setFrom(project.file("src/main/kotlin"));
- sourceSet.getClasspath()
- .from(project.getExtensions()
- .getByType(SourceSetContainer.class)
- .getByName(SourceSet.MAIN_SOURCE_SET_NAME)
- .getOutput());
+ sourceSet.getClasspath().from(project.getExtensions().getByType(SourceSetContainer.class)
+ .getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput());
sourceSet.getExternalDocumentationLinks().create("spring-boot-javadoc", (link) -> {
link.getUrl().set(URI.create("https://docs.spring.io/spring-boot/api/java/"));
link.getPackageListUrl().set(URI.create("https://docs.spring.io/spring-boot/api/java/element-list"));
});
sourceSet.getExternalDocumentationLinks().create("spring-framework-javadoc", (link) -> {
String url = "https://docs.spring.io/spring-framework/docs/%s/javadoc-api/"
- .formatted(project.property("springFrameworkVersion"));
+ .formatted(project.property("springFrameworkVersion"));
link.getUrl().set(URI.create(url));
link.getPackageListUrl().set(URI.create(url + "/element-list"));
});
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/InteractiveUpgradeResolver.java b/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/InteractiveUpgradeResolver.java
index 840665d78d..3778b177a6 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/InteractiveUpgradeResolver.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/bom/bomr/InteractiveUpgradeResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2023 the original author or authors.
+ * Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.boot.build.bom.bomr;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -58,12 +59,17 @@ public final class InteractiveUpgradeResolver implements UpgradeResolver {
if (libraryWithVersionOptions.getVersionOptions().isEmpty()) {
return null;
}
- VersionOption current = new VersionOption(libraryWithVersionOptions.getLibrary().getVersion().getVersion());
- VersionOption selected = this.userInputHandler.selectOption(
- libraryWithVersionOptions.getLibrary().getName() + " "
- + libraryWithVersionOptions.getLibrary().getVersion().getVersion(),
- libraryWithVersionOptions.getVersionOptions(), current);
- return (selected.equals(current)) ? null
+ VersionOption defaultOption = new VersionOption(
+ libraryWithVersionOptions.getLibrary().getVersion().getVersion());
+ VersionOption selected = this.userInputHandler.askUser((questions) -> {
+ String question = libraryWithVersionOptions.getLibrary().getName() + " "
+ + libraryWithVersionOptions.getLibrary().getVersion().getVersion();
+ List options = new ArrayList<>();
+ options.add(defaultOption);
+ options.addAll(libraryWithVersionOptions.getVersionOptions());
+ return questions.selectOption(question, options, defaultOption);
+ }).get();
+ return (selected.equals(defaultOption)) ? null
: new Upgrade(libraryWithVersionOptions.getLibrary(), selected.getVersion());
}
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/test/DockerTestPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/test/DockerTestPlugin.java
index b2970b2ed2..6c33d0fb9a 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/test/DockerTestPlugin.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/test/DockerTestPlugin.java
@@ -71,6 +71,8 @@ public class DockerTestPlugin implements Plugin {
.add(project.getConfigurations()
.getByName(dockerTestSourceSet.getRuntimeClasspathConfigurationName())));
});
+ project.getDependencies()
+ .add(dockerTestSourceSet.getRuntimeOnlyConfigurationName(), "org.junit.platform:junit-platform-launcher");
}
private SourceSet createSourceSet(Project project) {
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/test/IntegrationTestPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/test/IntegrationTestPlugin.java
index 6286df7601..34ff445b88 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/test/IntegrationTestPlugin.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/test/IntegrationTestPlugin.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2023 the original author or authors.
+ * Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,6 +58,8 @@ public class IntegrationTestPlugin implements Plugin {
eclipse.classpath((classpath) -> classpath.getPlusConfigurations()
.add(project.getConfigurations().getByName(intTestSourceSet.getRuntimeClasspathConfigurationName())));
});
+ project.getDependencies()
+ .add(intTestSourceSet.getRuntimeOnlyConfigurationName(), "org.junit.platform:junit-platform-launcher");
}
private SourceSet createSourceSet(Project project) {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index d64cd49177..a4b76b9530 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 3e593191a3..0aaefbcaf0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index 1aa94a4269..f5feea6d6b 100755
--- a/gradlew
+++ b/gradlew
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
+' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
diff --git a/gradlew.bat b/gradlew.bat
index 25da30dbde..9d21a21834 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle
index 3b4e685872..f87d6af8db 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle
@@ -202,6 +202,8 @@ tasks.named("test") {
}
def documentationTest = tasks.register("documentationTest", Test) {
+ testClassesDirs = testing.suites.test.sources.output.classesDirs
+ classpath = testing.suites.test.sources.runtimeClasspath
jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED"
filter {
includeTestsMatching("org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation.*")
diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle
index 6883de0b76..e080bd1035 100644
--- a/spring-boot-project/spring-boot-docs/build.gradle
+++ b/spring-boot-project/spring-boot-docs/build.gradle
@@ -1,4 +1,5 @@
plugins {
+ id "dev.adamko.dokkatoo-html"
id "java"
id "org.antora"
id "org.springframework.boot.conventions"
@@ -43,7 +44,7 @@ sourcesJar {
}
plugins.withType(EclipsePlugin) {
- extensions.getByType(org.gradle.plugins.ide.eclipse.model.EclipseModel).classpath { classpath ->
+ eclipse.classpath { classpath ->
classpath.plusConfigurations.add(configurations.getByName(sourceSets.main.runtimeClasspathConfigurationName))
}
}
diff --git a/spring-boot-project/spring-boot-test/build.gradle b/spring-boot-project/spring-boot-test/build.gradle
index 93fc006fbb..93c60932d8 100644
--- a/spring-boot-project/spring-boot-test/build.gradle
+++ b/spring-boot-project/spring-boot-test/build.gradle
@@ -1,4 +1,5 @@
plugins {
+ id "dev.adamko.dokkatoo-html"
id "java-library"
id "org.jetbrains.kotlin.jvm"
id "org.springframework.boot.conventions"
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-cli/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-cli/build.gradle
index bf42c68162..90d2420d6c 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-cli/build.gradle
+++ b/spring-boot-project/spring-boot-tools/spring-boot-cli/build.gradle
@@ -82,11 +82,11 @@ def configureArchive(archive) {
into "lib/"
}
archive.from(file("src/main/content")) {
- dirMode = 0755
- fileMode = 0644
+ dirPermissions { unix(0755) }
+ filePermissions { unix(0644) }
}
archive.from(file("src/main/executablecontent")) {
- fileMode = 0755
+ filePermissions { unix(0755) }
}
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java
index f87b6fe5fc..b767735ed3 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java
@@ -19,10 +19,8 @@ package org.springframework.boot.gradle.plugin;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
-import java.lang.reflect.Method;
import java.util.concurrent.Callable;
-import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
@@ -128,32 +126,16 @@ final class ApplicationPluginAction implements PluginApplicationAction {
private void configureFilePermissions(CopySpec copySpec, int mode) {
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
- try {
- Method filePermissions = copySpec.getClass().getMethod("filePermissions", Action.class);
- filePermissions.invoke(copySpec, new Action<>() {
-
- @Override
- public void execute(Object filePermissions) {
- String unixPermissions = Integer.toString(mode, 8);
- try {
- Method unix = filePermissions.getClass().getMethod("unix", String.class);
- unix.invoke(filePermissions, unixPermissions);
- }
- catch (Exception ex) {
- throw new GradleException("Failed to set file permissions to '" + unixPermissions + "'",
- ex);
- }
- }
-
- });
- }
- catch (Exception ex) {
- throw new GradleException("Failed to set file permissions", ex);
- }
+ copySpec.filePermissions((filePermissions) -> filePermissions.unix(Integer.toString(mode, 8)));
}
else {
- copySpec.setFileMode(mode);
+ configureFileMode(copySpec, mode);
}
}
+ @SuppressWarnings("deprecation")
+ private void configureFileMode(CopySpec copySpec, int mode) {
+ copySpec.setFileMode(mode);
+ }
+
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java
index 6cdd36d5f2..437547bf94 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java
@@ -26,9 +26,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
-import java.util.function.Supplier;
-import org.gradle.api.GradleException;
+import org.gradle.api.file.ConfigurableFilePermissions;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FileTreeElement;
@@ -133,8 +132,8 @@ class BootArchiveSupport {
File output = jar.getArchiveFile().get().getAsFile();
Manifest manifest = jar.getManifest();
boolean preserveFileTimestamps = jar.isPreserveFileTimestamps();
- Integer dirMode = getDirMode(jar);
- Integer fileMode = getFileMode(jar);
+ Integer dirPermissions = getUnixNumericDirPermissions(jar);
+ Integer filePermissions = getUnixNumericFilePermissions(jar);
boolean includeDefaultLoader = isUsingDefaultLoader(jar);
Spec requiresUnpack = this.requiresUnpack.getAsSpec();
Spec exclusions = this.exclusions.getAsExcludeSpec();
@@ -142,35 +141,35 @@ class BootArchiveSupport {
Spec librarySpec = this.librarySpec;
Function compressionResolver = this.compressionResolver;
String encoding = jar.getMetadataCharset();
- CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirMode, fileMode,
- includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript, librarySpec,
- compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver,
+ CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions,
+ filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript,
+ librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver,
loaderImplementation);
return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action;
}
+ private Integer getUnixNumericDirPermissions(CopySpec copySpec) {
+ return (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0)
+ ? asUnixNumeric(copySpec.getDirPermissions()) : getDirMode(copySpec);
+ }
+
+ private Integer getUnixNumericFilePermissions(CopySpec copySpec) {
+ return (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0)
+ ? asUnixNumeric(copySpec.getFilePermissions()) : getFileMode(copySpec);
+ }
+
+ private Integer asUnixNumeric(Property permissions) {
+ return permissions.isPresent() ? permissions.get().toUnixNumeric() : null;
+ }
+
+ @SuppressWarnings("deprecation")
private Integer getDirMode(CopySpec copySpec) {
- return getMode(copySpec, "getDirPermissions", () -> copySpec.getDirMode());
+ return copySpec.getDirMode();
}
+ @SuppressWarnings("deprecation")
private Integer getFileMode(CopySpec copySpec) {
- return getMode(copySpec, "getFilePermissions", () -> copySpec.getFileMode());
- }
-
- @SuppressWarnings("unchecked")
- private Integer getMode(CopySpec copySpec, String methodName, Supplier fallback) {
- if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
- try {
- Object filePermissions = ((Property