includes) {
this.includes = includes;
}
@@ -163,7 +165,7 @@ private FilterArtifacts getFilters(ArtifactsFilter... additionalFilters) {
return filters;
}
- private String cleanFilterConfig(String content) {
+ private String cleanFilterConfig(@Nullable String content) {
if (content == null || content.trim().isEmpty()) {
return "";
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
similarity index 91%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
index 386be8f8cea4..f4383ab65bd7 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractPackagerMojo.java
@@ -36,6 +36,7 @@
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
+import org.jspecify.annotations.Nullable;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
@@ -46,7 +47,6 @@
import org.springframework.boot.loader.tools.Layouts.None;
import org.springframework.boot.loader.tools.Layouts.War;
import org.springframework.boot.loader.tools.Libraries;
-import org.springframework.boot.loader.tools.LoaderImplementation;
import org.springframework.boot.loader.tools.Packager;
import org.springframework.boot.loader.tools.layer.CustomLayers;
@@ -67,6 +67,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 1.0.0
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
protected MavenProject project;
/**
@@ -74,6 +75,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 2.4.0
*/
@Parameter(defaultValue = "${session}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
protected MavenSession session;
/**
@@ -88,7 +90,7 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* @since 1.0.0
*/
@Parameter
- private String mainClass;
+ private @Nullable String mainClass;
/**
* Exclude Spring Boot devtools from the repackaged archive.
@@ -115,8 +117,8 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
* Include optional dependencies.
* @since 3.5.7
*/
- @Parameter(defaultValue = "true")
- public boolean includeOptional = true;
+ @Parameter(defaultValue = "false")
+ public boolean includeOptional;
/**
* Include JAR tools.
@@ -142,16 +144,7 @@ protected AbstractPackagerMojo(MavenProjectHelper projectHelper) {
* @return {@code null}, indicating a layout type will be chosen based on the original
* archive type
*/
- protected LayoutType getLayout() {
- return null;
- }
-
- /**
- * Return the loader implementation that should be used.
- * @return the loader implementation or {@code null}
- * @since 3.2.0
- */
- protected LoaderImplementation getLoaderImplementation() {
+ protected @Nullable LayoutType getLayout() {
return null;
}
@@ -160,7 +153,7 @@ protected LoaderImplementation getLoaderImplementation() {
* no explicit layout is set.
* @return {@code null}, indicating a default layout factory will be chosen
*/
- protected LayoutFactory getLayoutFactory() {
+ protected @Nullable LayoutFactory getLayoutFactory() {
return null;
}
@@ -172,7 +165,6 @@ protected LayoutFactory getLayoutFactory() {
*/
protected P getConfiguredPackager(Supplier
supplier) {
P packager = supplier.get();
- packager.setLoaderImplementation(getLoaderImplementation());
packager.setLayoutFactory(getLayoutFactory());
packager.addMainClassTimeoutWarningListener(new LoggingMainClassTimeoutWarningListener(this::getLog));
packager.setMainClass(this.mainClass);
@@ -218,7 +210,7 @@ private Document getDocumentIfAvailable(File xmlFile) throws Exception {
* @return the libraries to use
* @throws MojoExecutionException on execution error
*/
- protected final Libraries getLibraries(Collection unpacks) throws MojoExecutionException {
+ protected final Libraries getLibraries(@Nullable Collection unpacks) throws MojoExecutionException {
Set artifacts = this.project.getArtifacts();
Set includedArtifacts = filterDependencies(artifacts, getAdditionalFilters());
return new ArtifactsLibraries(artifacts, includedArtifacts, this.session.getProjects(), unpacks, getLog());
@@ -248,12 +240,12 @@ private ArtifactsFilter[] getAdditionalFilters() {
* @param classifier the artifact classifier
* @return the source artifact to repackage
*/
- protected Artifact getSourceArtifact(String classifier) {
+ protected Artifact getSourceArtifact(@Nullable String classifier) {
Artifact sourceArtifact = getArtifact(classifier);
return (sourceArtifact != null) ? sourceArtifact : this.project.getArtifact();
}
- private Artifact getArtifact(String classifier) {
+ private @Nullable Artifact getArtifact(@Nullable String classifier) {
if (classifier != null) {
for (Artifact attachedArtifact : this.project.getAttachedArtifacts()) {
if (classifier.equals(attachedArtifact.getClassifier()) && attachedArtifact.getFile() != null
@@ -265,7 +257,7 @@ private Artifact getArtifact(String classifier) {
return null;
}
- protected File getTargetFile(String finalName, String classifier, File targetDirectory) {
+ protected File getTargetFile(String finalName, @Nullable String classifier, File targetDirectory) {
String classifierSuffix = (classifier != null) ? classifier.trim() : "";
if (!classifierSuffix.isEmpty() && !classifierSuffix.startsWith("-")) {
classifierSuffix = "-" + classifierSuffix;
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
similarity index 93%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
index f15b2408d057..08feb075567f 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
@@ -37,6 +37,7 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.toolchain.ToolchainManager;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.loader.tools.FileUtils;
import org.springframework.util.StringUtils;
@@ -62,6 +63,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
private MavenProject project;
/**
@@ -70,6 +72,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.3.0
*/
@Parameter(defaultValue = "${session}", readonly = true)
+ @SuppressWarnings("NullAway.Init")
private MavenSession session;
/**
@@ -97,6 +100,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.2.0
*/
@Parameter(property = "spring-boot.run.agents")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private File[] agents;
/**
@@ -114,7 +118,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.5.0
*/
@Parameter(property = "spring-boot.run.workingDirectory")
- private File workingDirectory;
+ private @Nullable File workingDirectory;
/**
* JVM arguments that should be associated with the forked process used to run the
@@ -123,7 +127,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.1.0
*/
@Parameter(property = "spring-boot.run.jvmArguments")
- private String jvmArguments;
+ private @Nullable String jvmArguments;
/**
* List of JVM system properties to pass to the process.
@@ -131,7 +135,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.1.0
*/
@Parameter
- private Map systemPropertyVariables;
+ private @Nullable Map systemPropertyVariables;
/**
* List of Environment variables that should be associated with the forked process
@@ -140,7 +144,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.1.0
*/
@Parameter
- private Map environmentVariables;
+ private @Nullable Map environmentVariables;
/**
* Arguments that should be passed to the application.
@@ -148,6 +152,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] arguments;
/**
@@ -158,7 +163,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 2.2.3
*/
@Parameter(property = "spring-boot.run.arguments")
- private String commandlineArguments;
+ private @Nullable String commandlineArguments;
/**
* The spring profiles to activate. Convenience shortcut of specifying the
@@ -168,6 +173,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.3.0
*/
@Parameter(property = "spring-boot.run.profiles")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] profiles;
/**
@@ -177,7 +183,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(property = "spring-boot.run.main-class")
- private String mainClass;
+ private @Nullable String mainClass;
/**
* Additional classpath elements that should be added to the classpath. An element can
@@ -186,6 +192,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 3.2.0
*/
@Parameter(property = "spring-boot.run.additional-classpath-elements")
+ @SuppressWarnings("NullAway") // maven-maven-plugin can't handle annotated arrays
private String[] additionalClasspathElements;
/**
@@ -195,6 +202,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0.0
*/
@Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
+ @SuppressWarnings("NullAway.Init")
private File classesDirectory;
/**
@@ -304,7 +312,7 @@ private Map determineEnvironmentVariables() {
* @return a {@link RunArguments} defining the JVM arguments
*/
protected RunArguments resolveJvmArguments() {
- List arguments = new ArrayList<>();
+ List<@Nullable String> arguments = new ArrayList<>();
if (this.systemPropertyVariables != null) {
for (Entry systemProperty : this.systemPropertyVariables.entrySet()) {
String argument = SystemPropertyFormatter.format(systemProperty.getKey(), systemProperty.getValue());
@@ -341,7 +349,7 @@ private void addAgents(List args) {
}
private void addActiveProfileArgument(RunArguments arguments) {
- if (this.profiles.length > 0) {
+ if (this.profiles != null && this.profiles.length > 0) {
StringBuilder arg = new StringBuilder("--spring.profiles.active=");
for (int i = 0; i < this.profiles.length; i++) {
arg.append(this.profiles[i]);
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
similarity index 96%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
index d7b50579d637..8ed3efb08b75 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ArtifactsLibraries.java
@@ -29,6 +29,7 @@
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.loader.tools.Libraries;
import org.springframework.boot.loader.tools.Library;
@@ -64,7 +65,7 @@ public class ArtifactsLibraries implements Libraries {
private final Collection localProjects;
- private final Collection unpacks;
+ private final @Nullable Collection unpacks;
private final Log log;
@@ -78,7 +79,7 @@ public class ArtifactsLibraries implements Libraries {
* @since 2.4.0
*/
public ArtifactsLibraries(Set artifacts, Collection localProjects,
- Collection unpacks, Log log) {
+ @Nullable Collection unpacks, Log log) {
this(artifacts, artifacts, localProjects, unpacks, log);
}
@@ -93,7 +94,7 @@ public ArtifactsLibraries(Set artifacts, Collection loca
* @since 2.4.8
*/
public ArtifactsLibraries(Set artifacts, Set includedArtifacts,
- Collection localProjects, Collection unpacks, Log log) {
+ Collection localProjects, @Nullable Collection unpacks, Log log) {
this.artifacts = artifacts;
this.includedArtifacts = includedArtifacts;
this.localProjects = localProjects;
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageForkMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageForkMojo.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageForkMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageForkMojo.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java
similarity index 92%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java
index 065db26b039a..24b07f85b932 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java
@@ -34,6 +34,7 @@
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProjectHelper;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.buildpack.platform.build.AbstractBuildLog;
import org.springframework.boot.buildpack.platform.build.BuildLog;
@@ -49,7 +50,7 @@
import org.springframework.boot.loader.tools.ImagePackager;
import org.springframework.boot.loader.tools.LayoutFactory;
import org.springframework.boot.loader.tools.Libraries;
-import org.springframework.boot.loader.tools.LoaderImplementation;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -71,13 +72,15 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.0
*/
@Parameter(defaultValue = "${project.build.directory}", required = true)
+ @SuppressWarnings("NullAway.Init")
private File sourceDirectory;
/**
* Name of the source archive.
* @since 2.3.0
*/
- @Parameter(defaultValue = "${project.build.finalName}", readonly = true)
+ @Parameter(defaultValue = "${project.build.finalName}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
private String finalName;
/**
@@ -92,7 +95,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.0
*/
@Parameter
- private String classifier;
+ private @Nullable String classifier;
/**
* Image configuration, with {@code builder}, {@code runImage}, {@code name},
@@ -101,7 +104,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.0
*/
@Parameter
- private Image image;
+ private @Nullable Image image;
/**
* Alias for {@link Image#name} to support configuration through command-line
@@ -109,7 +112,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.0
*/
@Parameter(property = "spring-boot.build-image.imageName")
- String imageName;
+ @Nullable String imageName;
/**
* Alias for {@link Image#builder} to support configuration through command-line
@@ -117,14 +120,14 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.0
*/
@Parameter(property = "spring-boot.build-image.builder")
- String imageBuilder;
+ @Nullable String imageBuilder;
/**
* Alias for {@link Image#trustBuilder} to support configuration through command-line
* property.
*/
@Parameter(property = "spring-boot.build-image.trustBuilder")
- Boolean trustBuilder;
+ @Nullable Boolean trustBuilder;
/**
* Alias for {@link Image#runImage} to support configuration through command-line
@@ -132,7 +135,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.1
*/
@Parameter(property = "spring-boot.build-image.runImage")
- String runImage;
+ @Nullable String runImage;
/**
* Alias for {@link Image#cleanCache} to support configuration through command-line
@@ -140,21 +143,21 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.4.0
*/
@Parameter(property = "spring-boot.build-image.cleanCache")
- Boolean cleanCache;
+ @Nullable Boolean cleanCache;
/**
* Alias for {@link Image#pullPolicy} to support configuration through command-line
* property.
*/
@Parameter(property = "spring-boot.build-image.pullPolicy")
- PullPolicy pullPolicy;
+ @Nullable PullPolicy pullPolicy;
/**
* Alias for {@link Image#publish} to support configuration through command-line
* property.
*/
@Parameter(property = "spring-boot.build-image.publish")
- Boolean publish;
+ @Nullable Boolean publish;
/**
* Alias for {@link Image#network} to support configuration through command-line
@@ -162,7 +165,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.6.0
*/
@Parameter(property = "spring-boot.build-image.network")
- String network;
+ @Nullable String network;
/**
* Alias for {@link Image#createdDate} to support configuration through command-line
@@ -170,7 +173,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 3.1.0
*/
@Parameter(property = "spring-boot.build-image.createdDate")
- String createdDate;
+ @Nullable String createdDate;
/**
* Alias for {@link Image#applicationDirectory} to support configuration through
@@ -178,7 +181,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 3.1.0
*/
@Parameter(property = "spring-boot.build-image.applicationDirectory")
- String applicationDirectory;
+ @Nullable String applicationDirectory;
/**
* Alias for {@link Image#imagePlatform} to support configuration through command-line
@@ -186,14 +189,14 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 3.4.0
*/
@Parameter(property = "spring-boot.build-image.imagePlatform")
- String imagePlatform;
+ @Nullable String imagePlatform;
/**
* Docker configuration options.
* @since 2.4.0
*/
@Parameter
- private Docker docker;
+ private @Nullable Docker docker;
/**
* The type of archive (which corresponds to how the dependencies are laid out inside
@@ -202,14 +205,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.11
*/
@Parameter
- private LayoutType layout;
-
- /**
- * The loader implementation that should be used.
- * @since 3.2.0
- */
- @Parameter
- private LoaderImplementation loaderImplementation;
+ private @Nullable LayoutType layout;
/**
* The layout factory that will be used to create the executable archive if no
@@ -218,7 +214,7 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
* @since 2.3.11
*/
@Parameter
- private LayoutFactory layoutFactory;
+ private @Nullable LayoutFactory layoutFactory;
protected BuildImageMojo(MavenProjectHelper projectHelper) {
super(projectHelper);
@@ -230,15 +226,10 @@ protected BuildImageMojo(MavenProjectHelper projectHelper) {
* is not provided
*/
@Override
- protected LayoutType getLayout() {
+ protected @Nullable LayoutType getLayout() {
return this.layout;
}
- @Override
- protected LoaderImplementation getLoaderImplementation() {
- return this.loaderImplementation;
- }
-
/**
* Return the layout factory that will be used to determine the
* {@link AbstractPackagerMojo.LayoutType} if no explicit layout is set.
@@ -246,7 +237,7 @@ protected LoaderImplementation getLoaderImplementation() {
* parameter is not provided
*/
@Override
- protected LayoutFactory getLayoutFactory() {
+ protected @Nullable LayoutFactory getLayoutFactory() {
return this.layoutFactory;
}
@@ -340,7 +331,7 @@ private File getArchiveFile() {
* Return the {@link File} to use to back up the original source.
* @return the file to use to back up the original source
*/
- private File getBackupFile() {
+ private @Nullable File getBackupFile() {
// We can't use 'project.getAttachedArtifacts()' because package can be done in a
// forked lifecycle and will be null
if (this.classifier != null) {
@@ -451,11 +442,12 @@ public void writeTo(OutputStream outputStream) throws IOException {
}
}
- private void write(ZipEntry jarEntry, EntryWriter entryWriter, TarArchiveOutputStream tar) {
+ private void write(ZipEntry jarEntry, @Nullable EntryWriter entryWriter, TarArchiveOutputStream tar) {
try {
TarArchiveEntry tarEntry = convert(jarEntry);
tar.putArchiveEntry(tarEntry);
if (tarEntry.isFile()) {
+ Assert.state(entryWriter != null, "'entryWriter' must not be null");
entryWriter.write(tar);
}
tar.closeArchiveEntry();
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageNoForkMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageNoForkMojo.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageNoForkMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageNoForkMojo.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java
similarity index 91%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java
index 3e52e8888128..7877a60ad4e5 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildInfoMojo.java
@@ -33,6 +33,7 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.jspecify.annotations.Nullable;
import org.sonatype.plexus.build.incremental.BuildContext;
import org.springframework.boot.loader.tools.BuildPropertiesWriter;
@@ -56,18 +57,21 @@ public class BuildInfoMojo extends AbstractMojo {
* The Maven session.
*/
@Parameter(defaultValue = "${session}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
private MavenSession session;
/**
* The Maven project.
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
+ @SuppressWarnings("NullAway.Init")
private MavenProject project;
/**
* The location of the generated {@code build-info.properties} file.
*/
@Parameter(defaultValue = "${project.build.outputDirectory}/META-INF/build-info.properties")
+ @SuppressWarnings("NullAway.Init")
private File outputFile;
/**
@@ -79,14 +83,14 @@ public class BuildInfoMojo extends AbstractMojo {
* @since 2.2.0
*/
@Parameter(defaultValue = "${project.build.outputTimestamp}")
- private String time;
+ private @Nullable String time;
/**
* Additional properties to store in the {@code build-info.properties} file. Each
* entry is prefixed by {@code build.} in the generated {@code build-info.properties}.
*/
@Parameter
- private Map additionalProperties;
+ private @Nullable Map additionalProperties;
/**
* Properties that should be excluded {@code build-info.properties} file. Can be used
@@ -95,7 +99,7 @@ public class BuildInfoMojo extends AbstractMojo {
* {@code additionalProperties}.
*/
@Parameter
- private List excludeInfoProperties;
+ private @Nullable List excludeInfoProperties;
/**
* Skip the execution.
@@ -138,11 +142,11 @@ private ProjectDetails getProjectDetails() {
return new ProjectDetails(group, artifact, version, name, time, additionalProperties);
}
- private T getIfNotExcluded(String name, T value) {
+ private @Nullable T getIfNotExcluded(String name, @Nullable T value) {
return (this.excludeInfoProperties == null || !this.excludeInfoProperties.contains(name)) ? value : null;
}
- private Map applyExclusions(Map source) {
+ private @Nullable Map applyExclusions(@Nullable Map source) {
if (source == null || this.excludeInfoProperties == null) {
return source;
}
@@ -151,7 +155,7 @@ private Map applyExclusions(Map source) {
return result;
}
- private Instant getBuildTime() {
+ private @Nullable Instant getBuildTime() {
if (this.time == null || this.time.isEmpty()) {
Date startTime = this.session.getRequest().getStartTime();
return (startTime != null) ? startTime.toInstant() : Instant.now();
diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CacheInfo.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CacheInfo.java
new file mode 100644
index 000000000000..98d23db744bd
--- /dev/null
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CacheInfo.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.maven;
+
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.boot.buildpack.platform.build.Cache;
+import org.springframework.util.Assert;
+
+/**
+ * Encapsulates configuration of an image building cache.
+ *
+ * @author Scott Frederick
+ * @since 2.6.0
+ */
+public class CacheInfo {
+
+ private @Nullable Cache cache;
+
+ public CacheInfo() {
+ }
+
+ private CacheInfo(Cache cache) {
+ this.cache = cache;
+ }
+
+ public void setVolume(VolumeCacheInfo info) {
+ Assert.state(this.cache == null, "Each image building cache can be configured only once");
+ String name = info.getName();
+ Assert.state(name != null, "'name' must not be null");
+ this.cache = Cache.volume(name);
+ }
+
+ public void setBind(BindCacheInfo info) {
+ Assert.state(this.cache == null, "Each image building cache can be configured only once");
+ String source = info.getSource();
+ Assert.state(source != null, "'source' must not be null");
+ this.cache = Cache.bind(source);
+ }
+
+ @Nullable Cache asCache() {
+ return this.cache;
+ }
+
+ static CacheInfo fromVolume(VolumeCacheInfo cacheInfo) {
+ String name = cacheInfo.getName();
+ Assert.state(name != null, "'name' must not be null");
+ return new CacheInfo(Cache.volume(name));
+ }
+
+ static CacheInfo fromBind(BindCacheInfo cacheInfo) {
+ String source = cacheInfo.getSource();
+ Assert.state(source != null, "'source' must not be null");
+ return new CacheInfo(Cache.bind(source));
+ }
+
+ /**
+ * Encapsulates configuration of an image building cache stored in a volume.
+ */
+ public static class VolumeCacheInfo {
+
+ private @Nullable String name;
+
+ public VolumeCacheInfo() {
+ }
+
+ VolumeCacheInfo(String name) {
+ this.name = name;
+ }
+
+ public @Nullable String getName() {
+ return this.name;
+ }
+
+ void setName(@Nullable String name) {
+ this.name = name;
+ }
+
+ }
+
+ /**
+ * Encapsulates configuration of an image building cache stored in a bind mount.
+ */
+ public static class BindCacheInfo {
+
+ private @Nullable String source;
+
+ public BindCacheInfo() {
+ }
+
+ BindCacheInfo(String name) {
+ this.source = name;
+ }
+
+ public @Nullable String getSource() {
+ return this.source;
+ }
+
+ void setSource(@Nullable String source) {
+ this.source = source;
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java
similarity index 95%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java
index d4d8a6098e8b..0b65402e8502 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ClassPath.java
@@ -33,6 +33,8 @@
import java.util.stream.Collector;
import java.util.stream.Collectors;
+import org.jspecify.annotations.Nullable;
+
import org.springframework.util.StringUtils;
/**
@@ -125,12 +127,12 @@ static ClassPath of(List urls) {
* @param urls the class path URLs
* @return a new {@link ClassPath} instance
*/
- static ClassPath of(UnaryOperator getSystemProperty, List urls) {
+ static ClassPath of(UnaryOperator<@Nullable String> getSystemProperty, List urls) {
boolean preferArgFile = urls.size() > 1 && isWindows(getSystemProperty);
return new ClassPath(preferArgFile, urls.stream().map(ClassPath::toPathString).collect(JOIN_BY_PATH_SEPARATOR));
}
- private static boolean isWindows(UnaryOperator getSystemProperty) {
+ private static boolean isWindows(UnaryOperator<@Nullable String> getSystemProperty) {
String os = getSystemProperty.apply("os.name");
return StringUtils.hasText(os) && os.toLowerCase(Locale.ROOT).contains("win");
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java
similarity index 85%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java
index 2e48c4f8891f..045a9aad877a 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CommandLineBuilder.java
@@ -24,6 +24,8 @@
import java.util.Map.Entry;
import java.util.Objects;
+import org.jspecify.annotations.Nullable;
+
import org.springframework.util.StringUtils;
/**
@@ -49,14 +51,15 @@ static CommandLineBuilder forMainClass(String mainClass) {
return new CommandLineBuilder(mainClass);
}
- CommandLineBuilder withJvmArguments(String... jvmArguments) {
+ // Do not use String @Nullable ... jvmArguments, Maven can't deal with that
+ CommandLineBuilder withJvmArguments(@Nullable String... jvmArguments) {
if (jvmArguments != null) {
this.options.addAll(Arrays.stream(jvmArguments).filter(Objects::nonNull).toList());
}
return this;
}
- CommandLineBuilder withSystemProperties(Map systemProperties) {
+ CommandLineBuilder withSystemProperties(@Nullable Map systemProperties) {
if (systemProperties != null) {
for (Entry systemProperty : systemProperties.entrySet()) {
String option = SystemPropertyFormatter.format(systemProperty.getKey(), systemProperty.getValue());
@@ -73,7 +76,8 @@ CommandLineBuilder withClasspath(URL... elements) {
return this;
}
- CommandLineBuilder withArguments(String... arguments) {
+ // Do not use String @Nullable ... arguments, Maven can't deal with that
+ CommandLineBuilder withArguments(@Nullable String... arguments) {
if (arguments != null) {
this.arguments.addAll(Arrays.stream(arguments).filter(Objects::nonNull).toList());
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java
similarity index 98%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java
index f1c17b533935..5bc0fe8f513e 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/CustomLayersProvider.java
@@ -29,6 +29,7 @@
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
+import org.jspecify.annotations.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -157,7 +158,7 @@ private List getChildNodeTextContent(Element element, String tagName) {
return patterns;
}
- private Element getChildElement(Element element, String tagName) {
+ private @Nullable Element getChildElement(Element element, String tagName) {
NodeList nodes = element.getElementsByTagName(tagName);
if (nodes.getLength() == 0) {
return null;
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/DependencyFilter.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/DependencyFilter.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/DependencyFilter.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/DependencyFilter.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java
similarity index 78%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java
index f86c1cbea5c4..5a95ddf613c7 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Docker.java
@@ -17,9 +17,11 @@
package org.springframework.boot.maven;
import org.apache.maven.plugin.logging.Log;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.buildpack.platform.build.BuilderDockerConfiguration;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryAuthentication;
+import org.springframework.util.Assert;
/**
* Docker configuration options.
@@ -30,29 +32,29 @@
*/
public class Docker {
- private String host;
+ private @Nullable String host;
- private String context;
+ private @Nullable String context;
private boolean tlsVerify;
- private String certPath;
+ private @Nullable String certPath;
private boolean bindHostToBuilder;
- private DockerRegistry builderRegistry;
+ private @Nullable DockerRegistry builderRegistry;
- private DockerRegistry publishRegistry;
+ private @Nullable DockerRegistry publishRegistry;
/**
* The host address of the Docker daemon.
* @return the Docker host
*/
- public String getHost() {
+ public @Nullable String getHost() {
return this.host;
}
- void setHost(String host) {
+ void setHost(@Nullable String host) {
this.host = host;
}
@@ -60,11 +62,11 @@ void setHost(String host) {
* The Docker context to use to retrieve host configuration.
* @return the Docker context
*/
- public String getContext() {
+ public @Nullable String getContext() {
return this.context;
}
- public void setContext(String context) {
+ public void setContext(@Nullable String context) {
this.context = context;
}
@@ -85,11 +87,11 @@ void setTlsVerify(boolean tlsVerify) {
* Docker daemon.
* @return the TLS certificate path
*/
- public String getCertPath() {
+ public @Nullable String getCertPath() {
return this.certPath;
}
- void setCertPath(String certPath) {
+ void setCertPath(@Nullable String certPath) {
this.certPath = certPath;
}
@@ -109,7 +111,7 @@ void setBindHostToBuilder(boolean bindHostToBuilder) {
* Configuration of the Docker registry where builder and run images are stored.
* @return the registry configuration
*/
- DockerRegistry getBuilderRegistry() {
+ @Nullable DockerRegistry getBuilderRegistry() {
return this.builderRegistry;
}
@@ -118,7 +120,7 @@ DockerRegistry getBuilderRegistry() {
* registry.
* @param builderRegistry the registry configuration
*/
- void setBuilderRegistry(DockerRegistry builderRegistry) {
+ void setBuilderRegistry(@Nullable DockerRegistry builderRegistry) {
this.builderRegistry = builderRegistry;
}
@@ -126,7 +128,7 @@ void setBuilderRegistry(DockerRegistry builderRegistry) {
* Configuration of the Docker registry where the generated image will be published.
* @return the registry configuration
*/
- DockerRegistry getPublishRegistry() {
+ @Nullable DockerRegistry getPublishRegistry() {
return this.publishRegistry;
}
@@ -135,7 +137,7 @@ DockerRegistry getPublishRegistry() {
* registry.
* @param builderRegistry the registry configuration
*/
- void setPublishRegistry(DockerRegistry builderRegistry) {
+ void setPublishRegistry(@Nullable DockerRegistry builderRegistry) {
this.publishRegistry = builderRegistry;
}
@@ -189,17 +191,22 @@ private BuilderDockerConfiguration customizePublishAuthentication(Log log,
getRegistryAuthentication("publish", this.publishRegistry, authentication));
}
- private DockerRegistryAuthentication getRegistryAuthentication(String type, DockerRegistry registry,
+ private DockerRegistryAuthentication getRegistryAuthentication(String type, @Nullable DockerRegistry registry,
DockerRegistryAuthentication fallback) {
if (registry == null || registry.isEmpty()) {
return fallback;
}
if (registry.hasTokenAuth() && !registry.hasUserAuth()) {
- return DockerRegistryAuthentication.token(registry.getToken());
+ String token = registry.getToken();
+ Assert.state(token != null, "'token' must not be null");
+ return DockerRegistryAuthentication.token(token);
}
if (registry.hasUserAuth() && !registry.hasTokenAuth()) {
- return DockerRegistryAuthentication.user(registry.getUsername(), registry.getPassword(), registry.getUrl(),
- registry.getEmail());
+ String username = registry.getUsername();
+ String password = registry.getPassword();
+ Assert.state(username != null, "'username' must not be null");
+ Assert.state(password != null, "'password' must not be null");
+ return DockerRegistryAuthentication.user(username, password, registry.getUrl(), registry.getEmail());
}
throw new IllegalArgumentException("Invalid Docker " + type
+ " registry configuration, either token or username/password must be provided");
@@ -210,20 +217,21 @@ private DockerRegistryAuthentication getRegistryAuthentication(String type, Dock
*/
public static class DockerRegistry {
- private String username;
+ private @Nullable String username;
- private String password;
+ private @Nullable String password;
- private String url;
+ private @Nullable String url;
- private String email;
+ private @Nullable String email;
- private String token;
+ private @Nullable String token;
public DockerRegistry() {
}
- public DockerRegistry(String username, String password, String url, String email) {
+ public DockerRegistry(@Nullable String username, @Nullable String password, @Nullable String url,
+ @Nullable String email) {
this.username = username;
this.password = password;
this.url = url;
@@ -238,11 +246,11 @@ public DockerRegistry(String token) {
* The username that will be used for user authentication to the registry.
* @return the username
*/
- public String getUsername() {
+ public @Nullable String getUsername() {
return this.username;
}
- void setUsername(String username) {
+ void setUsername(@Nullable String username) {
this.username = username;
}
@@ -250,11 +258,11 @@ void setUsername(String username) {
* The password that will be used for user authentication to the registry.
* @return the password
*/
- public String getPassword() {
+ public @Nullable String getPassword() {
return this.password;
}
- void setPassword(String password) {
+ void setPassword(@Nullable String password) {
this.password = password;
}
@@ -262,11 +270,11 @@ void setPassword(String password) {
* The email address that will be used for user authentication to the registry.
* @return the email address
*/
- public String getEmail() {
+ public @Nullable String getEmail() {
return this.email;
}
- void setEmail(String email) {
+ void setEmail(@Nullable String email) {
this.email = email;
}
@@ -274,11 +282,11 @@ void setEmail(String email) {
* The URL of the registry.
* @return the registry URL
*/
- String getUrl() {
+ @Nullable String getUrl() {
return this.url;
}
- void setUrl(String url) {
+ void setUrl(@Nullable String url) {
this.url = url;
}
@@ -286,11 +294,11 @@ void setUrl(String url) {
* The token that will be used for token authentication to the registry.
* @return the authentication token
*/
- public String getToken() {
+ public @Nullable String getToken() {
return this.token;
}
- void setToken(String token) {
+ void setToken(@Nullable String token) {
this.token = token;
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java
similarity index 87%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java
index a26f04c7f7ab..0a2b458d3f88 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/EnvVariables.java
@@ -22,6 +22,8 @@
import java.util.List;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
+
/**
* Utility class for working with Env variables.
*
@@ -31,11 +33,11 @@ class EnvVariables {
private final Map variables;
- EnvVariables(Map variables) {
+ EnvVariables(@Nullable Map variables) {
this.variables = parseEnvVariables(variables);
}
- private static Map parseEnvVariables(Map args) {
+ private static Map parseEnvVariables(@Nullable Map args) {
if (args == null || args.isEmpty()) {
return Collections.emptyMap();
}
@@ -48,7 +50,7 @@ private static Map parseEnvVariables(Map args) {
return result;
}
- private static String getValue(String value) {
+ private static String getValue(@Nullable String value) {
return (value != null) ? value : "";
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java
similarity index 89%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java
index 5960233aece2..0324c8791fbb 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/FilterableDependency.java
@@ -17,6 +17,7 @@
package org.springframework.boot.maven;
import org.apache.maven.plugins.annotations.Parameter;
+import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
@@ -33,19 +34,21 @@ public abstract class FilterableDependency {
* The groupId of the artifact to exclude.
*/
@Parameter(required = true)
+ @SuppressWarnings("NullAway.Init")
private String groupId;
/**
* The artifactId of the artifact to exclude.
*/
@Parameter(required = true)
+ @SuppressWarnings("NullAway.Init")
private String artifactId;
/**
* The classifier of the artifact to exclude.
*/
@Parameter
- private String classifier;
+ private @Nullable String classifier;
String getGroupId() {
return this.groupId;
@@ -63,11 +66,11 @@ void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
- String getClassifier() {
+ @Nullable String getClassifier() {
return this.classifier;
}
- void setClassifier(String classifier) {
+ void setClassifier(@Nullable String classifier) {
this.classifier = classifier;
}
diff --git a/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Image.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Image.java
new file mode 100644
index 000000000000..42e7f7ca4cdb
--- /dev/null
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Image.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.maven;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.apache.maven.artifact.Artifact;
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.boot.buildpack.platform.build.BuildRequest;
+import org.springframework.boot.buildpack.platform.build.BuildpackReference;
+import org.springframework.boot.buildpack.platform.build.Cache;
+import org.springframework.boot.buildpack.platform.build.PullPolicy;
+import org.springframework.boot.buildpack.platform.docker.type.Binding;
+import org.springframework.boot.buildpack.platform.docker.type.ImageName;
+import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
+import org.springframework.boot.buildpack.platform.io.Owner;
+import org.springframework.boot.buildpack.platform.io.TarArchive;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * Image configuration options.
+ *
+ * @author Phillip Webb
+ * @author Scott Frederick
+ * @author Jeroen Meijer
+ * @author Rafael Ceccone
+ * @author Julian Liebig
+ * @since 2.3.0
+ */
+public class Image {
+
+ @Nullable String name;
+
+ @Nullable String builder;
+
+ @Nullable Boolean trustBuilder;
+
+ @Nullable String runImage;
+
+ @Nullable Map env;
+
+ @Nullable Boolean cleanCache;
+
+ boolean verboseLogging;
+
+ @Nullable PullPolicy pullPolicy;
+
+ @Nullable Boolean publish;
+
+ @Nullable List buildpacks;
+
+ @Nullable List bindings;
+
+ @Nullable String network;
+
+ @Nullable List tags;
+
+ @Nullable CacheInfo buildWorkspace;
+
+ @Nullable CacheInfo buildCache;
+
+ @Nullable CacheInfo launchCache;
+
+ @Nullable String createdDate;
+
+ @Nullable String applicationDirectory;
+
+ @Nullable List securityOptions;
+
+ @Nullable String imagePlatform;
+
+ /**
+ * The name of the created image.
+ * @return the image name
+ */
+ public @Nullable String getName() {
+ return this.name;
+ }
+
+ void setName(@Nullable String name) {
+ this.name = name;
+ }
+
+ /**
+ * The name of the builder image to use to create the image.
+ * @return the builder image name
+ */
+ public @Nullable String getBuilder() {
+ return this.builder;
+ }
+
+ void setBuilder(@Nullable String builder) {
+ this.builder = builder;
+ }
+
+ /**
+ * If the builder should be treated as trusted.
+ * @return {@code true} if the builder should be treated as trusted
+ */
+ public @Nullable Boolean getTrustBuilder() {
+ return this.trustBuilder;
+ }
+
+ void setTrustBuilder(@Nullable Boolean trustBuilder) {
+ this.trustBuilder = trustBuilder;
+ }
+
+ /**
+ * The name of the run image to use to create the image.
+ * @return the builder image name
+ */
+ public @Nullable String getRunImage() {
+ return this.runImage;
+ }
+
+ void setRunImage(@Nullable String runImage) {
+ this.runImage = runImage;
+ }
+
+ /**
+ * Environment properties that should be passed to the builder.
+ * @return the environment properties
+ */
+ public @Nullable Map getEnv() {
+ return this.env;
+ }
+
+ /**
+ * If the cache should be cleaned before building.
+ * @return {@code true} if the cache should be cleaned
+ */
+ public @Nullable Boolean getCleanCache() {
+ return this.cleanCache;
+ }
+
+ void setCleanCache(@Nullable Boolean cleanCache) {
+ this.cleanCache = cleanCache;
+ }
+
+ /**
+ * If verbose logging is required.
+ * @return {@code true} for verbose logging
+ */
+ public boolean isVerboseLogging() {
+ return this.verboseLogging;
+ }
+
+ /**
+ * If images should be pulled from a remote repository during image build.
+ * @return the pull policy
+ */
+ public @Nullable PullPolicy getPullPolicy() {
+ return this.pullPolicy;
+ }
+
+ void setPullPolicy(@Nullable PullPolicy pullPolicy) {
+ this.pullPolicy = pullPolicy;
+ }
+
+ /**
+ * If the built image should be pushed to a registry.
+ * @return {@code true} if the image should be published
+ */
+ public @Nullable Boolean getPublish() {
+ return this.publish;
+ }
+
+ void setPublish(@Nullable Boolean publish) {
+ this.publish = publish;
+ }
+
+ /**
+ * Returns the network the build container will connect to.
+ * @return the network
+ */
+ public @Nullable String getNetwork() {
+ return this.network;
+ }
+
+ public void setNetwork(@Nullable String network) {
+ this.network = network;
+ }
+
+ /**
+ * Returns the created date for the image.
+ * @return the created date
+ */
+ public @Nullable String getCreatedDate() {
+ return this.createdDate;
+ }
+
+ public void setCreatedDate(@Nullable String createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ /**
+ * Returns the application content directory for the image.
+ * @return the application directory
+ */
+ public @Nullable String getApplicationDirectory() {
+ return this.applicationDirectory;
+ }
+
+ public void setApplicationDirectory(@Nullable String applicationDirectory) {
+ this.applicationDirectory = applicationDirectory;
+ }
+
+ /**
+ * Returns the platform (os/architecture/variant) that will be used for all pulled
+ * images. When {@code null}, the system will choose a platform based on the host
+ * operating system and architecture.
+ * @return the image platform
+ */
+ public @Nullable String getImagePlatform() {
+ return this.imagePlatform;
+ }
+
+ public void setImagePlatform(@Nullable String imagePlatform) {
+ this.imagePlatform = imagePlatform;
+ }
+
+ BuildRequest getBuildRequest(Artifact artifact, Function applicationContent) {
+ return customize(BuildRequest.of(getOrDeduceName(artifact), applicationContent));
+ }
+
+ private ImageReference getOrDeduceName(Artifact artifact) {
+ if (StringUtils.hasText(this.name)) {
+ return ImageReference.of(this.name);
+ }
+ ImageName imageName = ImageName.of(artifact.getArtifactId());
+ return ImageReference.of(imageName, artifact.getVersion());
+ }
+
+ private BuildRequest customize(BuildRequest request) {
+ if (StringUtils.hasText(this.builder)) {
+ request = request.withBuilder(ImageReference.of(this.builder));
+ }
+ if (this.trustBuilder != null) {
+ request = request.withTrustBuilder(this.trustBuilder);
+ }
+ if (StringUtils.hasText(this.runImage)) {
+ request = request.withRunImage(ImageReference.of(this.runImage));
+ }
+ if (!CollectionUtils.isEmpty(this.env)) {
+ request = request.withEnv(this.env);
+ }
+ if (this.cleanCache != null) {
+ request = request.withCleanCache(this.cleanCache);
+ }
+ request = request.withVerboseLogging(this.verboseLogging);
+ if (this.pullPolicy != null) {
+ request = request.withPullPolicy(this.pullPolicy);
+ }
+ if (this.publish != null) {
+ request = request.withPublish(this.publish);
+ }
+ if (!CollectionUtils.isEmpty(this.buildpacks)) {
+ request = request.withBuildpacks(this.buildpacks.stream().map(BuildpackReference::of).toList());
+ }
+ if (!CollectionUtils.isEmpty(this.bindings)) {
+ request = request.withBindings(this.bindings.stream().map(Binding::of).toList());
+ }
+ request = request.withNetwork(this.network);
+ if (!CollectionUtils.isEmpty(this.tags)) {
+ request = request.withTags(this.tags.stream().map(ImageReference::of).toList());
+ }
+ if (this.buildWorkspace != null) {
+ Cache cache = this.buildWorkspace.asCache();
+ Assert.state(cache != null, "'cache' must not be null");
+ request = request.withBuildWorkspace(cache);
+ }
+ if (this.buildCache != null) {
+ Cache cache = this.buildCache.asCache();
+ Assert.state(cache != null, "'cache' must not be null");
+ request = request.withBuildCache(cache);
+ }
+ if (this.launchCache != null) {
+ Cache cache = this.launchCache.asCache();
+ Assert.state(cache != null, "'cache' must not be null");
+ request = request.withLaunchCache(cache);
+ }
+ if (StringUtils.hasText(this.createdDate)) {
+ request = request.withCreatedDate(this.createdDate);
+ }
+ if (StringUtils.hasText(this.applicationDirectory)) {
+ request = request.withApplicationDirectory(this.applicationDirectory);
+ }
+ if (this.securityOptions != null) {
+ request = request.withSecurityOptions(this.securityOptions);
+ }
+ if (StringUtils.hasText(this.imagePlatform)) {
+ request = request.withImagePlatform(this.imagePlatform);
+ }
+ return request;
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Include.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Include.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Include.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Include.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/IncludeFilter.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/IncludeFilter.java
similarity index 100%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/IncludeFilter.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/IncludeFilter.java
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
similarity index 93%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
index c9b0765ebaf5..445debcb6737 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JarTypeFilter.java
@@ -34,8 +34,8 @@
*/
class JarTypeFilter extends DependencyFilter {
- private static final Set EXCLUDED_JAR_TYPES = Collections
- .unmodifiableSet(new HashSet<>(Arrays.asList("annotation-processor", "dependencies-starter")));
+ private static final Set EXCLUDED_JAR_TYPES = Collections.unmodifiableSet(
+ new HashSet<>(Arrays.asList("annotation-processor", "dependencies-starter", "development-tool")));
JarTypeFilter() {
super(Collections.emptyList());
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java
similarity index 82%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java
index 43612027a74a..33e8f0f8dd80 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaCompilerPluginConfiguration.java
@@ -21,6 +21,9 @@
import org.apache.maven.model.Plugin;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.lang.Contract;
/**
* Provides access to the Maven Java Compiler plugin configuration.
@@ -35,7 +38,7 @@ class JavaCompilerPluginConfiguration {
this.project = project;
}
- String getSourceMajorVersion() {
+ @Nullable String getSourceMajorVersion() {
String version = getConfigurationValue("source");
if (version == null) {
@@ -45,7 +48,7 @@ String getSourceMajorVersion() {
return majorVersionFor(version);
}
- String getTargetMajorVersion() {
+ @Nullable String getTargetMajorVersion() {
String version = getConfigurationValue("target");
if (version == null) {
@@ -55,7 +58,7 @@ String getTargetMajorVersion() {
return majorVersionFor(version);
}
- String getReleaseVersion() {
+ @Nullable String getReleaseVersion() {
String version = getConfigurationValue("release");
if (version == null) {
@@ -65,7 +68,7 @@ String getReleaseVersion() {
return majorVersionFor(version);
}
- private String getConfigurationValue(String propertyName) {
+ private @Nullable String getConfigurationValue(String propertyName) {
Plugin plugin = this.project.getPlugin("org.apache.maven.plugins:maven-compiler-plugin");
if (plugin != null) {
Object pluginConfiguration = plugin.getConfiguration();
@@ -76,14 +79,14 @@ private String getConfigurationValue(String propertyName) {
return null;
}
- private String getPropertyValue(String propertyName) {
+ private @Nullable String getPropertyValue(String propertyName) {
if (this.project.getProperties().containsKey(propertyName)) {
return this.project.getProperties().get(propertyName).toString();
}
return null;
}
- private String getNodeValue(Xpp3Dom dom, String... childNames) {
+ private @Nullable String getNodeValue(Xpp3Dom dom, String... childNames) {
Xpp3Dom childNode = dom.getChild(childNames[0]);
if (childNode == null) {
@@ -97,7 +100,8 @@ private String getNodeValue(Xpp3Dom dom, String... childNames) {
return childNode.getValue();
}
- private String majorVersionFor(String version) {
+ @Contract("!null -> !null")
+ private @Nullable String majorVersionFor(@Nullable String version) {
if (version != null && version.startsWith("1.")) {
return version.substring("1.".length());
}
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java
similarity index 95%
rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java
rename to build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java
index 28a019d61407..3b1d7f793278 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java
+++ b/build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java
@@ -26,6 +26,7 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
+import org.jspecify.annotations.Nullable;
import org.springframework.boot.loader.tools.JavaExecutable;
import org.springframework.boot.loader.tools.RunProcess;
@@ -43,14 +44,14 @@ class JavaProcessExecutor {
private final ToolchainManager toolchainManager;
- private final Consumer