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 241eb571260..396c46faa9b 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 @@ -122,13 +122,12 @@ class BootArchiveSupport { } CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies, - LoaderImplementation loaderImplementation, boolean supportsSignatureFile) { - return createCopyAction(jar, resolvedDependencies, loaderImplementation, supportsSignatureFile, null, null); + LoaderImplementation loaderImplementation) { + return createCopyAction(jar, resolvedDependencies, loaderImplementation, null, null); } CopyAction createCopyAction(Jar jar, ResolvedDependencies resolvedDependencies, - LoaderImplementation loaderImplementation, boolean supportsSignatureFile, LayerResolver layerResolver, - String jarmodeToolsLocation) { + LoaderImplementation loaderImplementation, LayerResolver layerResolver, String jarmodeToolsLocation) { File output = jar.getArchiveFile().get().getAsFile(); Manifest manifest = jar.getManifest(); boolean preserveFileTimestamps = jar.isPreserveFileTimestamps(); @@ -143,8 +142,7 @@ class BootArchiveSupport { String encoding = jar.getMetadataCharset(); CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirPermissions, filePermissions, includeDefaultLoader, jarmodeToolsLocation, requiresUnpack, exclusions, launchScript, - librarySpec, compressionResolver, encoding, resolvedDependencies, supportsSignatureFile, layerResolver, - loaderImplementation); + librarySpec, compressionResolver, encoding, resolvedDependencies, layerResolver, loaderImplementation); return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java index 137f2b8c643..ee30378d7f5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java @@ -150,7 +150,7 @@ public abstract class BootJar extends Jar implements BootArchive { layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary); } String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null; - return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, true, layerResolver, + return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, layerResolver, jarmodeToolsLocation); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java index 67a86d5ccea..148ab6126d7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java @@ -124,8 +124,8 @@ public abstract class BootWar extends War implements BootArchive { layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary); } String jarmodeToolsLocation = isIncludeJarmodeTools() ? LIB_DIRECTORY : null; - return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, false, - layerResolver, jarmodeToolsLocation); + return this.support.createCopyAction(this, this.resolvedDependencies, loaderImplementation, layerResolver, + jarmodeToolsLocation); } private boolean isIncludeJarmodeTools() { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java index e891fea3fa3..0eb16258fb7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java @@ -114,8 +114,6 @@ class BootZipCopyAction implements CopyAction { private final ResolvedDependencies resolvedDependencies; - private final boolean supportsSignatureFile; - private final LayerResolver layerResolver; private final LoaderImplementation loaderImplementation; @@ -124,7 +122,7 @@ class BootZipCopyAction implements CopyAction { boolean includeDefaultLoader, String jarmodeToolsLocation, Spec requiresUnpack, Spec exclusions, LaunchScriptConfiguration launchScript, Spec librarySpec, Function compressionResolver, String encoding, - ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile, LayerResolver layerResolver, + ResolvedDependencies resolvedDependencies, LayerResolver layerResolver, LoaderImplementation loaderImplementation) { this.output = output; this.manifest = manifest; @@ -140,7 +138,6 @@ class BootZipCopyAction implements CopyAction { this.compressionResolver = compressionResolver; this.encoding = encoding; this.resolvedDependencies = resolvedDependencies; - this.supportsSignatureFile = supportsSignatureFile; this.layerResolver = layerResolver; this.loaderImplementation = loaderImplementation; } @@ -363,7 +360,7 @@ class BootZipCopyAction implements CopyAction { } private void writeSignatureFileIfNecessary() throws IOException { - if (BootZipCopyAction.this.supportsSignatureFile && hasSignedLibrary()) { + if (hasSignedLibrary()) { writeEntry("META-INF/BOOT.SF", (out) -> { }, false); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java index 3a379b6364e..91756198915 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java @@ -49,6 +49,7 @@ import org.apache.commons.compress.archivers.zip.UnixStat; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.BuildTask; import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.TestTemplate; @@ -647,6 +648,17 @@ abstract class AbstractBootArchiveIntegrationTests { } } + @TestTemplate + void signed() throws IOException { + BuildTask task = this.gradleBuild.build(this.taskName).task(":" + this.taskName); + assertThat(task).isNotNull(); + assertThat(task.getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + File jar = new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0]; + try (JarFile jarFile = new JarFile(jar)) { + assertThat(jarFile.getEntry("META-INF/BOOT.SF")).isNotNull(); + } + } + private void copyMainClassApplication() throws IOException { copyApplication("main"); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java index e8c2269177f..b19754fc664 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java @@ -16,15 +16,12 @@ package org.springframework.boot.gradle.tasks.bundling; -import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Set; import java.util.TreeSet; -import java.util.jar.JarFile; import org.gradle.testkit.runner.BuildResult; -import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.TestTemplate; @@ -46,15 +43,6 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { super("bootJar", "BOOT-INF/lib/", "BOOT-INF/classes/", "BOOT-INF/"); } - @TestTemplate - void signed() throws Exception { - assertThat(this.gradleBuild.build("bootJar").task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); - File jar = new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0]; - try (JarFile jarFile = new JarFile(jar)) { - assertThat(jarFile.getEntry("META-INF/BOOT.SF")).isNotNull(); - } - } - @TestTemplate void whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds() { Assumptions.assumeTrue(this.gradleBuild.gradleVersionIsLessThan("9.0-milestone-1")); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-signed.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-signed.gradle new file mode 100644 index 00000000000..c1c9216e0d5 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-signed.gradle @@ -0,0 +1,36 @@ +/* + * Copyright 2012-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'war' + id 'java' + id 'org.springframework.boot' version '{version}' +} + +bootWar { + mainClass = 'com.example.Application' +} + +repositories { + mavenCentral() + maven { + url = 'repository' + } +} + +dependencies { + implementation("org.bouncycastle:bcprov-jdk18on:1.78.1") +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java index bd12f6fe060..49cb0d365c6 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java @@ -51,7 +51,8 @@ public class Repackager extends Packager { @Override protected void writeSignatureFileIfNecessary(Map writtenLibraries, AbstractJarWriter writer) throws IOException { - if (getSource().getName().toLowerCase(Locale.ROOT).endsWith(".jar") && hasSignedLibrary(writtenLibraries)) { + String sourceName = getSource().getName().toLowerCase(Locale.ROOT); + if ((sourceName.endsWith(".jar") || sourceName.endsWith(".war")) && hasSignedLibrary(writtenLibraries)) { writer.writeEntry("META-INF/BOOT.SF", (entryWriter) -> { }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java index ce19c944a74..ca528506e00 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java @@ -240,4 +240,12 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests { }); } + @TestTemplate + void whenSigned(MavenBuild mavenBuild) { + mavenBuild.project("war-signed").execute((project) -> { + File repackaged = new File(project, "target/war-signed-0.0.1.BUILD-SNAPSHOT.war"); + assertThat(jar(repackaged)).hasEntryWithName("META-INF/BOOT.SF"); + }); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/pom.xml new file mode 100644 index 00000000000..551c164846d --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + org.springframework.boot.maven.it + war-signed + 0.0.1.BUILD-SNAPSHOT + war + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + @maven-war-plugin.version@ + + + + some.random.Main + + + Foo + + + + + + + + + org.springframework + spring-context + @spring-framework.version@ + + + jakarta.servlet + jakarta.servlet-api + @jakarta-servlet.version@ + provided + + + org.bouncycastle + bcprov-jdk18on + 1.78.1 + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..547d0cf0171 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/war-signed/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,24 @@ +/* + * Copyright 2012-present 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + } + +}