diff --git a/build-plugin/spring-boot-antlib/build.gradle b/build-plugin/spring-boot-antlib/build.gradle index 7afc096c366..928f57dd1de 100644 --- a/build-plugin/spring-boot-antlib/build.gradle +++ b/build-plugin/spring-boot-antlib/build.gradle @@ -80,7 +80,6 @@ tasks.register("integrationTest") { ant.propertyref(name: "ivy.class.path") } plainlistener() - file(layout.buildDirectory.dir("test-results/integrationTest")).mkdirs() xmllistener(toDir: resultsDir) fileset(dir: layout.buildDirectory.dir("it").get().asFile.toString(), includes: "**/build.xml") } diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java index 82e3f245dfb..c2ef3c208f4 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java @@ -141,9 +141,13 @@ final class ApplicationPluginAction implements PluginApplicationAction { } } - @SuppressWarnings("deprecation") private void configureFileMode(CopySpec copySpec, int mode) { - copySpec.setFileMode(mode); + try { + copySpec.getClass().getMethod("setFileMode", Integer.class).invoke(copySpec, Integer.valueOf(mode)); + } + catch (Exception ex) { + throw new RuntimeException("Failed to set file mode on CopySpec", ex); + } } } diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java index 67a29cfbae5..a78263c8b8d 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java @@ -285,7 +285,6 @@ final class JavaPluginAction implements PluginApplicationAction { private void configureProductionRuntimeClasspathConfiguration(Project project) { Configuration productionRuntimeClasspath = project.getConfigurations() .create(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME); - productionRuntimeClasspath.setVisible(false); Configuration runtimeClasspath = project.getConfigurations() .getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); productionRuntimeClasspath.attributes((attributes) -> { diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java index 4401f430722..8ee4c08ae45 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java @@ -104,7 +104,6 @@ class WarPluginAction implements PluginApplicationAction { .set(project.provider(() -> javaPluginExtension(project).getTargetCompatibility())); bootWar.resolvedArtifacts(runtimeClasspath.getIncoming().getArtifacts().getResolvedArtifacts()); }); - bootWarProvider.map(War::getClasspath); return bootWarProvider; } diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java index 6805f1199ab..9a09e71f125 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/ProcessTestAot.java @@ -43,7 +43,7 @@ import org.springframework.util.Assert; * @since 3.0.0 */ @CacheableTask -public class ProcessTestAot extends AbstractAot { +public abstract class ProcessTestAot extends AbstractAot { private @Nullable FileCollection classpathRoots; diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java index 27dccf61b35..9597ab3cc74 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java @@ -22,25 +22,19 @@ import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.function.Function; import org.gradle.api.file.ConfigurableFilePermissions; import org.gradle.api.file.CopySpec; import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; -import org.gradle.api.file.RelativePath; import org.gradle.api.internal.file.copy.CopyAction; -import org.gradle.api.internal.file.copy.CopyActionProcessingStream; -import org.gradle.api.internal.file.copy.FileCopyDetailsInternal; import org.gradle.api.java.archives.Attributes; import org.gradle.api.java.archives.Manifest; import org.gradle.api.provider.Property; import org.gradle.api.specs.Spec; import org.gradle.api.specs.Specs; -import org.gradle.api.tasks.WorkResult; import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.util.PatternSet; import org.gradle.util.GradleVersion; @@ -142,7 +136,7 @@ class BootArchiveSupport { CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions, filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript, librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver); - return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action; + return action; } private @Nullable Integer getUnixNumericDirPermissions(CopySpec copySpec) { @@ -159,14 +153,22 @@ class BootArchiveSupport { return permissions.isPresent() ? permissions.get().toUnixNumeric() : null; } - @SuppressWarnings("deprecation") private @Nullable Integer getDirMode(CopySpec copySpec) { - return copySpec.getDirMode(); + try { + return (Integer) copySpec.getClass().getMethod("getDirMode").invoke(copySpec); + } + catch (Exception ex) { + throw new RuntimeException("Failed to get dir mode from CopySpec", ex); + } } - @SuppressWarnings("deprecation") private @Nullable Integer getFileMode(CopySpec copySpec) { - return copySpec.getFileMode(); + try { + return (Integer) copySpec.getClass().getMethod("getFileMode").invoke(copySpec); + } + catch (Exception ex) { + throw new RuntimeException("Failed to get file mode from CopySpec", ex); + } } private boolean isUsingDefaultLoader(Jar jar) { @@ -229,26 +231,4 @@ class BootArchiveSupport { details.setRelativePath(details.getRelativeSourcePath()); } - /** - * {@link CopyAction} variant that sorts entries to ensure reproducible ordering. - */ - private static final class ReproducibleOrderingCopyAction implements CopyAction { - - private final CopyAction delegate; - - private ReproducibleOrderingCopyAction(CopyAction delegate) { - this.delegate = delegate; - } - - @Override - public WorkResult execute(CopyActionProcessingStream stream) { - return this.delegate.execute((action) -> { - Map detailsByPath = new TreeMap<>(); - stream.process((details) -> detailsByPath.put(details.getRelativePath(), details)); - detailsByPath.values().forEach(action::processFile); - }); - } - - } - } diff --git a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java index 3f7f1088da6..c4735b578c0 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java +++ b/build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java @@ -504,9 +504,13 @@ class BootZipCopyAction implements CopyAction { ? details.getPermissions().toUnixNumeric() : getMode(details); } - @SuppressWarnings("deprecation") private int getMode(FileCopyDetails details) { - return details.getMode(); + try { + return (int) details.getClass().getMethod("getMode").invoke(details); + } + catch (Exception ex) { + throw new RuntimeException("Failed to get mode from FileCopyDetails", ex); + } } } diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java index 9944ffe8795..27940c7587b 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoTests.java @@ -24,8 +24,6 @@ import java.time.format.DateTimeFormatter; import java.util.Properties; import org.gradle.api.Project; -import org.gradle.api.internal.project.ProjectInternal; -import org.gradle.initialization.GradlePropertiesController; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -173,11 +171,7 @@ class BuildInfoTests { private Project createProject(String projectName) { File projectDir = new File(this.temp, projectName); - Project project = GradleProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build(); - ((ProjectInternal) project).getServices() - .get(GradlePropertiesController.class) - .loadGradlePropertiesFrom(projectDir, false); - return project; + return GradleProjectBuilder.builder().withProjectDir(projectDir).withName(projectName).build(); } private BuildInfo createTask(Project project) { diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java index 42ad5f82845..e720ed7111b 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java @@ -233,14 +233,8 @@ abstract class AbstractBootArchiveIntegrationTests { .filter((entry) -> !entry.isDirectory()) .map(JarEntry::getName) .filter((name) -> name.startsWith(this.libPath)); - if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) { - assertThat(libEntryNames).containsExactly(this.libPath + "two-1.0.jar", - this.libPath + "commons-io-2.19.0.jar"); - } - else { - assertThat(libEntryNames).containsExactly(this.libPath + "commons-io-2.19.0.jar", - this.libPath + "two-1.0.jar"); - } + assertThat(libEntryNames).containsExactly(this.libPath + "two-1.0.jar", + this.libPath + "commons-io-2.19.0.jar"); } } diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java index d9cc6f6bc52..f11bc01253c 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java @@ -27,6 +27,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.PosixFilePermission; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; @@ -35,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.UUID; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -407,23 +410,46 @@ abstract class AbstractBootArchiveTests { } @Test - void reproducibleOrderingCanBeEnabled() throws IOException { + void archiveIsReproducibleByDefault() throws IOException { this.task.getMainClass().set("com.example.Main"); - this.task.from(newFile("bravo.txt"), newFile("alpha.txt"), newFile("charlie.txt")); - this.task.setReproducibleFileOrder(true); + this.task.from(newFiles("files/b/bravo.txt", "files/a/alpha.txt", "files/c/charlie.txt")); executeTask(); assertThat(this.task.getArchiveFile().get().getAsFile()).exists(); - List textFiles = new ArrayList<>(); + List files = new ArrayList<>(); try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) { Enumeration entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); - if (entry.getName().endsWith(".txt")) { - textFiles.add(entry.getName()); + OffsetDateTime lastModifiedTime = entry.getLastModifiedTime().toInstant().atOffset(ZoneOffset.UTC); + assertThat(lastModifiedTime).isEqualTo(OffsetDateTime.of(1980, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC)); + if (entry.getName().startsWith("files/")) { + files.add(entry.getName()); + } + } + } + assertThat(files).containsExactly("files/", "files/a/", "files/a/alpha.txt", "files/b/", "files/b/bravo.txt", + "files/c/", "files/c/charlie.txt"); + } + + @Test + void archiveReproducibilityCanBeDisabled() throws IOException { + this.task.getMainClass().set("com.example.Main"); + this.task.from(newFiles("files/b/bravo.txt", "files/a/alpha.txt", "files/c/charlie.txt")); + this.task.setPreserveFileTimestamps(true); + this.task.setReproducibleFileOrder(false); + executeTask(); + assertThat(this.task.getArchiveFile().get().getAsFile()).exists(); + try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".txt") || entry.getName().startsWith("BOOT-INF/lib/")) { + OffsetDateTime lastModifiedTime = entry.getLastModifiedTime().toInstant().atOffset(ZoneOffset.UTC); + assertThat(lastModifiedTime) + .isNotEqualTo(OffsetDateTime.of(1980, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC)); } } } - assertThat(textFiles).containsExactly("alpha.txt", "bravo.txt", "charlie.txt"); } @Test @@ -663,6 +689,19 @@ abstract class AbstractBootArchiveTests { return entryNames; } + protected File newFiles(String... names) throws IOException { + File dir = new File(this.temp, UUID.randomUUID().toString()); + dir.mkdir(); + List files = new ArrayList<>(); + for (String name : names) { + File file = new File(dir, name); + file.getParentFile().mkdirs(); + file.createNewFile(); + files.add(file); + } + return dir; + } + protected File newFile(String name) throws IOException { File file = new File(this.temp, name); file.createNewFile(); diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java index e8c2269177f..8ed557deb86 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java +++ b/build-plugin/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java @@ -66,18 +66,10 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { copyClasspathApplication(); BuildResult result = this.gradleBuild.build("launch"); String output = result.getOutput(); - if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) { - assertThat(output).containsPattern("1\\. .*classes"); - assertThat(output).containsPattern("2\\. .*library-1.0-SNAPSHOT.jar"); - assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar"); - assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar"); - } - else { - assertThat(output).containsPattern("1\\. .*classes"); - assertThat(output).containsPattern("2\\. .*commons-lang3-3.9.jar"); - assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar"); - assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar"); - } + assertThat(output).containsPattern("1\\. .*classes"); + assertThat(output).containsPattern("2\\. .*library-1.0-SNAPSHOT.jar"); + assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar"); + assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-tools.*.jar"); assertThat(output).doesNotContain("5. "); } @@ -86,18 +78,10 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { copyClasspathApplication(); BuildResult result = this.gradleBuild.build("launch"); String output = result.getOutput(); - if (this.gradleBuild.gradleVersionIsLessThan("9.0.0-rc-1")) { - assertThat(output).containsPattern("1\\. .*classes"); - assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar"); - assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar"); - assertThat(output).containsPattern("4\\. .*commons-lang3-3.9.jar"); - } - else { - assertThat(output).containsPattern("1\\. .*classes"); - assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar"); - assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar"); - assertThat(output).containsPattern("4\\. .*library-1.0-SNAPSHOT.jar"); - } + assertThat(output).containsPattern("1\\. .*classes"); + assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-tools.*.jar"); + assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar"); + assertThat(output).containsPattern("4\\. .*commons-lang3-3.9.jar"); assertThat(output).doesNotContain("5. "); } diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-reproducibleArchive.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-reproducibleArchive.gradle index a8aae4d8ca8..f35007c6f93 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-reproducibleArchive.gradle +++ b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-reproducibleArchive.gradle @@ -21,6 +21,8 @@ plugins { bootJar { mainClass = 'com.example.Application' - preserveFileTimestamps = false - reproducibleFileOrder = true + if (GradleVersion.current().compareTo(GradleVersion.version("9.0.0-rc-1")) < 0) { + preserveFileTimestamps = false + reproducibleFileOrder = true + } } diff --git a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-reproducibleArchive.gradle b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-reproducibleArchive.gradle index e9e1b70e262..f51b88df2b2 100644 --- a/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-reproducibleArchive.gradle +++ b/build-plugin/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-reproducibleArchive.gradle @@ -21,6 +21,8 @@ plugins { bootWar { mainClass = 'com.example.Application' - preserveFileTimestamps = false - reproducibleFileOrder = true + if (GradleVersion.current().compareTo(GradleVersion.version("9.0.0-rc-1")) < 0) { + preserveFileTimestamps = false + reproducibleFileOrder = true + } } diff --git a/buildSrc/src/main/java/org/springframework/boot/build/optional/OptionalDependenciesPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/optional/OptionalDependenciesPlugin.java index 2f91d3225e0..acbf3f924c8 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/optional/OptionalDependenciesPlugin.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/optional/OptionalDependenciesPlugin.java @@ -41,7 +41,7 @@ public class OptionalDependenciesPlugin implements Plugin { @Override public void apply(Project project) { Configuration optional = project.getConfigurations().create("optional"); - optional.setCanBeConsumed(false); + optional.setCanBeConsumed(true); optional.setCanBeResolved(false); project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { SourceSetContainer sourceSets = project.getExtensions() diff --git a/buildSrc/src/test/java/org/springframework/boot/build/testing/TestFailuresPluginIntegrationTests.java b/buildSrc/src/test/java/org/springframework/boot/build/testing/TestFailuresPluginIntegrationTests.java index 574b725dab8..0e9cc43627a 100644 --- a/buildSrc/src/test/java/org/springframework/boot/build/testing/TestFailuresPluginIntegrationTests.java +++ b/buildSrc/src/test/java/org/springframework/boot/build/testing/TestFailuresPluginIntegrationTests.java @@ -166,6 +166,7 @@ class TestFailuresPluginIntegrationTests { writer.println("dependencies {"); writer.println(" testImplementation 'org.junit.jupiter:junit-jupiter:5.6.0'"); writer.println(" testImplementation 'org.assertj:assertj-core:3.11.1'"); + writer.println(" testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.6.0'"); writer.println("}"); writer.println(); writer.println("test {"); diff --git a/documentation/spring-boot-docs/build.gradle b/documentation/spring-boot-docs/build.gradle index 173bf28d381..1a4f4624fc1 100644 --- a/documentation/spring-boot-docs/build.gradle +++ b/documentation/spring-boot-docs/build.gradle @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask import org.springframework.boot.build.docs.ConfigureJavadocLinks +import org.springframework.boot.build.optional.OptionalDependenciesPlugin plugins { id "dev.adamko.dokkatoo-html" @@ -237,9 +238,48 @@ dokkatoo { moduleName.set("Spring Boot Kotlin API") } +configurations { + javadoc { + canBeConsumed = true + canBeResolved = false + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION)) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EMBEDDED)) + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, DocsType.JAVADOC)) + } + } + javadocSource { + transitive = false + canBeConsumed = false + canBeResolved = true + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.VERIFICATION)) + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, DocsType.SOURCES)) + attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, objects.named(VerificationType.class, VerificationType.MAIN_SOURCES)) + } + extendsFrom configurations.javadoc + } + javadocClasspath { + canBeConsumed = false + canBeResolved = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) + } + extendsFrom configurations.javadoc + resolutionStrategy.eachDependency { + if (it.requested.group == 'org.opensaml') { + it.useVersion '4.0.1' + } + } + } +} + def aggregatedJavadoc = tasks.register('aggregatedJavadoc', Javadoc) { dependsOn configurations.resolvedBom destinationDir = project.file(project.layout.buildDirectory.dir("docs/javadoc")) + source = configurations.javadocSource + classpath = configurations.javadocClasspath + include("**/*.java") options { author = true docTitle = "Spring Boot ${project.version} API" @@ -253,7 +293,7 @@ def aggregatedJavadoc = tasks.register('aggregatedJavadoc', Javadoc) { } project.rootProject.gradle.projectsEvaluated { - Set publishedProjects = rootProject.subprojects + rootProject.subprojects .findAll { it != project } .findAll { it.plugins.hasPlugin(JavaPlugin) && it.plugins.hasPlugin(MavenPublishPlugin) } .findAll { !it.path.contains(":build-plugin:") } @@ -262,11 +302,14 @@ project.rootProject.gradle.projectsEvaluated { .findAll { !it.path.contains(":core:spring-boot-properties-migrator") } .findAll { !it.path.contains(":loader:spring-boot-jarmode-tools") } .findAll { !it.name.startsWith('spring-boot-starter') } - aggregatedJavadoc.configure { - dependsOn publishedProjects.javadoc - source publishedProjects.javadoc.source - classpath = project.files(publishedProjects.javadoc.classpath) - } + .each { javadocProject -> + dependencies { + javadoc(project(javadocProject.path)) + if (javadocProject.plugins.hasPlugin(OptionalDependenciesPlugin)) { + javadoc(project(path: javadocProject.path, configuration: 'optional')) + } + } + } } aggregates { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baab..8bdaf60c75a 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 d4081da476b..2e1113280ef 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-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a93670..adff685a034 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee8452..e509b2dd8fe 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%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" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/integration-test/spring-boot-loader-integration-tests/spring-boot-loader-tests-signed-jar/build.gradle b/integration-test/spring-boot-loader-integration-tests/spring-boot-loader-tests-signed-jar/build.gradle index e97b8f18429..f474bec3988 100644 --- a/integration-test/spring-boot-loader-integration-tests/spring-boot-loader-tests-signed-jar/build.gradle +++ b/integration-test/spring-boot-loader-integration-tests/spring-boot-loader-tests-signed-jar/build.gradle @@ -43,7 +43,7 @@ tasks.register("bootJarUnpack", BootJar.class) { classpath = bootJar.classpath requiresUnpack '**/bcprov-jdk18on-*.jar' archiveClassifier.set("unpack") - targetJavaVersion = targetCompatibility + targetJavaVersion = java.targetCompatibility } build.dependsOn bootJarUnpack diff --git a/integration-test/spring-boot-server-integration-tests/spring-boot-server-tests-app/build.gradle b/integration-test/spring-boot-server-integration-tests/spring-boot-server-tests-app/build.gradle index 53f2da6af4b..28db4d64fa8 100644 --- a/integration-test/spring-boot-server-integration-tests/spring-boot-server-tests-app/build.gradle +++ b/integration-test/spring-boot-server-integration-tests/spring-boot-server-tests-app/build.gradle @@ -86,7 +86,7 @@ static boolean isWindows() { task.mainClass = "com.example.ResourceHandlingApplication" task.classpath = configurations.getByName(webServer) task.archiveClassifier = webServer - task.targetJavaVersion = project.getTargetCompatibility() + task.targetJavaVersion = java.targetCompatibility } tasks.register("${webServer}BootJar", BootJar, configurer) tasks.register("${webServer}BootWar", BootWar, configurer) diff --git a/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-reactive-app/build.gradle b/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-reactive-app/build.gradle index 5e92e1a245d..d69f630597c 100644 --- a/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-reactive-app/build.gradle +++ b/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-reactive-app/build.gradle @@ -62,7 +62,7 @@ dependencies { task.mainClass = "org.springframework.boot.sni.server.SniServerApplication" task.classpath = configurations.getByName(webServer) task.archiveClassifier = webServer - task.targetJavaVersion = project.getTargetCompatibility() + task.targetJavaVersion = project.java.targetCompatibility } tasks.register("${webServer}ServerApp", BootJar, configurer) } \ No newline at end of file diff --git a/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-servlet-app/build.gradle b/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-servlet-app/build.gradle index 67a0e190c09..7793bb00cac 100644 --- a/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-servlet-app/build.gradle +++ b/integration-test/spring-boot-sni-integration-tests/spring-boot-sni-servlet-app/build.gradle @@ -62,7 +62,7 @@ dependencies { task.mainClass = "org.springframework.boot.sni.server.SniServerApplication" task.classpath = configurations.getByName(webServer) task.archiveClassifier = webServer - task.targetJavaVersion = project.getTargetCompatibility() + task.targetJavaVersion = project.java.targetCompatibility } tasks.register("${webServer}ServerApp", BootJar, configurer) } \ No newline at end of file diff --git a/loader/spring-boot-jarmode-tools/build.gradle b/loader/spring-boot-jarmode-tools/build.gradle index 9abb00c8613..31a1d6ed72e 100644 --- a/loader/spring-boot-jarmode-tools/build.gradle +++ b/loader/spring-boot-jarmode-tools/build.gradle @@ -30,8 +30,3 @@ dependencies { testImplementation("org.mockito:mockito-core") testImplementation("org.mockito:mockito-junit-jupiter") } - -jar { - reproducibleFileOrder = true - preserveFileTimestamps = false -} diff --git a/loader/spring-boot-loader-tools/build.gradle b/loader/spring-boot-loader-tools/build.gradle index 159cf0502ac..eaf3703ebfd 100644 --- a/loader/spring-boot-loader-tools/build.gradle +++ b/loader/spring-boot-loader-tools/build.gradle @@ -50,7 +50,7 @@ dependencies { testImplementation("org.zeroturnaround:zt-zip:1.13") } -tasks.register("reproducibleLoaderJar", Jar) { +tasks.register("loaderJar", Jar) { dependsOn configurations.loader from { zipTree(configurations.loader.incoming.files.singleFile).matching { @@ -59,8 +59,6 @@ tasks.register("reproducibleLoaderJar", Jar) { exclude "META-INF/spring-boot.properties" } } - reproducibleFileOrder = true - preserveFileTimestamps = false archiveFileName = "spring-boot-loader.jar" destinationDirectory = file(generatedResources.map {it.dir("META-INF/loader") }) } @@ -76,7 +74,7 @@ tasks.register("toolsJar", Sync) { sourceSets { main { - output.dir(generatedResources, builtBy: [toolsJar, reproducibleLoaderJar]) + output.dir(generatedResources, builtBy: [toolsJar, loaderJar]) } } diff --git a/test-support/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java b/test-support/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java index 739d37777b7..8cb21807bef 100644 --- a/test-support/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java +++ b/test-support/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java @@ -36,7 +36,7 @@ public final class GradleVersions { if (isJavaVersion(JavaVersion.VERSION_25)) { return Arrays.asList("9.0.0", "9.1.0"); } - return Arrays.asList(GradleVersion.current().getVersion(), "9.0.0", "9.1.0"); + return Arrays.asList("8.14.3", "9.0.0", GradleVersion.current().getVersion()); } public static String minimumCompatible() {