Improve null-safety of loader/spring-boot-loader-tools

See gh-46926
This commit is contained in:
Moritz Halbritter 2025-08-18 14:44:22 +02:00
parent f5be18587c
commit 3a40b0a623
6 changed files with 21 additions and 7 deletions

View File

@ -224,6 +224,7 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
@Override @Override
public void writeLoaderClasses(String loaderJarResourceName) throws IOException { public void writeLoaderClasses(String loaderJarResourceName) throws IOException {
URL loaderJar = getClass().getClassLoader().getResource(loaderJarResourceName); URL loaderJar = getClass().getClassLoader().getResource(loaderJarResourceName);
Assert.state(loaderJar != null, "Unable to load resource '%s'".formatted(loaderJarResourceName));
try (JarInputStream inputStream = new JarInputStream(new BufferedInputStream(loaderJar.openStream()))) { try (JarInputStream inputStream = new JarInputStream(new BufferedInputStream(loaderJar.openStream()))) {
JarEntry entry; JarEntry entry;
while ((entry = inputStream.getNextJarEntry()) != null) { while ((entry = inputStream.getNextJarEntry()) != null) {

View File

@ -31,6 +31,8 @@ import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/** /**
* Default implementation of {@link LaunchScript}. Provides the default Spring Boot launch * Default implementation of {@link LaunchScript}. Provides the default Spring Boot launch
* script or can load a specific script File. Also support mustache style template * script or can load a specific script File. Also support mustache style template
@ -63,7 +65,9 @@ public class DefaultLaunchScript implements LaunchScript {
private String loadContent(@Nullable File file) throws IOException { private String loadContent(@Nullable File file) throws IOException {
if (file == null) { if (file == null) {
return loadContent(getClass().getResourceAsStream("launch.script")); InputStream stream = getClass().getResourceAsStream("launch.script");
Assert.state(stream != null, "Unable to load resource 'launch.script'");
return loadContent(stream);
} }
return loadContent(new FileInputStream(file)); return loadContent(new FileInputStream(file));
} }
@ -85,7 +89,7 @@ public class DefaultLaunchScript implements LaunchScript {
outputStream.flush(); outputStream.flush();
} }
private String expandPlaceholders(@Nullable String content, Map<?, ?> properties) throws IOException { private String expandPlaceholders(String content, @Nullable Map<?, ?> properties) throws IOException {
StringBuilder expanded = new StringBuilder(); StringBuilder expanded = new StringBuilder();
Matcher matcher = PLACEHOLDER_PATTERN.matcher(content); Matcher matcher = PLACEHOLDER_PATTERN.matcher(content);
while (matcher.find()) { while (matcher.find()) {

View File

@ -25,6 +25,8 @@ import java.util.jar.Manifest;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/** /**
* Utilities for manipulating files and directories in Spring Boot tooling. * Utilities for manipulating files and directories in Spring Boot tooling.
* *
@ -43,7 +45,9 @@ public abstract class FileUtils {
*/ */
public static void removeDuplicatesFromOutputDirectory(File outputDirectory, File originDirectory) { public static void removeDuplicatesFromOutputDirectory(File outputDirectory, File originDirectory) {
if (originDirectory.isDirectory()) { if (originDirectory.isDirectory()) {
for (String name : originDirectory.list()) { String[] files = originDirectory.list();
Assert.state(files != null, "'files' must not be null");
for (String name : files) {
File targetFile = new File(outputDirectory, name); File targetFile = new File(outputDirectory, name);
if (targetFile.exists() && targetFile.canWrite()) { if (targetFile.exists() && targetFile.canWrite()) {
if (!targetFile.isDirectory()) { if (!targetFile.isDirectory()) {

View File

@ -109,6 +109,7 @@ public class Library {
* @throws IOException on error * @throws IOException on error
*/ */
InputStream openStream() throws IOException { InputStream openStream() throws IOException {
Assert.state(this.file != null, "'file' must not be null");
return new FileInputStream(this.file); return new FileInputStream(this.file);
} }

View File

@ -154,7 +154,10 @@ public abstract class MainClassFinder {
return null; return null;
} }
private static void pushAllSorted(Deque<File> stack, File[] files) { private static void pushAllSorted(Deque<File> stack, File @Nullable [] files) {
if (files == null) {
return;
}
Arrays.sort(files, Comparator.comparing(File::getName)); Arrays.sort(files, Comparator.comparing(File::getName));
for (File file : files) { for (File file : files) {
stack.push(file); stack.push(file);

View File

@ -115,17 +115,18 @@ final class SizeCalculatingEntryWriter implements EntryWriter {
} }
private OutputStream convertToFileOutputStream(ByteArrayOutputStream byteArrayOutputStream) throws IOException { private OutputStream convertToFileOutputStream(ByteArrayOutputStream byteArrayOutputStream) throws IOException {
initializeTempFile(); File tempFile = initializeTempFile();
FileOutputStream fileOutputStream = new FileOutputStream(this.tempFile); FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
StreamUtils.copy(byteArrayOutputStream.toByteArray(), fileOutputStream); StreamUtils.copy(byteArrayOutputStream.toByteArray(), fileOutputStream);
return fileOutputStream; return fileOutputStream;
} }
private void initializeTempFile() throws IOException { private File initializeTempFile() throws IOException {
if (this.tempFile == null) { if (this.tempFile == null) {
this.tempFile = File.createTempFile("springboot-", "-entrycontent"); this.tempFile = File.createTempFile("springboot-", "-entrycontent");
this.tempFile.deleteOnExit(); this.tempFile.deleteOnExit();
} }
return this.tempFile;
} }
@Override @Override