Skip to content

Commit 8d853fa

Browse files
committed
Add nullability annotations to loader/spring-boot-loader-tools
See gh-46587
1 parent d1d35d0 commit 8d853fa

File tree

22 files changed

+190
-125
lines changed

22 files changed

+190
-125
lines changed

documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/buildtoolplugins/otherbuildsystems/examplerepackageimplementation/MyBuildTool.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class MyBuildTool {
2727

2828
@Throws(IOException::class)
2929
fun build() {
30-
val sourceJarFile: File? = /**/null
30+
val sourceJarFile: File = /**/File(".")
3131
val repackager = Repackager(sourceJarFile)
3232
repackager.setBackupSource(false)
3333
repackager.repackage { callback: LibraryCallback -> getLibraries(callback) }
@@ -36,14 +36,14 @@ class MyBuildTool {
3636
@Throws(IOException::class)
3737
private fun getLibraries(callback: LibraryCallback) {
3838
// Build system specific implementation, callback for each dependency
39-
for (nestedJar in getCompileScopeJars()!!) {
39+
for (nestedJar in getCompileScopeJars()) {
4040
callback.library(Library(nestedJar, LibraryScope.COMPILE))
4141
}
4242
// ...
4343
}
4444

45-
private fun getCompileScopeJars(): List<File?>? {
46-
return /**/ null
45+
private fun getCompileScopeJars(): List<File> {
46+
return /**/ listOf()
4747
}
4848

4949
}

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AbstractJarWriter.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
import org.apache.commons.compress.archivers.jar.JarArchiveEntry;
4343
import org.apache.commons.compress.archivers.zip.UnixStat;
4444
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
45+
import org.jspecify.annotations.Nullable;
46+
47+
import org.springframework.util.Assert;
4548

4649
/**
4750
* Abstract base class for JAR writers.
@@ -61,16 +64,16 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
6164

6265
private final Set<String> writtenEntries = new HashSet<>();
6366

64-
private Layers layers;
67+
private @Nullable Layers layers;
6568

66-
private LayersIndex layersIndex;
69+
private @Nullable LayersIndex layersIndex;
6770

6871
/**
6972
* Update this writer to use specific layers.
7073
* @param layers the layers to use
7174
* @param layersIndex the layers index to update
7275
*/
73-
void useLayers(Layers layers, LayersIndex layersIndex) {
76+
void useLayers(@Nullable Layers layers, @Nullable LayersIndex layersIndex) {
7477
this.layers = layers;
7578
this.layersIndex = layersIndex;
7679
}
@@ -86,7 +89,7 @@ public void writeManifest(Manifest manifest) throws IOException {
8689
}
8790

8891
final void writeEntries(JarFile jarFile, EntryTransformer entryTransformer, UnpackHandler unpackHandler,
89-
Function<JarEntry, Library> libraryLookup) throws IOException {
92+
Function<JarEntry, @Nullable Library> libraryLookup) throws IOException {
9093
Enumeration<JarEntry> entries = jarFile.entries();
9194
while (entries.hasMoreElements()) {
9295
JarEntry entry = entries.nextElement();
@@ -98,7 +101,7 @@ final void writeEntries(JarFile jarFile, EntryTransformer entryTransformer, Unpa
98101
}
99102

100103
private void writeEntry(JarFile jarFile, EntryTransformer entryTransformer, UnpackHandler unpackHandler,
101-
JarArchiveEntry entry, Library library) throws IOException {
104+
JarArchiveEntry entry, @Nullable Library library) throws IOException {
102105
setUpEntry(jarFile, entry, unpackHandler);
103106
try (ZipHeaderPeekInputStream inputStream = new ZipHeaderPeekInputStream(jarFile.getInputStream(entry))) {
104107
EntryWriter entryWriter = new InputStreamEntryWriter(inputStream);
@@ -168,7 +171,7 @@ public void writeNestedLibrary(String location, Library library) throws IOExcept
168171
* @throws IOException if the write fails
169172
* @since 2.3.0
170173
*/
171-
public void writeIndexFile(String location, Collection<String> lines) throws IOException {
174+
public void writeIndexFile(@Nullable String location, Collection<String> lines) throws IOException {
172175
if (location != null) {
173176
JarArchiveEntry entry = new JarArchiveEntry(location);
174177
writeEntry(entry, (outputStream) -> {
@@ -207,7 +210,7 @@ public void writeLoaderClasses() throws IOException {
207210
}
208211

209212
@Override
210-
public void writeLoaderClasses(LoaderImplementation loaderImplementation) throws IOException {
213+
public void writeLoaderClasses(@Nullable LoaderImplementation loaderImplementation) throws IOException {
211214
writeLoaderClasses((loaderImplementation != null) ? loaderImplementation.getJarResourceName()
212215
: LoaderImplementation.DEFAULT.getJarResourceName());
213216
}
@@ -255,29 +258,31 @@ private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter) throws I
255258
* @param entryWriter the entry writer or {@code null} if there is no content
256259
* @throws IOException in case of I/O errors
257260
*/
258-
private void writeEntry(JarArchiveEntry entry, Library library, EntryWriter entryWriter) throws IOException {
261+
private void writeEntry(JarArchiveEntry entry, @Nullable Library library, @Nullable EntryWriter entryWriter)
262+
throws IOException {
259263
String name = entry.getName();
260264
if (this.writtenEntries.add(name)) {
261265
writeParentDirectoryEntries(name);
262266
entry.setUnixMode(name.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
263267
entry.getGeneralPurposeBit().useUTF8ForNames(true);
264268
if (!entry.isDirectory() && entry.getSize() == -1) {
265269
entryWriter = SizeCalculatingEntryWriter.get(entryWriter);
270+
Assert.state(entryWriter != null, "'entryWriter' must not be null");
266271
entry.setSize(entryWriter.size());
267272
}
268273
updateLayerIndex(entry, library);
269274
writeToArchive(entry, entryWriter);
270275
}
271276
}
272277

273-
private void updateLayerIndex(JarArchiveEntry entry, Library library) {
274-
if (this.layers != null && !entry.getName().endsWith("/")) {
278+
private void updateLayerIndex(JarArchiveEntry entry, @Nullable Library library) {
279+
if (this.layers != null && this.layersIndex != null && !entry.getName().endsWith("/")) {
275280
Layer layer = (library != null) ? this.layers.getLayer(library) : this.layers.getLayer(entry.getName());
276281
this.layersIndex.add(layer, entry.getName());
277282
}
278283
}
279284

280-
protected abstract void writeToArchive(ZipEntry entry, EntryWriter entryWriter) throws IOException;
285+
protected abstract void writeToArchive(ZipEntry entry, @Nullable EntryWriter entryWriter) throws IOException;
281286

282287
private void writeParentDirectoryEntries(String name) throws IOException {
283288
String parent = name.endsWith("/") ? name.substring(0, name.length() - 1) : name;
@@ -320,7 +325,7 @@ private static class StoredEntryPreparator {
320325

321326
private static final int BUFFER_SIZE = 32 * 1024;
322327

323-
private final MessageDigest messageDigest;
328+
private final @Nullable MessageDigest messageDigest;
324329

325330
private final CRC32 crc = new CRC32();
326331

@@ -378,7 +383,7 @@ interface EntryTransformer {
378383
*/
379384
EntryTransformer NONE = (jarEntry) -> jarEntry;
380385

381-
JarArchiveEntry transform(JarArchiveEntry jarEntry);
386+
@Nullable JarArchiveEntry transform(JarArchiveEntry jarEntry);
382387

383388
}
384389

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/BuildPropertiesWriter.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.Map;
2525
import java.util.Properties;
2626

27+
import org.jspecify.annotations.Nullable;
28+
2729
import org.springframework.core.CollectionFactory;
2830
import org.springframework.util.StringUtils;
2931

@@ -86,7 +88,7 @@ protected Properties createBuildInfo(ProjectDetails project) {
8688
return properties;
8789
}
8890

89-
private void addIfHasValue(Properties properties, String name, String value) {
91+
private void addIfHasValue(Properties properties, String name, @Nullable String value) {
9092
if (StringUtils.hasText(value)) {
9193
properties.put(name, value);
9294
}
@@ -97,20 +99,20 @@ private void addIfHasValue(Properties properties, String name, String value) {
9799
*/
98100
public static final class ProjectDetails {
99101

100-
private final String group;
102+
private final @Nullable String group;
101103

102-
private final String artifact;
104+
private final @Nullable String artifact;
103105

104-
private final String name;
106+
private final @Nullable String name;
105107

106-
private final String version;
108+
private final @Nullable String version;
107109

108-
private final Instant time;
110+
private final @Nullable Instant time;
109111

110-
private final Map<String, String> additionalProperties;
112+
private final @Nullable Map<String, String> additionalProperties;
111113

112-
public ProjectDetails(String group, String artifact, String version, String name, Instant time,
113-
Map<String, String> additionalProperties) {
114+
public ProjectDetails(@Nullable String group, @Nullable String artifact, @Nullable String version,
115+
@Nullable String name, @Nullable Instant time, @Nullable Map<String, String> additionalProperties) {
114116
this.group = group;
115117
this.artifact = artifact;
116118
this.name = name;
@@ -120,7 +122,7 @@ public ProjectDetails(String group, String artifact, String version, String name
120122
this.additionalProperties = additionalProperties;
121123
}
122124

123-
private static void validateAdditionalProperties(Map<String, String> additionalProperties) {
125+
private static void validateAdditionalProperties(@Nullable Map<String, String> additionalProperties) {
124126
if (additionalProperties != null) {
125127
additionalProperties.forEach((name, value) -> {
126128
if (value == null) {
@@ -130,27 +132,27 @@ private static void validateAdditionalProperties(Map<String, String> additionalP
130132
}
131133
}
132134

133-
public String getGroup() {
135+
public @Nullable String getGroup() {
134136
return this.group;
135137
}
136138

137-
public String getArtifact() {
139+
public @Nullable String getArtifact() {
138140
return this.artifact;
139141
}
140142

141-
public String getName() {
143+
public @Nullable String getName() {
142144
return this.name;
143145
}
144146

145-
public String getVersion() {
147+
public @Nullable String getVersion() {
146148
return this.version;
147149
}
148150

149-
public Instant getTime() {
151+
public @Nullable Instant getTime() {
150152
return this.time;
151153
}
152154

153-
public Map<String, String> getAdditionalProperties() {
155+
public @Nullable Map<String, String> getAdditionalProperties() {
154156
return this.additionalProperties;
155157
}
156158

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/DefaultLaunchScript.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.regex.Matcher;
3030
import java.util.regex.Pattern;
3131

32+
import org.jspecify.annotations.Nullable;
33+
3234
/**
3335
* Default implementation of {@link LaunchScript}. Provides the default Spring Boot launch
3436
* script or can load a specific script File. Also support mustache style template
@@ -54,12 +56,12 @@ public class DefaultLaunchScript implements LaunchScript {
5456
* @param properties an optional set of script properties used for variable expansion
5557
* @throws IOException if the script cannot be loaded
5658
*/
57-
public DefaultLaunchScript(File file, Map<?, ?> properties) throws IOException {
59+
public DefaultLaunchScript(@Nullable File file, Map<?, ?> properties) throws IOException {
5860
String content = loadContent(file);
5961
this.content = expandPlaceholders(content, properties);
6062
}
6163

62-
private String loadContent(File file) throws IOException {
64+
private String loadContent(@Nullable File file) throws IOException {
6365
if (file == null) {
6466
return loadContent(getClass().getResourceAsStream("launch.script"));
6567
}
@@ -83,7 +85,7 @@ private void copy(InputStream inputStream, OutputStream outputStream) throws IOE
8385
outputStream.flush();
8486
}
8587

86-
private String expandPlaceholders(String content, Map<?, ?> properties) throws IOException {
88+
private String expandPlaceholders(@Nullable String content, Map<?, ?> properties) throws IOException {
8789
StringBuilder expanded = new StringBuilder();
8890
Matcher matcher = PLACEHOLDER_PATTERN.matcher(content);
8991
while (matcher.find()) {

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.jar.JarFile;
2424
import java.util.jar.Manifest;
2525

26+
import org.jspecify.annotations.Nullable;
27+
2628
/**
2729
* Utilities for manipulating files and directories in Spring Boot tooling.
2830
*
@@ -61,7 +63,10 @@ public static void removeDuplicatesFromOutputDirectory(File outputDirectory, Fil
6163
* @return if the file has been signed
6264
* @throws IOException on IO error
6365
*/
64-
public static boolean isSignedJarFile(File file) throws IOException {
66+
public static boolean isSignedJarFile(@Nullable File file) throws IOException {
67+
if (file == null) {
68+
return false;
69+
}
6570
try (JarFile jarFile = new JarFile(file)) {
6671
if (hasDigestEntry(jarFile.getManifest())) {
6772
return true;
@@ -70,7 +75,7 @@ public static boolean isSignedJarFile(File file) throws IOException {
7075
return false;
7176
}
7277

73-
private static boolean hasDigestEntry(Manifest manifest) {
78+
private static boolean hasDigestEntry(@Nullable Manifest manifest) {
7479
return (manifest != null) && manifest.getEntries().values().stream().anyMatch(FileUtils::hasDigestName);
7580
}
7681

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/ImagePackager.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.jar.JarFile;
2323
import java.util.zip.ZipEntry;
2424

25+
import org.jspecify.annotations.Nullable;
26+
2527
import org.springframework.util.Assert;
2628

2729
/**
@@ -38,7 +40,7 @@ public class ImagePackager extends Packager {
3840
* @param source the source file to package
3941
* @param backupFile the backup of the source file to package
4042
*/
41-
public ImagePackager(File source, File backupFile) {
43+
public ImagePackager(File source, @Nullable File backupFile) {
4244
super(source);
4345
setBackupFile(backupFile);
4446
if (isAlreadyPackaged()) {
@@ -55,7 +57,8 @@ public ImagePackager(File source, File backupFile) {
5557
* @param exporter the exporter used to write the image
5658
* @throws IOException on IO error
5759
*/
58-
public void packageImage(Libraries libraries, BiConsumer<ZipEntry, EntryWriter> exporter) throws IOException {
60+
public void packageImage(Libraries libraries, BiConsumer<ZipEntry, @Nullable EntryWriter> exporter)
61+
throws IOException {
5962
packageImage(libraries, new DelegatingJarWriter(exporter));
6063
}
6164

@@ -71,14 +74,14 @@ private void packageImage(Libraries libraries, AbstractJarWriter writer) throws
7174
*/
7275
private static class DelegatingJarWriter extends AbstractJarWriter {
7376

74-
private final BiConsumer<ZipEntry, EntryWriter> exporter;
77+
private final BiConsumer<ZipEntry, @Nullable EntryWriter> exporter;
7578

76-
DelegatingJarWriter(BiConsumer<ZipEntry, EntryWriter> exporter) {
79+
DelegatingJarWriter(BiConsumer<ZipEntry, @Nullable EntryWriter> exporter) {
7780
this.exporter = exporter;
7881
}
7982

8083
@Override
81-
protected void writeToArchive(ZipEntry entry, EntryWriter entryWriter) throws IOException {
84+
protected void writeToArchive(ZipEntry entry, @Nullable EntryWriter entryWriter) throws IOException {
8285
this.exporter.accept(entry, entryWriter);
8386
}
8487

loader/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarModeLibrary.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ private static String getJarName(LibraryCoordinates coordinates) {
6363

6464
@Override
6565
public InputStream openStream() throws IOException {
66-
String path = "META-INF/jarmode/" + getCoordinates().getArtifactId() + ".jar";
66+
LibraryCoordinates coordinates = getCoordinates();
67+
Assert.state(coordinates != null, "'coordinates' must not be null");
68+
String path = "META-INF/jarmode/" + coordinates.getArtifactId() + ".jar";
6769
URL resource = getClass().getClassLoader().getResource(path);
6870
Assert.state(resource != null, () -> "Unable to find resource " + path);
6971
return resource.openStream();

0 commit comments

Comments
 (0)