Improve null-safety of buildpack/spring-boot-buildpack-platform

See gh-47263
This commit is contained in:
Moritz Halbritter
2025-10-16 10:45:12 +02:00
parent a5c8e2b703
commit c2286abdf9
9 changed files with 24 additions and 18 deletions
@@ -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("'");
@@ -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);
}
@@ -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<Buildpack> buildpacks) {
static Buildpacks of(@Nullable List<Buildpack> buildpacks) {
return CollectionUtils.isEmpty(buildpacks) ? EMPTY : new Buildpacks(buildpacks);
}
@@ -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<String, String> env,
BuilderMetadata builderMetadata, Creator creator, @Nullable Map<String, String> 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)) {
@@ -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<PullImageUpdateEvent> listener) throws IOException {
return pull(reference, platform, listener, null);
}
@@ -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<TotalProgressEvent> {
* @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)) {
@@ -49,7 +49,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
private final BiConsumer<String, Exception> credentialHelperExceptionHandler;
private final Function<String, CredentialHelper> credentialHelperFactory;
private final Function<String, @Nullable CredentialHelper> credentialHelperFactory;
private final DockerConfig dockerConfig;
@@ -61,7 +61,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
DockerRegistryConfigAuthentication(@Nullable DockerRegistryAuthentication fallback,
BiConsumer<String, Exception> credentialHelperExceptionHandler, Environment environment,
Function<String, CredentialHelper> credentialHelperFactory) {
Function<String, @Nullable CredentialHelper> credentialHelperFactory) {
this.fallback = fallback;
this.credentialHelperExceptionHandler = credentialHelperExceptionHandler;
this.dockerConfig = DockerConfigurationMetadata.from(environment).getConfiguration();
@@ -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);
@@ -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");