From c2286abdf9b23dc6a9a64126553454a1d278f07e Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Thu, 16 Oct 2025 10:45:12 +0200 Subject: [PATCH] Improve null-safety of buildpack/spring-boot-buildpack-platform See gh-47263 --- .../buildpack/platform/build/BuilderException.java | 10 ++++++---- .../buildpack/platform/build/BuildpackCoordinates.java | 2 +- .../boot/buildpack/platform/build/Buildpacks.java | 4 +++- .../buildpack/platform/build/EphemeralBuilder.java | 4 ++-- .../boot/buildpack/platform/docker/DockerApi.java | 2 +- .../buildpack/platform/docker/TotalProgressBar.java | 4 +++- .../DockerRegistryConfigAuthentication.java | 4 ++-- .../buildpack/platform/docker/ssl/KeyStoreFactory.java | 2 +- .../docker/transport/DockerEngineException.java | 10 +++++----- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderException.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderException.java index f0086282b36..94201397a8a 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderException.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderException.java @@ -16,6 +16,8 @@ package org.springframework.boot.buildpack.platform.build; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; /** @@ -26,11 +28,11 @@ import org.springframework.util.StringUtils; */ public class BuilderException extends RuntimeException { - private final String operation; + private final @Nullable String operation; private final int statusCode; - BuilderException(String operation, int statusCode) { + BuilderException(@Nullable String operation, int statusCode) { super(buildMessage(operation, statusCode)); this.operation = operation; this.statusCode = statusCode; @@ -40,7 +42,7 @@ public class BuilderException extends RuntimeException { * Return the Builder operation that failed. * @return the operation description */ - public String getOperation() { + public @Nullable String getOperation() { return this.operation; } @@ -52,7 +54,7 @@ public class BuilderException extends RuntimeException { return this.statusCode; } - private static String buildMessage(String operation, int statusCode) { + private static String buildMessage(@Nullable String operation, int statusCode) { StringBuilder message = new StringBuilder("Builder"); if (StringUtils.hasLength(operation)) { message.append(" lifecycle '").append(operation).append("'"); diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java index 210069e7ca1..d273d299e93 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildpackCoordinates.java @@ -134,7 +134,7 @@ final class BuildpackCoordinates { * @param version the buildpack version * @return a new {@link BuildpackCoordinates} instance */ - static BuildpackCoordinates of(String id, String version) { + static BuildpackCoordinates of(String id, @Nullable String version) { return new BuildpackCoordinates(id, version); } diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Buildpacks.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Buildpacks.java index 83591418072..6cd267fc009 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Buildpacks.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Buildpacks.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.util.Collections; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.buildpack.platform.docker.type.Layer; import org.springframework.boot.buildpack.platform.io.Content; import org.springframework.boot.buildpack.platform.io.IOConsumer; @@ -79,7 +81,7 @@ final class Buildpacks { builder.append("\n"); } - static Buildpacks of(List buildpacks) { + static Buildpacks of(@Nullable List buildpacks) { return CollectionUtils.isEmpty(buildpacks) ? EMPTY : new Buildpacks(buildpacks); } diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilder.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilder.java index 1c78bc3376e..92f48f0851d 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilder.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilder.java @@ -65,7 +65,7 @@ class EphemeralBuilder { * @param buildpacks an optional set of buildpacks to apply */ EphemeralBuilder(BuildOwner buildOwner, Image builderImage, ImageReference targetImage, - BuilderMetadata builderMetadata, Creator creator, Map env, + BuilderMetadata builderMetadata, Creator creator, @Nullable Map env, @Nullable Buildpacks buildpacks) { this.name = ImageReference.random("pack.local/builder/").inTaggedForm(); this.buildOwner = buildOwner; @@ -129,7 +129,7 @@ class EphemeralBuilder { * @return the ephemeral builder archive * @throws IOException on IO error */ - ImageArchive getArchive(String applicationDirectory) throws IOException { + ImageArchive getArchive(@Nullable String applicationDirectory) throws IOException { return ImageArchive.from(this.builderImage, (update) -> { this.archiveUpdate.accept(update); if (StringUtils.hasLength(applicationDirectory)) { diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java index 16d29c65e94..407d5f9298c 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java @@ -207,7 +207,7 @@ public class DockerApi { * @return the {@link ImageApi pulled image} instance * @throws IOException on IO error */ - public Image pull(ImageReference reference, ImagePlatform platform, + public Image pull(ImageReference reference, @Nullable ImagePlatform platform, UpdateListener listener) throws IOException { return pull(reference, platform, listener, null); } diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressBar.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressBar.java index 36793fc174c..39c4ee54a38 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressBar.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressBar.java @@ -19,6 +19,8 @@ package org.springframework.boot.buildpack.platform.docker; import java.io.PrintStream; import java.util.function.Consumer; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; /** @@ -62,7 +64,7 @@ public class TotalProgressBar implements Consumer { * @param bookend if bookends should be printed * @param out the output print stream to use */ - public TotalProgressBar(String prefix, char progressChar, boolean bookend, PrintStream out) { + public TotalProgressBar(@Nullable String prefix, char progressChar, boolean bookend, PrintStream out) { this.progressChar = progressChar; this.bookend = bookend; if (StringUtils.hasLength(prefix)) { diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java index e0bec2ba458..fb5c1f0c827 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java @@ -49,7 +49,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication private final BiConsumer credentialHelperExceptionHandler; - private final Function credentialHelperFactory; + private final Function credentialHelperFactory; private final DockerConfig dockerConfig; @@ -61,7 +61,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication DockerRegistryConfigAuthentication(@Nullable DockerRegistryAuthentication fallback, BiConsumer credentialHelperExceptionHandler, Environment environment, - Function credentialHelperFactory) { + Function credentialHelperFactory) { this.fallback = fallback; this.credentialHelperExceptionHandler = credentialHelperExceptionHandler; this.dockerConfig = DockerConfigurationMetadata.from(environment).getConfiguration(); diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/KeyStoreFactory.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/KeyStoreFactory.java index 69ac5e0a090..92439c5de9d 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/KeyStoreFactory.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/KeyStoreFactory.java @@ -50,7 +50,7 @@ final class KeyStoreFactory { * @param alias the alias to use for KeyStore entries * @return the {@code KeyStore} */ - static KeyStore create(Path certPath, Path keyPath, String alias) { + static KeyStore create(Path certPath, @Nullable Path keyPath, String alias) { try { KeyStore keyStore = getKeyStore(); String certificateText = Files.readString(certPath); diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java index d686a4dc742..346d398b995 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/DockerEngineException.java @@ -34,14 +34,14 @@ public class DockerEngineException extends RuntimeException { private final int statusCode; - private final String reasonPhrase; + private final @Nullable String reasonPhrase; private final @Nullable Errors errors; private final @Nullable Message responseMessage; - public DockerEngineException(String host, URI uri, int statusCode, String reasonPhrase, @Nullable Errors errors, - @Nullable Message responseMessage) { + public DockerEngineException(String host, URI uri, int statusCode, @Nullable String reasonPhrase, + @Nullable Errors errors, @Nullable Message responseMessage) { super(buildMessage(host, uri, statusCode, reasonPhrase, errors, responseMessage)); this.statusCode = statusCode; this.reasonPhrase = reasonPhrase; @@ -61,7 +61,7 @@ public class DockerEngineException extends RuntimeException { * Return the reason phrase returned by the Docker API. * @return the reasonPhrase */ - public String getReasonPhrase() { + public @Nullable String getReasonPhrase() { return this.reasonPhrase; } @@ -83,7 +83,7 @@ public class DockerEngineException extends RuntimeException { return this.responseMessage; } - private static String buildMessage(String host, URI uri, int statusCode, String reasonPhrase, + private static String buildMessage(String host, URI uri, int statusCode, @Nullable String reasonPhrase, @Nullable Errors errors, @Nullable Message responseMessage) { Assert.notNull(host, "'host' must not be null"); Assert.notNull(uri, "'uri' must not be null");