Browse Source

Improve null-safety of build-plugin/spring-boot-gradle-plugin

See gh-46926
pull/46973/head
Moritz Halbritter 4 months ago
parent
commit
2a907ba369
  1. 10
      build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java
  2. 21
      build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java
  3. 16
      build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java
  4. 11
      build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java
  5. 9
      build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LoaderZipEntries.java

10
build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java

@ -17,6 +17,7 @@ @@ -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; @@ -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 { @@ -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 { @@ -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)));

21
build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfoProperties.java

@ -48,7 +48,7 @@ public abstract class BuildInfoProperties implements Serializable { @@ -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 { @@ -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 { @@ -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 { @@ -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;
}

16
build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java

@ -41,6 +41,7 @@ import org.gradle.work.DisableCachingByDefault; @@ -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 { @@ -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;
}

11
build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java

@ -22,6 +22,7 @@ import java.io.IOException; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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);
});
}

9
build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LoaderZipEntries.java

@ -30,6 +30,7 @@ import org.gradle.api.file.FileTreeElement; @@ -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 { @@ -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 { @@ -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);

Loading…
Cancel
Save