diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java index 7b37eac1a02..cf7f1de8226 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildOwner.java @@ -18,6 +18,8 @@ package org.springframework.boot.buildpack.platform.build; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.buildpack.platform.io.Owner; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -38,7 +40,7 @@ class BuildOwner implements Owner { private final long gid; - BuildOwner(Map env) { + BuildOwner(Map env) { this.uid = getValue(env, USER_PROPERTY_NAME); this.gid = getValue(env, GROUP_PROPERTY_NAME); } @@ -48,7 +50,7 @@ class BuildOwner implements Owner { this.gid = gid; } - private long getValue(Map env, String name) { + private long getValue(Map env, String name) { String value = env.get(name); Assert.state(StringUtils.hasText(value), () -> "Missing '" + name + "' value from the builder environment '" + env + "'"); @@ -83,7 +85,7 @@ class BuildOwner implements Owner { * @return a {@link BuildOwner} instance extracted from the env * @throws IllegalStateException if the env does not contain the correct CNB variables */ - static BuildOwner fromEnv(Map env) { + static BuildOwner fromEnv(Map env) { Assert.notNull(env, "'env' must not be null"); return new BuildOwner(env); } 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 91373ccb9ae..210069e7ca1 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 @@ -106,15 +106,15 @@ final class BuildpackCoordinates { private static BuildpackCoordinates fromToml(TomlParseResult toml, Path path) { Assert.isTrue(!toml.isEmpty(), () -> "Buildpack descriptor 'buildpack.toml' is required in buildpack '" + path + "'"); - Assert.hasText(toml.getString("buildpack.id"), - () -> "Buildpack descriptor must contain ID in buildpack '" + path + "'"); + String buildpackId = toml.getString("buildpack.id"); + Assert.hasText(buildpackId, () -> "Buildpack descriptor must contain ID in buildpack '" + path + "'"); Assert.hasText(toml.getString("buildpack.version"), () -> "Buildpack descriptor must contain version in buildpack '" + path + "'"); Assert.isTrue(toml.contains("stacks") || toml.contains("order"), () -> "Buildpack descriptor must contain either 'stacks' or 'order' in buildpack '" + path + "'"); Assert.isTrue(!(toml.contains("stacks") && toml.contains("order")), () -> "Buildpack descriptor must not contain both 'stacks' and 'order' in buildpack '" + path + "'"); - return new BuildpackCoordinates(toml.getString("buildpack.id"), toml.getString("buildpack.version")); + return new BuildpackCoordinates(buildpackId, toml.getString("buildpack.version")); } /** 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 6717f207bbd..6e4ac7111ae 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 @@ -160,10 +160,12 @@ public class DockerApi { } private ApiVersion getApiVersion() { - if (this.apiVersion == null) { - this.apiVersion = this.system.getApiVersion(); + ApiVersion apiVersion = this.apiVersion; + if (apiVersion == null) { + apiVersion = this.system.getApiVersion(); + this.apiVersion = apiVersion; } - return this.apiVersion; + return apiVersion; } /** diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java index 1419abb1575..49ad78b66a4 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListener.java @@ -105,6 +105,9 @@ public abstract class TotalProgressListener void update(ImageProgressUpdateEvent event) { String status = event.getStatus(); + if (status == null) { + return; + } if (event.getProgressDetail() != null && this.progressByStatus.containsKey(status)) { int current = this.progressByStatus.get(status); this.progressByStatus.put(status, updateProgress(current, event.getProgressDetail())); diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java index 26501ddc374..44c8e5c9c49 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java @@ -89,7 +89,7 @@ final class DockerConfigurationMetadata { return this.context; } - DockerContext forContext(String context) { + DockerContext forContext(@Nullable String context) { return createDockerContext(this.configLocation, context); } @@ -129,8 +129,9 @@ final class DockerConfigurationMetadata { if (currentContext == null || DEFAULT_CONTEXT.equals(currentContext)) { return DockerContext.empty(); } - Path metaPath = Path.of(configLocation, CONTEXTS_DIR, META_DIR, asHash(currentContext), CONTEXT_FILE_NAME); - Path tlsPath = Path.of(configLocation, CONTEXTS_DIR, TLS_DIR, asHash(currentContext), DOCKER_ENDPOINT); + String hash = asHash(currentContext); + Path metaPath = Path.of(configLocation, CONTEXTS_DIR, META_DIR, hash, CONTEXT_FILE_NAME); + Path tlsPath = Path.of(configLocation, CONTEXTS_DIR, TLS_DIR, hash, DOCKER_ENDPOINT); if (!metaPath.toFile().exists()) { throw new IllegalArgumentException("Docker context '" + currentContext + "' does not exist"); } @@ -146,14 +147,14 @@ final class DockerConfigurationMetadata { } } - private static @Nullable String asHash(String currentContext) { + private static String asHash(String currentContext) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(currentContext.getBytes(StandardCharsets.UTF_8)); return HexFormat.of().formatHex(hash); } catch (NoSuchAlgorithmException ex) { - return null; + throw new IllegalStateException("SHA-256 is not available", ex); } } diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java index 9ce00408092..bf4d403f931 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PemPrivateKeyParser.java @@ -115,11 +115,11 @@ final class PemPrivateKeyParser { private PemPrivateKeyParser() { } - private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, @Nullable String password) { return createKeySpecForAlgorithm(bytes, RSA_ALGORITHM, null); } - private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, @Nullable String password) { DerElement ecPrivateKey = DerElement.of(bytes); Assert.state(ecPrivateKey != null, "Unable to find private key"); Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE), @@ -164,7 +164,7 @@ final class PemPrivateKeyParser { } } - private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, @Nullable String password) { DerElement ecPrivateKey = DerElement.of(bytes); Assert.state(ecPrivateKey != null, "Unable to find private key"); Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE), @@ -182,7 +182,7 @@ final class PemPrivateKeyParser { return (algorithmName != null) ? new PKCS8EncodedKeySpec(bytes, algorithmName) : new PKCS8EncodedKeySpec(bytes); } - private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, @Nullable String password) { return Pkcs8PrivateKeyDecryptor.decrypt(bytes, password); } diff --git a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java index 515fcda248e..bfb1d34ab79 100644 --- a/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java +++ b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageConfig.java @@ -24,6 +24,7 @@ import java.util.function.Consumer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.jspecify.annotations.Nullable; import org.springframework.boot.buildpack.platform.json.MappedObject; @@ -38,7 +39,7 @@ public class ImageConfig extends MappedObject { private final Map labels; - private final Map configEnv; + private final Map configEnv; ImageConfig(JsonNode node) { super(node, MethodHandles.lookup()); @@ -55,12 +56,12 @@ public class ImageConfig extends MappedObject { return labels; } - private Map parseConfigEnv() { + private Map parseConfigEnv() { String[] entries = valueAt("/Env", String[].class); if (entries == null) { return Collections.emptyMap(); } - Map env = new LinkedHashMap<>(); + Map env = new LinkedHashMap<>(); for (String entry : entries) { int i = entry.indexOf('='); String name = (i != -1) ? entry.substring(0, i) : entry; @@ -88,7 +89,7 @@ public class ImageConfig extends MappedObject { * an empty {@code Map} is returned. * @return the env, never {@code null} */ - public Map getEnv() { + public Map getEnv() { return this.configEnv; } diff --git a/core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java b/core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java index 5a3a9baaeee..062075484c7 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java @@ -115,11 +115,11 @@ final class PemPrivateKeyParser { private PemPrivateKeyParser() { } - private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs1Rsa(byte[] bytes, @Nullable String password) { return createKeySpecForAlgorithm(bytes, RSA_ALGORITHM, null); } - private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForSec1Ec(byte[] bytes, @Nullable String password) { DerElement ecPrivateKey = DerElement.of(bytes); Assert.state(ecPrivateKey != null, "Unable to find private key"); Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE), @@ -164,7 +164,7 @@ final class PemPrivateKeyParser { } } - private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, @Nullable String password) { DerElement ecPrivateKey = DerElement.of(bytes); Assert.state(ecPrivateKey != null, "Unable to find private key"); Assert.state(ecPrivateKey.isType(ValueType.ENCODED, TagType.SEQUENCE), @@ -182,7 +182,7 @@ final class PemPrivateKeyParser { return (algorithmName != null) ? new PKCS8EncodedKeySpec(bytes, algorithmName) : new PKCS8EncodedKeySpec(bytes); } - private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, String password) { + private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, @Nullable String password) { return Pkcs8PrivateKeyDecryptor.decrypt(bytes, password); }