Make consistent use of Property for Gradle task configuration

Closes gh-32769
This commit is contained in:
Andy Wilkinson
2022-10-19 17:29:46 +01:00
parent e5c12c2b56
commit 8621be6bba
60 changed files with 554 additions and 960 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 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.
@@ -30,7 +30,6 @@ import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo;
import org.springframework.boot.gradle.tasks.buildinfo.BuildInfoProperties;
/**
* Entry point to Spring Boot's Gradle DSL.
@@ -92,12 +91,8 @@ public class SpringBootExtension {
this::configureBuildInfoTask);
this.project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
tasks.named(JavaPlugin.CLASSES_TASK_NAME).configure((task) -> task.dependsOn(bootBuildInfo));
this.project.afterEvaluate((evaluated) -> bootBuildInfo.configure((buildInfo) -> {
BuildInfoProperties properties = buildInfo.getProperties();
if (properties.getArtifact() == null) {
properties.setArtifact(determineArtifactBaseName());
}
}));
bootBuildInfo.configure((buildInfo) -> buildInfo.getProperties().getArtifact()
.convention(this.project.provider(() -> determineArtifactBaseName())));
});
if (configurer != null) {
bootBuildInfo.configure(configurer);
@@ -107,8 +102,8 @@ public class SpringBootExtension {
private void configureBuildInfoTask(BuildInfo task) {
task.setGroup(BasePlugin.BUILD_GROUP);
task.setDescription("Generates a META-INF/build-info.properties file.");
task.getConventionMapping().map("destinationDir",
() -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF"));
task.getDestinationDir().convention(this.project.getLayout()
.dir(this.project.provider(() -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF"))));
}
private File determineMainSourceSetResourcesOutputDir() {

View File

@@ -89,8 +89,8 @@ class NativeImagePluginAction implements PluginApplicationAction {
private void configureBootBuildImageToProduceANativeImage(Project project) {
project.getTasks().named(SpringBootPlugin.BOOT_BUILD_IMAGE_TASK_NAME, BootBuildImage.class)
.configure((bootBuildImage) -> {
bootBuildImage.setBuilder("paketobuildpacks/builder:tiny");
bootBuildImage.environment("BP_NATIVE_IMAGE", "true");
bootBuildImage.getBuilder().convention("paketobuildpacks/builder:tiny");
bootBuildImage.getEnvironment().put("BP_NATIVE_IMAGE", "true");
});
}

View File

@@ -32,25 +32,20 @@ import org.gradle.api.tasks.TaskAction;
* @since 3.0.0
*/
@CacheableTask
public class ProcessAot extends AbstractAot {
private final Property<String> applicationClass;
public abstract class ProcessAot extends AbstractAot {
public ProcessAot() {
this.applicationClass = getProject().getObjects().property(String.class);
getMainClass().set("org.springframework.boot.SpringApplicationAotProcessor");
}
@Input
public Property<String> getApplicationClass() {
return this.applicationClass;
}
public abstract Property<String> getApplicationClass();
@Override
@TaskAction
public void exec() {
List<String> args = new ArrayList<>();
args.add(this.applicationClass.get());
args.add(getApplicationClass().get());
args.addAll(processorArgs());
this.setArgs(args);
super.exec();

View File

@@ -18,14 +18,13 @@ package org.springframework.boot.gradle.tasks.buildinfo;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.DefaultTask;
import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.internal.ConventionTask;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
@@ -43,28 +42,35 @@ import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetail
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BuildInfo extends ConventionTask {
public abstract class BuildInfo extends DefaultTask {
private final BuildInfoProperties properties = new BuildInfoProperties(getProject());
private final DirectoryProperty destinationDir;
private final BuildInfoProperties properties;
public BuildInfo() {
this.destinationDir = getProject().getObjects().directoryProperty()
.convention(getProject().getLayout().getBuildDirectory());
this.properties = getProject().getObjects().newInstance(BuildInfoProperties.class, getExcludes());
getDestinationDir().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
}
/**
* Returns the names of the properties to exclude from the output.
* @return names of the properties to exclude
* @since 3.0.0
*/
@Internal
public abstract SetProperty<String> getExcludes();
/**
* Generates the {@code build-info.properties} file in the configured
* {@link #setDestinationDir(File) destination}.
* {@link #getDestinationDir destination}.
*/
@TaskAction
public void generateBuildProperties() {
try {
ProjectDetails details = new ProjectDetails(this.properties.getGroup(), this.properties.getArtifact(),
this.properties.getVersion(), this.properties.getName(), this.properties.getTime(),
coerceToStringValues(this.properties.getAdditional()));
new BuildPropertiesWriter(new File(getDestinationDir(), "build-info.properties"))
ProjectDetails details = new ProjectDetails(this.properties.getGroupIfNotExcluded(),
this.properties.getArtifactIfNotExcluded(), this.properties.getVersionIfNotExcluded(),
this.properties.getNameIfNotExcluded(), this.properties.getTimeIfNotExcluded(),
this.properties.getAdditionalIfNotExcluded());
new BuildPropertiesWriter(new File(getDestinationDir().get().getAsFile(), "build-info.properties"))
.writeBuildProperties(details);
}
catch (IOException ex) {
@@ -74,21 +80,11 @@ public class BuildInfo extends ConventionTask {
/**
* Returns the directory to which the {@code build-info.properties} file will be
* written. Defaults to the {@link Project#getBuildDir() Project's build directory}.
* written.
* @return the destination directory
*/
@OutputDirectory
public File getDestinationDir() {
return this.destinationDir.getAsFile().get();
}
/**
* Sets the directory to which the {@code build-info.properties} file will be written.
* @param destinationDir the destination directory
*/
public void setDestinationDir(File destinationDir) {
this.destinationDir.set(destinationDir);
}
public abstract DirectoryProperty getDestinationDir();
/**
* Returns the {@link BuildInfoProperties properties} that will be included in the
@@ -108,10 +104,4 @@ public class BuildInfo extends ConventionTask {
action.execute(this.properties);
}
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
Map<String, String> output = new HashMap<>();
input.forEach((key, value) -> output.put(key, (value != null) ? value.toString() : null));
return output;
}
}

View File

@@ -16,19 +16,27 @@
package org.springframework.boot.gradle.tasks.buildinfo;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import javax.inject.Inject;
import org.gradle.api.Project;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.springframework.util.function.SingletonSupplier;
/**
* The properties that are written into the {@code build-info.properties} file.
*
@@ -36,164 +44,135 @@ import org.gradle.api.tasks.Optional;
* @since 2.0.0
*/
@SuppressWarnings("serial")
public class BuildInfoProperties implements Serializable {
public abstract class BuildInfoProperties implements Serializable {
private transient Instant creationTime = Instant.now();
private final SetProperty<String> excludes;
private final Property<String> group;
private final Supplier<String> creationTime = SingletonSupplier.of(new CurrentIsoInstantSupplier());
private final Property<String> artifact;
private final Property<String> version;
private final Property<String> name;
private final Property<Long> time;
private boolean timeConfigured = false;
private Map<String, Object> additionalProperties = new HashMap<>();
BuildInfoProperties(Project project) {
this.time = project.getObjects().property(Long.class);
this.group = project.getObjects().property(String.class);
this.group.set(project.provider(() -> project.getGroup().toString()));
this.artifact = project.getObjects().property(String.class);
this.version = project.getObjects().property(String.class);
this.version.set(projectVersion(project));
this.name = project.getObjects().property(String.class);
this.name.set(project.provider(project::getName));
}
private Provider<String> projectVersion(Project project) {
return project.provider(() -> project.getVersion().toString());
@Inject
public BuildInfoProperties(Project project, SetProperty<String> excludes) {
this.excludes = excludes;
getGroup().convention(project.provider(() -> project.getGroup().toString()));
getVersion().convention(project.provider(() -> project.getVersion().toString()));
getArtifact()
.convention(project.provider(() -> project.findProperty("archivesBaseName")).map(Object::toString));
getName().convention(project.provider(project::getName));
}
/**
* Returns the value used for the {@code build.group} property. Defaults to the
* {@link Project#getGroup() Project's group}.
* @return the group
* Returns the {@code build.group} property. Defaults to the {@link Project#getGroup()
* Project's group}.
* @return the group property
*/
@Input
@Optional
public String getGroup() {
return this.group.getOrNull();
}
@Internal
public abstract Property<String> getGroup();
/**
* Sets the value used for the {@code build.group} property.
* @param group the group name
* Returns the {@code build.artifact} property.
* @return the artifact property
*/
public void setGroup(String group) {
this.group.set(group);
}
@Internal
public abstract Property<String> getArtifact();
/**
* Returns the value used for the {@code build.artifact} property.
* @return the artifact
*/
@Input
@Optional
public String getArtifact() {
return this.artifact.getOrNull();
}
/**
* Sets the value used for the {@code build.artifact} property.
* @param artifact the artifact
*/
public void setArtifact(String artifact) {
this.artifact.set(artifact);
}
/**
* Returns the value used for the {@code build.version} property. Defaults to the
* Returns the {@code build.version} property. Defaults to the
* {@link Project#getVersion() Project's version}.
* @return the version
*/
@Input
@Optional
public String getVersion() {
return this.version.getOrNull();
}
@Internal
public abstract Property<String> getVersion();
/**
* Sets the value used for the {@code build.version} property.
* @param version the version
*/
public void setVersion(String version) {
this.version.set(version);
}
/**
* Returns the value used for the {@code build.name} property. Defaults to the
* {@link Project#getDisplayName() Project's display name}.
* Returns the {@code build.name} property. Defaults to the {@link Project#getName()
* Project's name}.
* @return the name
*/
@Input
@Optional
public String getName() {
return this.name.getOrNull();
}
@Internal
public abstract Property<String> getName();
/**
* Sets the value used for the {@code build.name} property.
* @param name the name
*/
public void setName(String name) {
this.name.set(name);
}
/**
* Returns the value used for the {@code build.time} property. Defaults to
* {@link Instant#now} when the {@code BuildInfoProperties} instance was created.
* Returns the {@code build.time} property.
* @return the time
*/
@Input
@Optional
public Instant getTime() {
Long epochMillis = this.time.getOrNull();
if (epochMillis != null) {
return Instant.ofEpochMilli(epochMillis);
}
if (this.timeConfigured) {
return null;
}
return this.creationTime;
}
/**
* Sets the value used for the {@code build.time} property.
* @param time the build time
*/
public void setTime(Instant time) {
this.timeConfigured = true;
this.time.set((time != null) ? time.toEpochMilli() : null);
}
@Internal
public abstract Property<String> getTime();
/**
* Returns the additional properties that will be included. When written, the name of
* each additional property is prefixed with {@code build.}.
* @return the additional properties
*/
@Internal
public abstract MapProperty<String, Object> getAdditional();
@Input
@Optional
public Map<String, Object> getAdditional() {
return this.additionalProperties;
String getArtifactIfNotExcluded() {
return getIfNotExcluded(getArtifact(), "artifact");
}
/**
* Sets the additional properties that will be included. When written, the name of
* each additional property is prefixed with {@code build.}.
* @param additionalProperties the additional properties
*/
public void setAdditional(Map<String, Object> additionalProperties) {
this.additionalProperties = additionalProperties;
@Input
@Optional
String getGroupIfNotExcluded() {
return getIfNotExcluded(getGroup(), "group");
}
private void readObject(ObjectInputStream input) throws ClassNotFoundException, IOException {
input.defaultReadObject();
this.creationTime = Instant.now();
@Input
@Optional
String getNameIfNotExcluded() {
return getIfNotExcluded(getName(), "name");
}
@Input
@Optional
Instant getTimeIfNotExcluded() {
String time = getIfNotExcluded(getTime(), "time", this.creationTime);
return (time != null) ? Instant.parse(time) : null;
}
@Input
@Optional
String getVersionIfNotExcluded() {
return getIfNotExcluded(getVersion(), "version");
}
@Input
Map<String, String> getAdditionalIfNotExcluded() {
return coerceToStringValues(applyExclusions(getAdditional().getOrElse(Collections.emptyMap())));
}
private <T> T getIfNotExcluded(Property<T> property, String name) {
return getIfNotExcluded(property, name, () -> null);
}
private <T> T getIfNotExcluded(Property<T> property, String name, Supplier<T> defaultValue) {
if (this.excludes.getOrElse(Collections.emptySet()).contains(name)) {
return null;
}
return property.getOrElse(defaultValue.get());
}
private Map<String, String> coerceToStringValues(Map<String, Object> input) {
Map<String, String> output = new HashMap<>();
input.forEach((key, value) -> output.put(key, (value != null) ? value.toString() : null));
return output;
}
private Map<String, Object> applyExclusions(Map<String, Object> input) {
Map<String, Object> output = new HashMap<>();
Set<String> exclusions = this.excludes.getOrElse(Collections.emptySet());
input.forEach((key, value) -> output.put(key, (!exclusions.contains(key)) ? value : null));
return output;
}
private static final class CurrentIsoInstantSupplier implements Supplier<String> {
@Override
public String get() {
return DateTimeFormatter.ISO_INSTANT.format(Instant.now());
}
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.boot.gradle.tasks.bundling;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,6 +27,7 @@ import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
@@ -64,42 +64,12 @@ import org.springframework.util.StringUtils;
* @since 2.3.0
*/
@DisableCachingByDefault
public class BootBuildImage extends DefaultTask {
public abstract class BootBuildImage extends DefaultTask {
private static final String BUILDPACK_JVM_VERSION_KEY = "BP_JVM_VERSION";
private final String projectName;
private final Property<String> projectVersion;
private RegularFileProperty archiveFile;
private Property<JavaVersion> targetJavaVersion;
private String imageName;
private String builder;
private String runImage;
private Map<String, String> environment = new HashMap<>();
private boolean cleanCache;
private boolean verboseLogging;
private PullPolicy pullPolicy;
private boolean publish;
private final ListProperty<String> buildpacks;
private final ListProperty<String> bindings;
private String network;
private final ListProperty<String> tags;
private final CacheSpec buildCache;
private final CacheSpec launchCache;
@@ -107,15 +77,20 @@ public class BootBuildImage extends DefaultTask {
private final DockerSpec docker;
public BootBuildImage() {
this.archiveFile = getProject().getObjects().fileProperty();
this.targetJavaVersion = getProject().getObjects().property(JavaVersion.class);
this.projectName = getProject().getName();
this.projectVersion = getProject().getObjects().property(String.class);
Project project = getProject();
this.projectVersion.set(getProject().provider(() -> project.getVersion().toString()));
this.buildpacks = getProject().getObjects().listProperty(String.class);
this.bindings = getProject().getObjects().listProperty(String.class);
this.tags = getProject().getObjects().listProperty(String.class);
Property<String> projectVersion = project.getObjects().property(String.class)
.convention(project.provider(() -> project.getVersion().toString()));
getImageName().convention(project.provider(() -> {
ImageName imageName = ImageName.of(this.projectName);
if ("unspecified".equals(projectVersion.get())) {
return ImageReference.of(imageName).toString();
}
return ImageReference.of(imageName, projectVersion.get()).toString();
}));
getCleanCache().convention(false);
getVerboseLogging().convention(false);
getPublish().convention(false);
this.buildCache = getProject().getObjects().newInstance(CacheSpec.class);
this.launchCache = getProject().getObjects().newInstance(CacheSpec.class);
this.docker = getProject().getObjects().newInstance(DockerSpec.class);
@@ -127,9 +102,7 @@ public class BootBuildImage extends DefaultTask {
*/
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
public RegularFileProperty getArchiveFile() {
return this.archiveFile;
}
public abstract RegularFileProperty getArchiveFile();
/**
* Returns the target Java version of the project (e.g. as provided by the
@@ -138,9 +111,7 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public Property<JavaVersion> getTargetJavaVersion() {
return this.targetJavaVersion;
}
public abstract Property<JavaVersion> getTargetJavaVersion();
/**
* Returns the name of the image that will be built. When {@code null}, the name will
@@ -150,18 +121,8 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public String getImageName() {
return determineImageReference().toString();
}
/**
* Sets the name of the image that will be built.
* @param imageName name of the image
*/
@Option(option = "imageName", description = "The name of the image to generate")
public void setImageName(String imageName) {
this.imageName = imageName;
}
public abstract Property<String> getImageName();
/**
* Returns the builder that will be used to build the image. When {@code null}, the
@@ -170,18 +131,8 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public String getBuilder() {
return this.builder;
}
/**
* Sets the builder that will be used to build the image.
* @param builder the builder
*/
@Option(option = "builder", description = "The name of the builder image to use")
public void setBuilder(String builder) {
this.builder = builder;
}
public abstract Property<String> getBuilder();
/**
* Returns the run image that will be included in the built image. When {@code null},
@@ -190,88 +141,32 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public String getRunImage() {
return this.runImage;
}
/**
* Sets the run image that will be included in the built image.
* @param runImage the run image
*/
@Option(option = "runImage", description = "The name of the run image to use")
public void setRunImage(String runImage) {
this.runImage = runImage;
}
public abstract Property<String> getRunImage();
/**
* Returns the environment that will be used when building the image.
* @return the environment
*/
@Input
public Map<String, String> getEnvironment() {
return this.environment;
}
/**
* Sets the environment that will be used when building the image.
* @param environment the environment
*/
public void setEnvironment(Map<String, String> environment) {
this.environment = environment;
}
/**
* Add an entry to the environment that will be used when building the image.
* @param name the name of the entry
* @param value the value of the entry
*/
public void environment(String name, String value) {
this.environment.put(name, value);
}
/**
* Adds entries to the environment that will be used when building the image.
* @param entries the entries to add to the environment
*/
public void environment(Map<String, String> entries) {
this.environment.putAll(entries);
}
public abstract MapProperty<String, String> getEnvironment();
/**
* Returns whether caches should be cleaned before packaging.
* @return whether caches should be cleaned
* @since 3.0.0
*/
@Input
public boolean isCleanCache() {
return this.cleanCache;
}
/**
* Sets whether caches should be cleaned before packaging.
* @param cleanCache {@code true} to clean the cache, otherwise {@code false}.
*/
@Option(option = "cleanCache", description = "Clean caches before packaging")
public void setCleanCache(boolean cleanCache) {
this.cleanCache = cleanCache;
}
public abstract Property<Boolean> getCleanCache();
/**
* Whether verbose logging should be enabled while building the image.
* @return whether verbose logging should be enabled
* @since 3.0.0
*/
@Input
public boolean isVerboseLogging() {
return this.verboseLogging;
}
/**
* Sets whether verbose logging should be enabled while building the image.
* @param verboseLogging {@code true} to enable verbose logging, otherwise
* {@code false}.
*/
public void setVerboseLogging(boolean verboseLogging) {
this.verboseLogging = verboseLogging;
}
public abstract Property<Boolean> getVerboseLogging();
/**
* Returns image pull policy that will be used when building the image.
@@ -279,36 +174,17 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public PullPolicy getPullPolicy() {
return this.pullPolicy;
}
/**
* Sets image pull policy that will be used when building the image.
* @param pullPolicy image pull policy {@link PullPolicy}
*/
@Option(option = "pullPolicy", description = "The image pull policy")
public void setPullPolicy(PullPolicy pullPolicy) {
this.pullPolicy = pullPolicy;
}
public abstract Property<PullPolicy> getPullPolicy();
/**
* Whether the built image should be pushed to a registry.
* @return whether the built image should be pushed
* @since 3.0.0
*/
@Input
public boolean isPublish() {
return this.publish;
}
/**
* Sets whether the built image should be pushed to a registry.
* @param publish {@code true} the push the built image to a registry. {@code false}.
*/
@Option(option = "publishImage", description = "Publish the built image to a registry")
public void setPublish(boolean publish) {
this.publish = publish;
}
public abstract Property<Boolean> getPublish();
/**
* Returns the buildpacks that will be used when building the image.
@@ -316,33 +192,7 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public List<String> getBuildpacks() {
return this.buildpacks.getOrNull();
}
/**
* Sets the buildpacks that will be used when building the image.
* @param buildpacks the buildpack references
*/
public void setBuildpacks(List<String> buildpacks) {
this.buildpacks.set(buildpacks);
}
/**
* Add an entry to the buildpacks that will be used when building the image.
* @param buildpack the buildpack reference
*/
public void buildpack(String buildpack) {
this.buildpacks.add(buildpack);
}
/**
* Adds entries to the buildpacks that will be used when building the image.
* @param buildpacks the buildpack references
*/
public void buildpacks(List<String> buildpacks) {
this.buildpacks.addAll(buildpacks);
}
public abstract ListProperty<String> getBuildpacks();
/**
* Returns the volume bindings that will be mounted to the container when building the
@@ -351,36 +201,7 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public List<String> getBindings() {
return this.bindings.getOrNull();
}
/**
* Sets the volume bindings that will be mounted to the container when building the
* image.
* @param bindings the bindings
*/
public void setBindings(List<String> bindings) {
this.bindings.set(bindings);
}
/**
* Add an entry to the volume bindings that will be mounted to the container when
* building the image.
* @param binding the binding
*/
public void binding(String binding) {
this.bindings.add(binding);
}
/**
* Add entries to the volume bindings that will be mounted to the container when
* building the image.
* @param bindings the bindings
*/
public void bindings(List<String> bindings) {
this.bindings.addAll(bindings);
}
public abstract ListProperty<String> getBindings();
/**
* Returns the tags that will be created for the built image.
@@ -388,33 +209,7 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public List<String> getTags() {
return this.tags.getOrNull();
}
/**
* Sets the tags that will be created for the built image.
* @param tags the tags
*/
public void setTags(List<String> tags) {
this.tags.set(tags);
}
/**
* Add an entry to the tags that will be created for the built image.
* @param tag the tag
*/
public void tag(String tag) {
this.tags.add(tag);
}
/**
* Add entries to the tags that will be created for the built image.
* @param tags the tags
*/
public void tags(List<String> tags) {
this.tags.addAll(tags);
}
public abstract ListProperty<String> getTags();
/**
* Returns the network the build container will connect to.
@@ -422,18 +217,8 @@ public class BootBuildImage extends DefaultTask {
*/
@Input
@Optional
public String getNetwork() {
return this.network;
}
/**
* Sets the network the build container will connect to.
* @param network the network
*/
@Option(option = "network", description = "Connect detect and build containers to network")
public void setNetwork(String network) {
this.network = network;
}
public abstract Property<String> getNetwork();
/**
* Returns the build cache that will be used when building the image.
@@ -500,19 +285,8 @@ public class BootBuildImage extends DefaultTask {
}
BuildRequest createRequest() {
return customize(BuildRequest.of(determineImageReference(),
(owner) -> new ZipFileTarArchive(this.archiveFile.get().getAsFile(), owner)));
}
private ImageReference determineImageReference() {
if (StringUtils.hasText(this.imageName)) {
return ImageReference.of(this.imageName);
}
ImageName imageName = ImageName.of(this.projectName);
if ("unspecified".equals(this.projectVersion.get())) {
return ImageReference.of(imageName);
}
return ImageReference.of(imageName, this.projectVersion.get());
return customize(BuildRequest.of(getImageName().map(ImageReference::of).get(),
(owner) -> new ZipFileTarArchive(getArchiveFile().get().getAsFile(), owner)));
}
private BuildRequest customize(BuildRequest request) {
@@ -520,37 +294,40 @@ public class BootBuildImage extends DefaultTask {
request = customizeRunImage(request);
request = customizeEnvironment(request);
request = customizeCreator(request);
request = request.withCleanCache(this.cleanCache);
request = request.withVerboseLogging(this.verboseLogging);
request = request.withCleanCache(getCleanCache().get());
request = request.withVerboseLogging(getVerboseLogging().get());
request = customizePullPolicy(request);
request = customizePublish(request);
request = customizeBuildpacks(request);
request = customizeBindings(request);
request = customizeTags(request);
request = customizeCaches(request);
request = request.withNetwork(this.network);
request = request.withNetwork(getNetwork().getOrNull());
return request;
}
private BuildRequest customizeBuilder(BuildRequest request) {
if (StringUtils.hasText(this.builder)) {
return request.withBuilder(ImageReference.of(this.builder));
String builder = this.getBuilder().getOrNull();
if (StringUtils.hasText(builder)) {
return request.withBuilder(ImageReference.of(builder));
}
return request;
}
private BuildRequest customizeRunImage(BuildRequest request) {
if (StringUtils.hasText(this.runImage)) {
return request.withRunImage(ImageReference.of(this.runImage));
String runImage = this.getRunImage().getOrNull();
if (StringUtils.hasText(runImage)) {
return request.withRunImage(ImageReference.of(runImage));
}
return request;
}
private BuildRequest customizeEnvironment(BuildRequest request) {
if (this.environment != null && !this.environment.isEmpty()) {
request = request.withEnv(this.environment);
Map<String, String> environment = this.getEnvironment().getOrNull();
if (environment != null && !environment.isEmpty()) {
request = request.withEnv(environment);
}
if (this.targetJavaVersion.isPresent() && !request.getEnv().containsKey(BUILDPACK_JVM_VERSION_KEY)) {
if (this.getTargetJavaVersion().isPresent() && !request.getEnv().containsKey(BUILDPACK_JVM_VERSION_KEY)) {
request = request.withEnv(BUILDPACK_JVM_VERSION_KEY, translateTargetJavaVersion());
}
return request;
@@ -565,19 +342,20 @@ public class BootBuildImage extends DefaultTask {
}
private BuildRequest customizePullPolicy(BuildRequest request) {
if (this.pullPolicy != null) {
request = request.withPullPolicy(this.pullPolicy);
PullPolicy pullPolicy = getPullPolicy().getOrNull();
if (pullPolicy != null) {
request = request.withPullPolicy(pullPolicy);
}
return request;
}
private BuildRequest customizePublish(BuildRequest request) {
request = request.withPublish(this.publish);
request = request.withPublish(getPublish().get());
return request;
}
private BuildRequest customizeBuildpacks(BuildRequest request) {
List<String> buildpacks = this.buildpacks.getOrNull();
List<String> buildpacks = getBuildpacks().getOrNull();
if (buildpacks != null && !buildpacks.isEmpty()) {
return request.withBuildpacks(buildpacks.stream().map(BuildpackReference::of).toList());
}
@@ -585,7 +363,7 @@ public class BootBuildImage extends DefaultTask {
}
private BuildRequest customizeBindings(BuildRequest request) {
List<String> bindings = this.bindings.getOrNull();
List<String> bindings = getBindings().getOrNull();
if (bindings != null && !bindings.isEmpty()) {
return request.withBindings(bindings.stream().map(Binding::of).toList());
}
@@ -593,7 +371,7 @@ public class BootBuildImage extends DefaultTask {
}
private BuildRequest customizeTags(BuildRequest request) {
List<String> tags = this.tags.getOrNull();
List<String> tags = getTags().getOrNull();
if (tags != null && !tags.isEmpty()) {
return request.withTags(tags.stream().map(ImageReference::of).toList());
}
@@ -611,7 +389,7 @@ public class BootBuildImage extends DefaultTask {
}
private String translateTargetJavaVersion() {
return this.targetJavaVersion.get().getMajorVersion() + ".*";
return this.getTargetJavaVersion().get().getMajorVersion() + ".*";
}
}

View File

@@ -29,7 +29,6 @@ import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.internal.file.copy.CopyAction;
import org.gradle.api.provider.Property;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
@@ -46,7 +45,7 @@ import org.gradle.work.DisableCachingByDefault;
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BootJar extends Jar implements BootArchive {
public abstract class BootJar extends Jar implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.JarLauncher";
@@ -64,8 +63,6 @@ public class BootJar extends Jar implements BootArchive {
private final CopySpec bootInfSpec;
private final Property<String> mainClass;
private final LayeredSpec layered;
private FileCollection classpath;
@@ -77,7 +74,6 @@ public class BootJar extends Jar implements BootArchive {
this.support = new BootArchiveSupport(LAUNCHER, new LibrarySpec(), new ZipCompressionResolver());
Project project = getProject();
this.bootInfSpec = project.copySpec().into("BOOT-INF");
this.mainClass = project.getObjects().property(String.class);
this.layered = project.getObjects().newInstance(LayeredSpec.class);
configureBootInfSpec(this.bootInfSpec);
getMainSpec().with(this.bootInfSpec);
@@ -128,24 +124,19 @@ public class BootJar extends Jar implements BootArchive {
}
private boolean isLayeredDisabled() {
return this.layered != null && !this.layered.isEnabled();
return !getLayered().getEnabled().get();
}
@Override
protected CopyAction createCopyAction() {
if (!isLayeredDisabled()) {
LayerResolver layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
String layerToolsLocation = this.layered.isIncludeLayerTools() ? LIB_DIRECTORY : null;
String layerToolsLocation = this.layered.getIncludeLayerTools().get() ? LIB_DIRECTORY : null;
return this.support.createCopyAction(this, this.resolvedDependencies, layerResolver, layerToolsLocation);
}
return this.support.createCopyAction(this, this.resolvedDependencies);
}
@Override
public Property<String> getMainClass() {
return this.mainClass;
}
@Override
public void requiresUnpack(String... patterns) {
this.support.requiresUnpack(patterns);

View File

@@ -28,7 +28,6 @@ import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.internal.file.copy.CopyAction;
import org.gradle.api.provider.Property;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Internal;
@@ -46,7 +45,7 @@ import org.gradle.work.DisableCachingByDefault;
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BootWar extends War implements BootArchive {
public abstract class BootWar extends War implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.WarLauncher";
@@ -62,8 +61,6 @@ public class BootWar extends War implements BootArchive {
private final BootArchiveSupport support;
private final Property<String> mainClass;
private final ResolvedDependencies resolvedDependencies = new ResolvedDependencies();
private final LayeredSpec layered;
@@ -76,7 +73,6 @@ public class BootWar extends War implements BootArchive {
public BootWar() {
this.support = new BootArchiveSupport(LAUNCHER, new LibrarySpec(), new ZipCompressionResolver());
Project project = getProject();
this.mainClass = project.getObjects().property(String.class);
this.layered = project.getObjects().newInstance(LayeredSpec.class);
getWebInf().into("lib-provided", fromCallTo(this::getProvidedLibFiles));
this.support.moveModuleInfoToRoot(getRootSpec());
@@ -103,24 +99,19 @@ public class BootWar extends War implements BootArchive {
}
private boolean isLayeredDisabled() {
return this.layered != null && !this.layered.isEnabled();
return !this.layered.getEnabled().get();
}
@Override
protected CopyAction createCopyAction() {
if (!isLayeredDisabled()) {
LayerResolver layerResolver = new LayerResolver(this.resolvedDependencies, this.layered, this::isLibrary);
String layerToolsLocation = this.layered.isIncludeLayerTools() ? LIB_DIRECTORY : null;
String layerToolsLocation = this.layered.getIncludeLayerTools().get() ? LIB_DIRECTORY : null;
return this.support.createCopyAction(this, this.resolvedDependencies, layerResolver, layerToolsLocation);
}
return this.support.createCopyAction(this, this.resolvedDependencies);
}
@Override
public Property<String> getMainClass() {
return this.mainClass;
}
@Override
public void requiresUnpack(String... patterns) {
this.support.requiresUnpack(patterns);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-2022 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.
@@ -20,6 +20,8 @@ import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.springframework.boot.buildpack.platform.build.Cache;
@@ -32,11 +34,13 @@ import org.springframework.boot.buildpack.platform.build.Cache;
*/
public class CacheSpec {
private final ObjectFactory objectFactory;
private Cache cache = null;
@Inject
public CacheSpec() {
public CacheSpec(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
public Cache asCache() {
@@ -51,34 +55,22 @@ public class CacheSpec {
if (this.cache != null) {
throw new GradleException("Each image building cache can be configured only once");
}
VolumeCacheSpec spec = new VolumeCacheSpec();
VolumeCacheSpec spec = this.objectFactory.newInstance(VolumeCacheSpec.class);
action.execute(spec);
this.cache = Cache.volume(spec.getName());
this.cache = Cache.volume(spec.getName().get());
}
/**
* Configuration for an image building cache stored in a Docker volume.
*/
public static class VolumeCacheSpec {
private String name;
public abstract static class VolumeCacheSpec {
/**
* Returns the name of the cache.
* @return the cache name
*/
@Input
public String getName() {
return this.name;
}
/**
* Sets the name of the cache.
* @param name the cache name
*/
public void setName(String name) {
this.name = name;
}
public abstract Property<String> getName();
}

View File

@@ -16,8 +16,12 @@
package org.springframework.boot.gradle.tasks.bundling;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
@@ -31,23 +35,18 @@ import org.springframework.boot.buildpack.platform.docker.configuration.DockerCo
* @author Scott Frederick
* @since 2.4.0
*/
public class DockerSpec {
private String host;
private boolean tlsVerify;
private String certPath;
private boolean bindHostToBuilder;
public abstract class DockerSpec {
private final DockerRegistrySpec builderRegistry;
private final DockerRegistrySpec publishRegistry;
public DockerSpec() {
this.builderRegistry = new DockerRegistrySpec();
this.publishRegistry = new DockerRegistrySpec();
@Inject
public DockerSpec(ObjectFactory objects) {
this.builderRegistry = objects.newInstance(DockerRegistrySpec.class);
this.publishRegistry = objects.newInstance(DockerRegistrySpec.class);
getBindHostToBuilder().convention(false);
getTlsVerify().convention(false);
}
DockerSpec(DockerRegistrySpec builderRegistry, DockerRegistrySpec publishRegistry) {
@@ -57,43 +56,19 @@ public class DockerSpec {
@Input
@Optional
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public abstract Property<String> getHost();
@Input
@Optional
public Boolean isTlsVerify() {
return this.tlsVerify;
}
public void setTlsVerify(boolean tlsVerify) {
this.tlsVerify = tlsVerify;
}
public abstract Property<Boolean> getTlsVerify();
@Input
@Optional
public String getCertPath() {
return this.certPath;
}
public void setCertPath(String certPath) {
this.certPath = certPath;
}
public abstract Property<String> getCertPath();
@Input
@Optional
public Boolean isBindHostToBuilder() {
return this.bindHostToBuilder;
}
public void setBindHostToBuilder(boolean use) {
this.bindHostToBuilder = use;
}
public abstract Property<Boolean> getBindHostToBuilder();
/**
* Returns the {@link DockerRegistrySpec} that configures authentication to the
@@ -142,15 +117,16 @@ public class DockerSpec {
DockerConfiguration asDockerConfiguration() {
DockerConfiguration dockerConfiguration = new DockerConfiguration();
dockerConfiguration = customizeHost(dockerConfiguration);
dockerConfiguration = dockerConfiguration.withBindHostToBuilder(this.bindHostToBuilder);
dockerConfiguration = dockerConfiguration.withBindHostToBuilder(getBindHostToBuilder().get());
dockerConfiguration = customizeBuilderAuthentication(dockerConfiguration);
dockerConfiguration = customizePublishAuthentication(dockerConfiguration);
return dockerConfiguration;
}
private DockerConfiguration customizeHost(DockerConfiguration dockerConfiguration) {
if (this.host != null) {
return dockerConfiguration.withHost(this.host, this.tlsVerify, this.certPath);
String host = getHost().getOrNull();
if (host != null) {
return dockerConfiguration.withHost(host, getTlsVerify().get(), getCertPath().getOrNull());
}
return dockerConfiguration;
}
@@ -160,11 +136,12 @@ public class DockerSpec {
return dockerConfiguration;
}
if (this.builderRegistry.hasTokenAuth() && !this.builderRegistry.hasUserAuth()) {
return dockerConfiguration.withBuilderRegistryTokenAuthentication(this.builderRegistry.getToken());
return dockerConfiguration.withBuilderRegistryTokenAuthentication(this.builderRegistry.getToken().get());
}
if (this.builderRegistry.hasUserAuth() && !this.builderRegistry.hasTokenAuth()) {
return dockerConfiguration.withBuilderRegistryUserAuthentication(this.builderRegistry.getUsername(),
this.builderRegistry.getPassword(), this.builderRegistry.getUrl(), this.builderRegistry.getEmail());
return dockerConfiguration.withBuilderRegistryUserAuthentication(this.builderRegistry.getUsername().get(),
this.builderRegistry.getPassword().get(), this.builderRegistry.getUrl().getOrNull(),
this.builderRegistry.getEmail().getOrNull());
}
throw new GradleException(
"Invalid Docker builder registry configuration, either token or username/password must be provided");
@@ -175,11 +152,12 @@ public class DockerSpec {
return dockerConfiguration.withEmptyPublishRegistryAuthentication();
}
if (this.publishRegistry.hasTokenAuth() && !this.publishRegistry.hasUserAuth()) {
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken());
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken().get());
}
if (this.publishRegistry.hasUserAuth() && !this.publishRegistry.hasTokenAuth()) {
return dockerConfiguration.withPublishRegistryUserAuthentication(this.publishRegistry.getUsername(),
this.publishRegistry.getPassword(), this.publishRegistry.getUrl(), this.publishRegistry.getEmail());
return dockerConfiguration.withPublishRegistryUserAuthentication(this.publishRegistry.getUsername().get(),
this.publishRegistry.getPassword().get(), this.publishRegistry.getUrl().getOrNull(),
this.publishRegistry.getEmail().getOrNull());
}
throw new GradleException(
"Invalid Docker publish registry configuration, either token or username/password must be provided");
@@ -188,31 +166,7 @@ public class DockerSpec {
/**
* Encapsulates Docker registry authentication configuration options.
*/
public static class DockerRegistrySpec {
private String username;
private String password;
private String url;
private String email;
private String token;
public DockerRegistrySpec() {
}
DockerRegistrySpec(String username, String password, String url, String email) {
this.username = username;
this.password = password;
this.url = url;
this.email = email;
}
DockerRegistrySpec(String token) {
this.token = token;
}
public abstract static class DockerRegistrySpec {
/**
* Returns the username to use when authenticating to the Docker registry.
@@ -220,17 +174,7 @@ public class DockerSpec {
*/
@Input
@Optional
public String getUsername() {
return this.username;
}
/**
* Sets the username to use when authenticating to the Docker registry.
* @param username the registry username
*/
public void setUsername(String username) {
this.username = username;
}
public abstract Property<String> getUsername();
/**
* Returns the password to use when authenticating to the Docker registry.
@@ -238,17 +182,7 @@ public class DockerSpec {
*/
@Input
@Optional
public String getPassword() {
return this.password;
}
/**
* Sets the password to use when authenticating to the Docker registry.
* @param password the registry username
*/
public void setPassword(String password) {
this.password = password;
}
public abstract Property<String> getPassword();
/**
* Returns the Docker registry URL.
@@ -256,17 +190,7 @@ public class DockerSpec {
*/
@Input
@Optional
public String getUrl() {
return this.url;
}
/**
* Sets the Docker registry URL.
* @param url the registry URL
*/
public void setUrl(String url) {
this.url = url;
}
public abstract Property<String> getUrl();
/**
* Returns the email address associated with the Docker registry username.
@@ -274,17 +198,7 @@ public class DockerSpec {
*/
@Input
@Optional
public String getEmail() {
return this.email;
}
/**
* Sets the email address associated with the Docker registry username.
* @param email the registry email address
*/
public void setEmail(String email) {
this.email = email;
}
public abstract Property<String> getEmail();
/**
* Returns the identity token to use when authenticating to the Docker registry.
@@ -292,29 +206,36 @@ public class DockerSpec {
*/
@Input
@Optional
public String getToken() {
return this.token;
}
/**
* Sets the identity token to use when authenticating to the Docker registry.
* @param token the registry identity token
*/
public void setToken(String token) {
this.token = token;
}
public abstract Property<String> getToken();
boolean hasEmptyAuth() {
return this.username == null && this.password == null && this.url == null && this.email == null
&& this.token == null;
return nonePresent(getUsername(), getPassword(), getUrl(), getEmail(), getToken());
}
private boolean nonePresent(Property<?>... properties) {
for (Property<?> property : properties) {
if (property.isPresent()) {
return false;
}
}
return true;
}
boolean hasUserAuth() {
return this.getUsername() != null && this.getPassword() != null;
return allPresent(getUsername(), getPassword());
}
private boolean allPresent(Property<?>... properties) {
for (Property<?> property : properties) {
if (!property.isPresent()) {
return false;
}
}
return true;
}
boolean hasTokenAuth() {
return this.getToken() != null;
return this.getToken().isPresent();
}
}

View File

@@ -27,6 +27,8 @@ import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
@@ -49,64 +51,38 @@ import org.springframework.util.Assert;
* @author Phillip Webb
* @since 2.3.0
*/
public class LayeredSpec {
private boolean includeLayerTools = true;
private boolean enabled = true;
public abstract class LayeredSpec {
private ApplicationSpec application;
private DependenciesSpec dependencies;
@Optional
private List<String> layerOrder;
private Layers layers;
@Inject
public LayeredSpec(ObjectFactory objects) {
this.application = objects.newInstance(ApplicationSpec.class);
this.dependencies = objects.newInstance(DependenciesSpec.class);
getEnabled().convention(true);
getIncludeLayerTools().convention(true);
}
/**
* Returns whether the layer tools should be included as a dependency in the layered
* archive.
* @return whether the layer tools should be included
* @since 3.0.0
*/
@Input
public boolean isIncludeLayerTools() {
return this.includeLayerTools;
}
/**
* Sets whether the layer tools should be included as a dependency in the layered
* archive.
* @param includeLayerTools {@code true} if the layer tools should be included,
* otherwise {@code false}
*/
public void setIncludeLayerTools(boolean includeLayerTools) {
this.includeLayerTools = includeLayerTools;
}
public abstract Property<Boolean> getIncludeLayerTools();
/**
* Returns whether the layers.idx should be included in the archive.
* @return whether the layers.idx should be included
* @since 3.0.0
*/
@Input
public boolean isEnabled() {
return this.enabled;
}
/**
* Sets whether the layers.idx should be included in the archive.
* @param enabled {@code true} layers.idx should be included in the archive, otherwise
* {@code false}
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public abstract Property<Boolean> getEnabled();
/**
* Returns the {@link ApplicationSpec} that controls the layers to which application
@@ -168,25 +144,8 @@ public class LayeredSpec {
* @return the layer order
*/
@Input
public List<String> getLayerOrder() {
return this.layerOrder;
}
/**
* Sets the order of the layers in the archive from least to most frequently changing.
* @param layerOrder the layer order
*/
public void setLayerOrder(String... layerOrder) {
this.layerOrder = Arrays.asList(layerOrder);
}
/**
* Sets the order of the layers in the archive from least to most frequently changing.
* @param layerOrder the layer order
*/
public void setLayerOrder(List<String> layerOrder) {
this.layerOrder = layerOrder;
}
@Optional
public abstract ListProperty<String> getLayerOrder();
/**
* Return this configuration as a {@link Layers} instance. This method should only be
@@ -203,12 +162,13 @@ public class LayeredSpec {
}
private Layers createLayers() {
if (this.layerOrder == null || this.layerOrder.isEmpty()) {
List<String> layerOrder = getLayerOrder().getOrNull();
if (layerOrder == null || layerOrder.isEmpty()) {
Assert.state(this.application.isEmpty() && this.dependencies.isEmpty(),
"The 'layerOrder' must be defined when using custom layering");
return Layers.IMPLICIT;
}
List<Layer> layers = this.layerOrder.stream().map(Layer::new).toList();
List<Layer> layers = layerOrder.stream().map(Layer::new).toList();
return new CustomLayers(layers, this.application.asSelectors(), this.dependencies.asSelectors());
}

View File

@@ -20,6 +20,7 @@ import java.io.File;
import java.util.Set;
import org.gradle.api.file.SourceDirectorySet;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.SourceSet;
@@ -33,30 +34,20 @@ import org.gradle.work.DisableCachingByDefault;
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Application should always run")
public class BootRun extends JavaExec {
public abstract class BootRun extends JavaExec {
private boolean optimizedLaunch = true;
public BootRun() {
getOptimizedLaunch().convention(true);
}
/**
* Returns {@code true} if the JVM's launch should be optimized, otherwise
* {@code false}. Defaults to {@code true}.
* Returns the property for whether the JVM's launch should be optimized. The property
* defaults to {@code true}.
* @return whether the JVM's launch should be optimized
* @since 2.2.0
* @since 3.0.0
*/
@Input
public boolean isOptimizedLaunch() {
return this.optimizedLaunch;
}
/**
* Sets whether the JVM's launch should be optimized. Defaults to {@code true}.
* @param optimizedLaunch {@code true} if the JVM's launch should be optimised,
* otherwise {@code false}
* @since 2.2.0
*/
public void setOptimizedLaunch(boolean optimizedLaunch) {
this.optimizedLaunch = optimizedLaunch;
}
public abstract Property<Boolean> getOptimizedLaunch();
/**
* Adds the {@link SourceDirectorySet#getSrcDirs() source directories} of the given
@@ -73,7 +64,7 @@ public class BootRun extends JavaExec {
@Override
public void exec() {
if (this.optimizedLaunch) {
if (this.getOptimizedLaunch().get()) {
setJvmArgs(getJvmArgs());
jvmArgs("-XX:TieredStopAtLevel=1");
}