mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-01 23:09:01 +00:00
Add nullability annotations to loader/spring-boot-jarmode-tools
See gh-46587
This commit is contained in:
+9
-7
@@ -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<? extends Command> commands, String name) {
|
||||
static @Nullable Command find(Collection<? extends Command> 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<String> args) {
|
||||
private @Nullable String claimArg(Deque<String> args) {
|
||||
if (this.valueDescription == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+8
-6
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+14
-16
@@ -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);
|
||||
|
||||
+3
-1
@@ -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("[<layer>...]"));
|
||||
this.delegate = new ExtractCommand(context, layers);
|
||||
|
||||
+3
-1
@@ -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<Command> commands, String jarMode) {
|
||||
HelpCommand(Context context, List<Command> commands, @Nullable String jarMode) {
|
||||
super("help", "Help about any command", Options.none(), Parameters.of("[<command>]"));
|
||||
this.context = context;
|
||||
this.commands = commands;
|
||||
|
||||
+4
-2
@@ -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();
|
||||
|
||||
+3
-1
@@ -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) {
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
+3
-1
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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;
|
||||
}
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* JarMode support for layertools and tools.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.jarmode.tools;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
Reference in New Issue
Block a user