From e5a24bafc71dab4845e92354dd0e81adebc52ac9 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 2 Sep 2026 16:34:49 +0200 Subject: [PATCH] Polish "Add jarmode tools command to print the SBOM" See gh-51505 --- .../boot/jarmode/tools/SbomCommand.java | 15 ++++++++------- .../boot/jarmode/tools/SbomCommandTests.java | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/SbomCommand.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/SbomCommand.java index 8f6e55beea7..1568d9c8aca 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/SbomCommand.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/SbomCommand.java @@ -73,14 +73,15 @@ class SbomCommand extends Command { private String getSbomLocation(JarFile jarFile) throws IOException { Manifest manifest = jarFile.getManifest(); - if (manifest != null) { - String location = manifest.getMainAttributes().getValue(SBOM_LOCATION_ATTRIBUTE); - if (location != null) { - return location; - } + if (manifest == null) { + throw new JarModeErrorException("No manifest found in the jar"); } - throw new JarModeErrorException( - "No SBOM found in the jar; the manifest has no '%s' attribute".formatted(SBOM_LOCATION_ATTRIBUTE)); + String location = manifest.getMainAttributes().getValue(SBOM_LOCATION_ATTRIBUTE); + if (location == null) { + throw new JarModeErrorException( + "No SBOM found in the jar; the manifest has no '%s' attribute".formatted(SBOM_LOCATION_ATTRIBUTE)); + } + return location; } private void writeSbom(InputStream in, PrintStream out, Map options) throws IOException { diff --git a/loader/spring-boot-jarmode-tools/src/test/java/org/springframework/boot/jarmode/tools/SbomCommandTests.java b/loader/spring-boot-jarmode-tools/src/test/java/org/springframework/boot/jarmode/tools/SbomCommandTests.java index acb019072e2..8f18fe379e5 100644 --- a/loader/spring-boot-jarmode-tools/src/test/java/org/springframework/boot/jarmode/tools/SbomCommandTests.java +++ b/loader/spring-boot-jarmode-tools/src/test/java/org/springframework/boot/jarmode/tools/SbomCommandTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.jarmode.tools; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -24,6 +25,8 @@ import java.io.PrintStream; import java.nio.file.Files; import java.util.ArrayDeque; import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.junit.jupiter.api.Test; @@ -63,6 +66,13 @@ class SbomCommandTests extends AbstractJarModeTests { .withMessage("No SBOM found in the jar; the manifest has no 'Sbom-Location' attribute"); } + @Test + void shouldFailWhenManifestIsMissing() throws IOException { + File archive = createArchiveWithoutManifest(); + assertThatExceptionOfType(JarModeErrorException.class).isThrownBy(() -> run(archive)) + .withMessage("No manifest found in the jar"); + } + @Test void shouldFailWhenSbomEntryIsMissing() throws IOException { Manifest manifest = createManifest("Sbom-Location: " + SBOM_LOCATION); @@ -133,6 +143,15 @@ class SbomCommandTests extends AbstractJarModeTests { return createArchive(manifest, SBOM_LOCATION, SBOM_RESOURCE); } + private File createArchiveWithoutManifest() throws IOException { + File file = new File(this.tempDir, "no-manifest.jar"); + try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file))) { + zip.putNextEntry(new ZipEntry("some-file.txt")); + zip.closeEntry(); + } + return file; + } + private byte[] getResourceContent(String resource) throws IOException { try (InputStream stream = getClass().getResourceAsStream(resource)) { assertThat(stream).as("Resource '%s'", resource).isNotNull();