diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Command.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Command.java index fe64e3430bf..b2239546c6d 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Command.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Command.java @@ -28,6 +28,8 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; + /** * A command that can be launched. * @@ -132,7 +134,7 @@ abstract class Command { * Returns the deprecation message. * @return the deprecation message */ - String getDeprecationMessage() { + @Nullable String getDeprecationMessage() { return null; } @@ -142,7 +144,7 @@ abstract class Command { * @param name the name of the command to find * @return a {@link Command} instance or {@code null}. */ - static Command find(Collection commands, String name) { + static @Nullable Command find(Collection commands, String name) { for (Command command : commands) { if (command.getName().equals(name)) { return command; @@ -206,7 +208,7 @@ abstract class Command { this.values = values; } - private Option find(String arg) { + private @Nullable Option find(String arg) { if (arg.startsWith("--")) { String name = arg.substring(2); for (Option candidate : this.values) { @@ -264,13 +266,13 @@ abstract class Command { private final String name; - private final String valueDescription; + private final @Nullable String valueDescription; private final String description; private final boolean optionalValue; - private Option(String name, String valueDescription, String description, boolean optionalValue) { + private Option(String name, @Nullable String valueDescription, String description, boolean optionalValue) { this.name = name; this.description = description; this.valueDescription = valueDescription; @@ -290,7 +292,7 @@ abstract class Command { * option is a flag/switch. * @return the option value description */ - String getValueDescription() { + @Nullable String getValueDescription() { return this.valueDescription; } @@ -310,7 +312,7 @@ abstract class Command { return this.description; } - private String claimArg(Deque args) { + private @Nullable String claimArg(Deque args) { if (this.valueDescription == null) { return null; } diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Context.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Context.java index 2a647a14cc7..79d7e553bbb 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Context.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/Context.java @@ -28,6 +28,8 @@ import java.security.ProtectionDomain; import java.util.Locale; import java.util.jar.JarFile; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; /** @@ -41,7 +43,7 @@ class Context { private final File workingDir; - private final String relativeDir; + private final @Nullable String relativeDir; /** * Create a new {@link Context} instance. @@ -63,7 +65,7 @@ class Context { this.relativeDir = deduceRelativeDir(archiveFile.getParentFile(), this.workingDir); } - private boolean isExistingFile(File archiveFile) { + private boolean isExistingFile(@Nullable File archiveFile) { return archiveFile != null && archiveFile.isFile() && archiveFile.exists(); } @@ -81,10 +83,10 @@ class Context { if (source != null && source.exists()) { return source.getAbsoluteFile(); } - return null; + throw new IllegalStateException("Unable to find source archive"); } catch (Exception ex) { - return null; + throw new IllegalStateException("Unable to find source archive", ex); } } @@ -105,7 +107,7 @@ class Context { return new File(name); } - private String deduceRelativeDir(File sourceDirectory, File workingDir) { + private @Nullable String deduceRelativeDir(File sourceDirectory, File workingDir) { String sourcePath = sourceDirectory.getAbsolutePath(); String workingPath = workingDir.getAbsolutePath(); if (sourcePath.equals(workingPath) || !sourcePath.startsWith(workingPath)) { @@ -136,7 +138,7 @@ class Context { * or {@code null} if none relative directory can be deduced. * @return the relative dir ending in {@code /} or {@code null} */ - String getRelativeArchiveDir() { + @Nullable String getRelativeArchiveDir() { return this.relativeDir; } diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractCommand.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractCommand.java index 68ae5f7cc64..667527752a1 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractCommand.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractCommand.java @@ -41,6 +41,8 @@ import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.jarmode.tools.JarStructure.Entry; import org.springframework.boot.jarmode.tools.JarStructure.Entry.Type; import org.springframework.boot.loader.jarmode.JarModeErrorException; @@ -84,13 +86,13 @@ class ExtractCommand extends Command { private final Context context; - private final Layers layers; + private final @Nullable Layers layers; ExtractCommand(Context context) { this(context, null); } - ExtractCommand(Context context, Layers layers) { + ExtractCommand(Context context, @Nullable Layers layers) { super("extract", "Extract the contents from the jar", Options.of(LAUNCHER_OPTION, LAYERS_OPTION, DESTINATION_OPTION, LIBRARIES_DIRECTORY_OPTION, APPLICATION_FILENAME_OPTION, FORCE_OPTION), Parameters.none()); @@ -153,7 +155,7 @@ class ExtractCommand extends Command { String librariesDirectory = getLibrariesDirectory(options); extractArchive(fileResolver, (jarEntry) -> { Entry entry = jarStructure.resolve(jarEntry); - if (isType(entry, Type.LIBRARY)) { + if (entry != null && entry.type() == Type.LIBRARY) { return librariesDirectory + entry.location(); } return null; @@ -269,10 +271,6 @@ class ExtractCommand extends Command { return this.context.getArchiveFile().getName(); } - private static boolean isType(Entry entry, Type type) { - return (entry != null) && entry.type() == type; - } - private static void extractEntry(InputStream stream, JarEntry entry, File file) throws IOException { mkdirs(file.getParentFile()); try (OutputStream out = new FileOutputStream(file)) { @@ -287,15 +285,15 @@ class ExtractCommand extends Command { } } - private static FileTime getCreationTime(JarEntry entry) { + private static @Nullable FileTime getCreationTime(JarEntry entry) { return (entry.getCreationTime() != null) ? entry.getCreationTime() : entry.getLastModifiedTime(); } - private static FileTime getLastAccessTime(JarEntry entry) { + private static @Nullable FileTime getLastAccessTime(JarEntry entry) { return (entry.getLastAccessTime() != null) ? entry.getLastAccessTime() : getLastModifiedTime(entry); } - private static FileTime getLastModifiedTime(JarEntry entry) { + private static @Nullable FileTime getLastModifiedTime(JarEntry entry) { return (entry.getLastModifiedTime() != null) ? entry.getLastModifiedTime() : entry.getCreationTime(); } @@ -348,7 +346,7 @@ class ExtractCommand extends Command { @FunctionalInterface private interface EntryNameTransformer { - String getName(JarEntry entry); + @Nullable String getName(JarEntry entry); } @@ -375,7 +373,7 @@ class ExtractCommand extends Command { * should be skipped * @throws IOException if something went wrong */ - default File resolve(JarEntry entry, String newName) throws IOException { + default @Nullable File resolve(JarEntry entry, String newName) throws IOException { return resolve(entry.getName(), newName); } @@ -387,7 +385,7 @@ class ExtractCommand extends Command { * should be skipped * @throws IOException if something went wrong */ - File resolve(String originalName, String newName) throws IOException; + @Nullable File resolve(String originalName, String newName) throws IOException; /** * Resolves the file for the application. @@ -395,7 +393,7 @@ class ExtractCommand extends Command { * be skipped * @throws IOException if something went wrong */ - File resolveApplication() throws IOException; + @Nullable File resolveApplication() throws IOException; } @@ -453,7 +451,7 @@ class ExtractCommand extends Command { } @Override - public File resolve(String originalName, String newName) throws IOException { + public @Nullable File resolve(String originalName, String newName) throws IOException { String layer = this.layers.getLayer(originalName); if (shouldExtractLayer(layer)) { File directory = getLayerDirectory(layer); @@ -463,7 +461,7 @@ class ExtractCommand extends Command { } @Override - public File resolveApplication() throws IOException { + public @Nullable File resolveApplication() throws IOException { String layer = this.layers.getApplicationLayerName(); if (shouldExtractLayer(layer)) { File directory = getLayerDirectory(layer); diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractLayersCommand.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractLayersCommand.java index fc0cdf4d300..eca850c61be 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractLayersCommand.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ExtractLayersCommand.java @@ -22,6 +22,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.util.StringUtils; /** @@ -39,7 +41,7 @@ class ExtractLayersCommand extends Command { this(context, null); } - ExtractLayersCommand(Context context, Layers layers) { + ExtractLayersCommand(Context context, @Nullable Layers layers) { super("extract", "Extracts layers from the jar for image creation", Options.of(DESTINATION_OPTION), Parameters.of("[...]")); this.delegate = new ExtractCommand(context, layers); diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/HelpCommand.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/HelpCommand.java index 296c6d9dd85..f4a5b4947d7 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/HelpCommand.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/HelpCommand.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; + /** * Implicit {@code 'help'} command. * @@ -39,7 +41,7 @@ class HelpCommand extends Command { this(context, commands, System.getProperty("jarmode")); } - HelpCommand(Context context, List commands, String jarMode) { + HelpCommand(Context context, List commands, @Nullable String jarMode) { super("help", "Help about any command", Options.none(), Parameters.of("[]")); this.context = context; this.commands = commands; diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedJarStructure.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedJarStructure.java index c5f779a4d6f..c4c7dc266ff 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedJarStructure.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedJarStructure.java @@ -33,6 +33,8 @@ import java.util.jar.Manifest; import java.util.stream.Collectors; import java.util.zip.ZipEntry; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.jarmode.tools.JarStructure.Entry.Type; import org.springframework.util.Assert; import org.springframework.util.StreamUtils; @@ -92,7 +94,7 @@ class IndexedJarStructure implements JarStructure { } @Override - public Entry resolve(String name) { + public @Nullable Entry resolve(String name) { if (ENTRY_IGNORE_LIST.contains(name)) { return null; } @@ -138,7 +140,7 @@ class IndexedJarStructure implements JarStructure { return value; } - static IndexedJarStructure get(File file) { + static @Nullable IndexedJarStructure get(File file) { try { try (JarFile jarFile = new JarFile(file)) { Manifest manifest = jarFile.getManifest(); diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedLayers.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedLayers.java index e6d674fba60..7f560d0656d 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedLayers.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/IndexedLayers.java @@ -30,6 +30,8 @@ import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.ZipEntry; +import org.jspecify.annotations.Nullable; + import org.springframework.util.Assert; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; @@ -98,7 +100,7 @@ class IndexedLayers implements Layers { * @return an {@link IndexedLayers} instance or {@code null} if this not a layered * jar. */ - static IndexedLayers get(Context context) { + static @Nullable IndexedLayers get(Context context) { try (JarFile jarFile = new JarFile(context.getArchiveFile())) { Manifest manifest = jarFile.getManifest(); if (manifest == null) { diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/JarStructure.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/JarStructure.java index 71f80ac7b30..1a9455059d6 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/JarStructure.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/JarStructure.java @@ -20,6 +20,8 @@ import java.util.function.UnaryOperator; import java.util.jar.Manifest; import java.util.zip.ZipEntry; +import org.jspecify.annotations.Nullable; + /** * Provide information about a fat jar structure that is meant to be extracted. * @@ -34,7 +36,7 @@ interface JarStructure { * @param entry the entry to handle * @return the resolved {@link Entry} */ - default Entry resolve(ZipEntry entry) { + default @Nullable Entry resolve(ZipEntry entry) { return resolve(entry.getName()); } @@ -44,7 +46,7 @@ interface JarStructure { * @param name the name of the entry to handle * @return the resolved {@link Entry} */ - Entry resolve(String name); + @Nullable Entry resolve(String name); /** * Create the {@link Manifest} for the launcher jar, applying the specified operator diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/LayerToolsJarMode.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/LayerToolsJarMode.java index aa6c5754585..c1663c64871 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/LayerToolsJarMode.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/LayerToolsJarMode.java @@ -18,6 +18,8 @@ package org.springframework.boot.jarmode.tools; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.loader.jarmode.JarMode; /** @@ -29,7 +31,7 @@ import org.springframework.boot.loader.jarmode.JarMode; */ public class LayerToolsJarMode implements JarMode { - static Context contextOverride; + static @Nullable Context contextOverride; @Override public boolean accepts(String mode) { diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ToolsJarMode.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ToolsJarMode.java index 437fefe3df5..c8c705ea8d8 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ToolsJarMode.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/ToolsJarMode.java @@ -19,6 +19,8 @@ package org.springframework.boot.jarmode.tools; import java.io.PrintStream; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.loader.jarmode.JarMode; /** @@ -37,7 +39,7 @@ public class ToolsJarMode implements JarMode { this(null, null); } - public ToolsJarMode(Context context, PrintStream out) { + public ToolsJarMode(@Nullable Context context, @Nullable PrintStream out) { this.context = (context != null) ? context : new Context(); this.out = (out != null) ? out : System.out; } diff --git a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/package-info.java b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/package-info.java index 668088bd615..d818f3fd838 100644 --- a/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/package-info.java +++ b/loader/spring-boot-jarmode-tools/src/main/java/org/springframework/boot/jarmode/tools/package-info.java @@ -17,4 +17,7 @@ /** * JarMode support for layertools and tools. */ +@NullMarked package org.springframework.boot.jarmode.tools; + +import org.jspecify.annotations.NullMarked;