mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-04 08:19:50 +00:00
Improve null-safety of build-plugin/spring-boot-gradle-plugin
See gh-46926
This commit is contained in:
+9
-1
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.gradle.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -38,6 +39,7 @@ import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator;
|
||||
import org.gradle.util.GradleVersion;
|
||||
|
||||
import org.springframework.boot.gradle.tasks.run.BootRun;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Action that is executed in response to the {@link ApplicationPlugin} being applied.
|
||||
@@ -110,7 +112,7 @@ final class ApplicationPluginAction implements PluginApplicationAction {
|
||||
}
|
||||
|
||||
private String loadResource(String name) {
|
||||
try (InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream(name))) {
|
||||
try (InputStreamReader reader = new InputStreamReader(getResourceAsStream(name))) {
|
||||
char[] buffer = new char[4096];
|
||||
int read;
|
||||
StringWriter writer = new StringWriter();
|
||||
@@ -124,6 +126,12 @@ final class ApplicationPluginAction implements PluginApplicationAction {
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getResourceAsStream(String name) {
|
||||
InputStream stream = getClass().getResourceAsStream(name);
|
||||
Assert.state(stream != null, "Resource '%s' not found'".formatted(name));
|
||||
return stream;
|
||||
}
|
||||
|
||||
private void configureFilePermissions(CopySpec copySpec, int mode) {
|
||||
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
|
||||
copySpec.filePermissions((filePermissions) -> filePermissions.unix(Integer.toString(mode, 8)));
|
||||
|
||||
+16
-5
@@ -48,7 +48,7 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||
|
||||
private final SetProperty<String> excludes;
|
||||
|
||||
private final Supplier<String> creationTime = () -> DateTimeFormatter.ISO_INSTANT.format(Instant.now());
|
||||
private final Supplier<@Nullable String> creationTime = () -> DateTimeFormatter.ISO_INSTANT.format(Instant.now());
|
||||
|
||||
@Inject
|
||||
public BuildInfoProperties(Project project, SetProperty<String> excludes) {
|
||||
@@ -142,15 +142,19 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||
return coerceToStringValues(applyExclusions(getAdditional().getOrElse(Collections.emptyMap())));
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name) {
|
||||
return getIfNotExcluded(property, name, () -> null);
|
||||
}
|
||||
|
||||
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name, Supplier<T> defaultValue) {
|
||||
private <T> @Nullable T getIfNotExcluded(Property<T> property, String name, Supplier<@Nullable T> defaultValue) {
|
||||
if (this.excludes.getOrElse(Collections.emptySet()).contains(name)) {
|
||||
return null;
|
||||
}
|
||||
return property.getOrElse(defaultValue.get());
|
||||
if (property.isPresent()) {
|
||||
return property.get();
|
||||
}
|
||||
return defaultValue.get();
|
||||
}
|
||||
|
||||
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
|
||||
@@ -159,7 +163,9 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||
if (value instanceof Provider<?> provider) {
|
||||
value = provider.getOrNull();
|
||||
}
|
||||
output.put(key, (value != null) ? value.toString() : null);
|
||||
if (value != null) {
|
||||
output.put(key, value.toString());
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}
|
||||
@@ -167,7 +173,12 @@ public abstract class BuildInfoProperties implements Serializable {
|
||||
private Map<String, Object> applyExclusions(Map<String, Object> input) {
|
||||
Map<String, Object> output = new HashMap<>();
|
||||
Set<String> exclusions = this.excludes.getOrElse(Collections.emptySet());
|
||||
input.forEach((key, value) -> output.put(key, (!exclusions.contains(key)) ? value : null));
|
||||
input.forEach((key, value) -> {
|
||||
boolean isExcluded = exclusions.contains(key);
|
||||
if (!isExcluded) {
|
||||
output.put(key, value);
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -41,6 +41,7 @@ import org.gradle.work.DisableCachingByDefault;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||
import org.springframework.boot.buildpack.platform.build.Builder;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||
import org.springframework.boot.buildpack.platform.build.Cache;
|
||||
import org.springframework.boot.buildpack.platform.build.Creator;
|
||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||
import org.springframework.boot.buildpack.platform.docker.transport.DockerEngineException;
|
||||
@@ -460,14 +461,17 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||
}
|
||||
|
||||
private BuildRequest customizeCaches(BuildRequest request) {
|
||||
if (this.buildWorkspace.asCache() != null) {
|
||||
request = request.withBuildWorkspace((this.buildWorkspace.asCache()));
|
||||
Cache buildWorkspaceCache = this.buildWorkspace.asCache();
|
||||
if (buildWorkspaceCache != null) {
|
||||
request = request.withBuildWorkspace(buildWorkspaceCache);
|
||||
}
|
||||
if (this.buildCache.asCache() != null) {
|
||||
request = request.withBuildCache(this.buildCache.asCache());
|
||||
Cache buildCache = this.buildCache.asCache();
|
||||
if (buildCache != null) {
|
||||
request = request.withBuildCache(buildCache);
|
||||
}
|
||||
if (this.launchCache.asCache() != null) {
|
||||
request = request.withLaunchCache(this.launchCache.asCache());
|
||||
Cache launchCache = this.launchCache.asCache();
|
||||
if (launchCache != null) {
|
||||
request = request.withLaunchCache(launchCache);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
+7
-4
@@ -22,6 +22,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.OffsetDateTime;
|
||||
@@ -111,7 +112,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
|
||||
private final Function<FileCopyDetails, ZipCompression> compressionResolver;
|
||||
|
||||
private final String encoding;
|
||||
private final @Nullable String encoding;
|
||||
|
||||
private final ResolvedDependencies resolvedDependencies;
|
||||
|
||||
@@ -125,7 +126,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
@Nullable Integer fileMode, boolean includeDefaultLoader, @Nullable String jarmodeToolsLocation,
|
||||
Spec<FileTreeElement> requiresUnpack, Spec<FileTreeElement> exclusions,
|
||||
@Nullable LaunchScriptConfiguration launchScript, Spec<FileCopyDetails> librarySpec,
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver, String encoding,
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver, @Nullable String encoding,
|
||||
ResolvedDependencies resolvedDependencies, boolean supportsSignatureFile,
|
||||
@Nullable LayerResolver layerResolver, LoaderImplementation loaderImplementation) {
|
||||
this.output = output;
|
||||
@@ -390,7 +391,8 @@ class BootZipCopyAction implements CopyAction {
|
||||
if (classPathIndex != null) {
|
||||
Set<String> libraryNames = this.writtenLibraries.keySet();
|
||||
List<String> lines = libraryNames.stream().map((line) -> "- \"" + line + "\"").toList();
|
||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines(BootZipCopyAction.this.encoding, lines);
|
||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines((BootZipCopyAction.this.encoding != null)
|
||||
? BootZipCopyAction.this.encoding : StandardCharsets.UTF_8.name(), lines);
|
||||
writeEntry(classPathIndex, writer, true);
|
||||
}
|
||||
}
|
||||
@@ -415,7 +417,8 @@ class BootZipCopyAction implements CopyAction {
|
||||
}
|
||||
NativeImageArgFile argFile = new NativeImageArgFile(excludes);
|
||||
argFile.writeIfNecessary((lines) -> {
|
||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines(BootZipCopyAction.this.encoding, lines);
|
||||
ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines((BootZipCopyAction.this.encoding != null)
|
||||
? BootZipCopyAction.this.encoding : StandardCharsets.UTF_8.name(), lines);
|
||||
writeEntry(NativeImageArgFile.LOCATION, writer, true);
|
||||
});
|
||||
}
|
||||
|
||||
+8
-1
@@ -30,6 +30,7 @@ import org.gradle.api.file.FileTreeElement;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.loader.tools.LoaderImplementation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
@@ -61,7 +62,7 @@ class LoaderZipEntries {
|
||||
WrittenEntries writeTo(ZipArchiveOutputStream out) throws IOException {
|
||||
WrittenEntries written = new WrittenEntries();
|
||||
try (ZipInputStream loaderJar = new ZipInputStream(
|
||||
getClass().getResourceAsStream("/" + this.loaderImplementation.getJarResourceName()))) {
|
||||
getResourceAsStream("/" + this.loaderImplementation.getJarResourceName()))) {
|
||||
java.util.zip.ZipEntry entry = loaderJar.getNextEntry();
|
||||
while (entry != null) {
|
||||
if (entry.isDirectory() && !entry.getName().equals("META-INF/")) {
|
||||
@@ -78,6 +79,12 @@ class LoaderZipEntries {
|
||||
return written;
|
||||
}
|
||||
|
||||
private InputStream getResourceAsStream(String name) {
|
||||
InputStream stream = getClass().getResourceAsStream(name);
|
||||
Assert.state(stream != null, "Resource '%s not found'".formatted(name));
|
||||
return stream;
|
||||
}
|
||||
|
||||
private void writeDirectory(ZipArchiveEntry entry, ZipArchiveOutputStream out) throws IOException {
|
||||
prepareEntry(entry, this.dirMode);
|
||||
out.putArchiveEntry(entry);
|
||||
|
||||
Reference in New Issue
Block a user