Make buildSrc's custom Gradle tasks consistently abstract

Closes gh-41272
This commit is contained in:
Andy Wilkinson 2024-06-28 12:44:36 +01:00
parent 86fa2296e2
commit d71fdd9712
30 changed files with 277 additions and 514 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2022 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,15 +21,13 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException; import org.gradle.api.GradleException;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
@ -42,54 +40,30 @@ import org.springframework.util.PropertyPlaceholderHelper;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class ExtractResources extends DefaultTask { public abstract class ExtractResources extends DefaultTask {
private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("${", "}"); private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("${", "}");
private final Map<String, String> properties = new HashMap<>();
private final DirectoryProperty destinationDirectory;
private List<String> resourceNames = new ArrayList<>();
public ExtractResources() {
this.destinationDirectory = getProject().getObjects().directoryProperty();
}
@Input @Input
public List<String> getResourceNames() { public abstract ListProperty<String> getResourceNames();
return this.resourceNames;
}
public void setResourcesNames(List<String> resourceNames) {
this.resourceNames = resourceNames;
}
@OutputDirectory @OutputDirectory
public DirectoryProperty getDestinationDirectory() { public abstract DirectoryProperty getDestinationDirectory();
return this.destinationDirectory;
}
public void property(String name, String value) {
this.properties.put(name, value);
}
@Input @Input
public Map<String, String> getProperties() { public abstract MapProperty<String, String> getProperties();
return this.properties;
}
@TaskAction @TaskAction
void extractResources() throws IOException { void extractResources() throws IOException {
for (String resourceName : this.resourceNames) { for (String resourceName : getResourceNames().get()) {
InputStream resourceStream = getClass().getClassLoader().getResourceAsStream(resourceName); InputStream resourceStream = getClass().getClassLoader().getResourceAsStream(resourceName);
if (resourceStream == null) { if (resourceStream == null) {
throw new GradleException("Resource '" + resourceName + "' does not exist"); throw new GradleException("Resource '" + resourceName + "' does not exist");
} }
String resource = FileCopyUtils.copyToString(new InputStreamReader(resourceStream, StandardCharsets.UTF_8)); String resource = FileCopyUtils.copyToString(new InputStreamReader(resourceStream, StandardCharsets.UTF_8));
resource = this.propertyPlaceholderHelper.replacePlaceholders(resource, this.properties::get); resource = this.propertyPlaceholderHelper.replacePlaceholders(resource, getProperties().get()::get);
FileCopyUtils.copy(resource, FileCopyUtils.copy(resource,
new FileWriter(this.destinationDirectory.file(resourceName).get().getAsFile())); new FileWriter(getDestinationDirectory().file(resourceName).get().getAsFile()));
} }
} }

View File

@ -129,8 +129,8 @@ class JavaConventions {
ExtractResources extractLegalResources = project.getTasks() ExtractResources extractLegalResources = project.getTasks()
.create("extractLegalResources", ExtractResources.class); .create("extractLegalResources", ExtractResources.class);
extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal")); extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal"));
extractLegalResources.setResourcesNames(Arrays.asList("LICENSE.txt", "NOTICE.txt")); extractLegalResources.getResourceNames().set(Arrays.asList("LICENSE.txt", "NOTICE.txt"));
extractLegalResources.property("version", project.getVersion().toString()); extractLegalResources.getProperties().put("version", project.getVersion().toString());
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
Set<String> sourceJarTaskNames = sourceSets.stream() Set<String> sourceJarTaskNames = sourceSets.stream()
.map(SourceSet::getSourcesJarTaskName) .map(SourceSet::getSourcesJarTaskName)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2021-2023 the original author or authors. * Copyright 2021-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,6 @@ package org.springframework.boot.build;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory; import org.gradle.api.tasks.InputDirectory;
@ -31,45 +30,29 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class SyncAppSource extends DefaultTask { public abstract class SyncAppSource extends DefaultTask {
private final DirectoryProperty sourceDirectory;
private final DirectoryProperty destinationDirectory;
private final Property<String> pluginVersion;
public SyncAppSource() { public SyncAppSource() {
ObjectFactory objects = getProject().getObjects(); getPluginVersion().convention(getProject().provider(() -> getProject().getVersion().toString()));
this.sourceDirectory = objects.directoryProperty();
this.destinationDirectory = objects.directoryProperty();
this.pluginVersion = objects.property(String.class)
.convention(getProject().provider(() -> getProject().getVersion().toString()));
} }
@InputDirectory
public abstract DirectoryProperty getSourceDirectory();
@OutputDirectory
public abstract DirectoryProperty getDestinationDirectory();
@Input
public abstract Property<String> getPluginVersion();
@TaskAction @TaskAction
void syncAppSources() { void syncAppSources() {
getProject().sync((copySpec) -> { getProject().sync((copySpec) -> {
copySpec.from(this.sourceDirectory); copySpec.from(getSourceDirectory());
copySpec.into(this.destinationDirectory); copySpec.into(getDestinationDirectory());
copySpec.filter((line) -> line.replace("id \"org.springframework.boot\"", copySpec.filter((line) -> line.replace("id \"org.springframework.boot\"",
"id \"org.springframework.boot\" version \"" + getProject().getVersion() + "\"")); "id \"org.springframework.boot\" version \"" + getProject().getVersion() + "\""));
}); });
} }
@InputDirectory
public DirectoryProperty getSourceDirectory() {
return this.sourceDirectory;
}
@OutputDirectory
public DirectoryProperty getDestinationDirectory() {
return this.destinationDirectory;
}
@Input
public Property<String> getPluginVersion() {
return this.pluginVersion;
}
} }

View File

@ -28,11 +28,15 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
@ -48,47 +52,45 @@ import org.springframework.core.CollectionFactory;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Scott Frederick * @author Scott Frederick
*/ */
public class AutoConfigurationMetadata extends DefaultTask { public abstract class AutoConfigurationMetadata extends DefaultTask {
private static final String COMMENT_START = "#"; private static final String COMMENT_START = "#";
private final String moduleName; private final String moduleName;
private SourceSet sourceSet; private FileCollection classesDirectories;
private File outputFile;
public AutoConfigurationMetadata() { public AutoConfigurationMetadata() {
getInputs()
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports"))
.withPathSensitivity(PathSensitivity.RELATIVE)
.withPropertyName("org.springframework.boot.autoconfigure.AutoConfiguration");
dependsOn((Callable<String>) () -> this.sourceSet.getProcessResourcesTaskName());
getProject().getConfigurations() getProject().getConfigurations()
.maybeCreate(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME); .maybeCreate(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME);
this.moduleName = getProject().getName(); this.moduleName = getProject().getName();
} }
public void setSourceSet(SourceSet sourceSet) { public void setSourceSet(SourceSet sourceSet) {
this.sourceSet = sourceSet; getAutoConfigurationImports().set(new File(sourceSet.getOutput().getResourcesDir(),
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports"));
this.classesDirectories = sourceSet.getOutput().getClassesDirs();
dependsOn(sourceSet.getOutput());
} }
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
abstract RegularFileProperty getAutoConfigurationImports();
@OutputFile @OutputFile
public File getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
}
public void setOutputFile(File outputFile) { @Classpath
this.outputFile = outputFile; FileCollection getClassesDirectories() {
return this.classesDirectories;
} }
@TaskAction @TaskAction
void documentAutoConfiguration() throws IOException { void documentAutoConfiguration() throws IOException {
Properties autoConfiguration = readAutoConfiguration(); Properties autoConfiguration = readAutoConfiguration();
getOutputFile().getParentFile().mkdirs(); File outputFile = getOutputFile().get().getAsFile();
try (FileWriter writer = new FileWriter(getOutputFile())) { outputFile.getParentFile().mkdirs();
try (FileWriter writer = new FileWriter(outputFile)) {
autoConfiguration.store(writer, null); autoConfiguration.store(writer, null);
} }
} }
@ -120,8 +122,7 @@ public class AutoConfigurationMetadata extends DefaultTask {
* @return auto-configurations * @return auto-configurations
*/ */
private List<String> readAutoConfigurationsFile() throws IOException { private List<String> readAutoConfigurationsFile() throws IOException {
File file = new File(this.sourceSet.getOutput().getResourcesDir(), File file = getAutoConfigurationImports().getAsFile().get();
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
if (!file.exists()) { if (!file.exists()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -140,7 +141,7 @@ public class AutoConfigurationMetadata extends DefaultTask {
private File findClassFile(String className) { private File findClassFile(String className) {
String classFileName = className.replace(".", "/") + ".class"; String classFileName = className.replace(".", "/") + ".class";
for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) { for (File classesDir : this.classesDirectories) {
File classFile = new File(classesDir, classFileName); File classFile = new File(classesDir, classFileName);
if (classFile.isFile()) { if (classFile.isFile()) {
return classFile; return classFile;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ArchCondition;
@ -94,10 +93,9 @@ public class AutoConfigurationPlugin implements Plugin<Project> {
.getByName(SourceSet.MAIN_SOURCE_SET_NAME); .getByName(SourceSet.MAIN_SOURCE_SET_NAME);
task.setSourceSet(main); task.setSourceSet(main);
task.dependsOn(main.getClassesTaskName()); task.dependsOn(main.getClassesTaskName());
task.setOutputFile(new File(project.getBuildDir(), "auto-configuration-metadata.properties")); task.getOutputFile().set(new File(project.getBuildDir(), "auto-configuration-metadata.properties"));
project.getArtifacts() project.getArtifacts()
.add(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME, .add(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME, task.getOutputFile(),
project.provider((Callable<File>) task::getOutputFile),
(artifact) -> artifact.builtBy(task)); (artifact) -> artifact.builtBy(task));
}); });
project.getPlugins().withType(ArchitecturePlugin.class, (architecturePlugin) -> { project.getPlugins().withType(ArchitecturePlugin.class, (architecturePlugin) -> {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,6 +31,7 @@ import java.util.stream.Collectors;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
@ -42,12 +43,10 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentAutoConfigurationClasses extends DefaultTask { public abstract class DocumentAutoConfigurationClasses extends DefaultTask {
private FileCollection autoConfiguration; private FileCollection autoConfiguration;
private File outputDir;
@InputFiles @InputFiles
public FileCollection getAutoConfiguration() { public FileCollection getAutoConfiguration() {
return this.autoConfiguration; return this.autoConfiguration;
@ -58,13 +57,7 @@ public class DocumentAutoConfigurationClasses extends DefaultTask {
} }
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract RegularFileProperty getOutputDir();
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@TaskAction @TaskAction
void documentAutoConfigurationClasses() throws IOException { void documentAutoConfigurationClasses() throws IOException {
@ -80,9 +73,10 @@ public class DocumentAutoConfigurationClasses extends DefaultTask {
} }
private void writeTable(AutoConfiguration autoConfigurationClasses) throws IOException { private void writeTable(AutoConfiguration autoConfigurationClasses) throws IOException {
this.outputDir.mkdirs(); File outputDir = getOutputDir().getAsFile().get();
outputDir.mkdirs();
try (PrintWriter writer = new PrintWriter( try (PrintWriter writer = new PrintWriter(
new FileWriter(new File(this.outputDir, autoConfigurationClasses.module + ".adoc")))) { new FileWriter(new File(outputDir, autoConfigurationClasses.module + ".adoc")))) {
writer.println("[cols=\"4,1\"]"); writer.println("[cols=\"4,1\"]");
writer.println("|==="); writer.println("|===");
writer.println("| Configuration Class | Links"); writer.println("| Configuration Class | Links");

View File

@ -149,7 +149,7 @@ public class BomExtension {
} }
MavenExec generateEffectiveBom = this.project.getTasks() MavenExec generateEffectiveBom = this.project.getTasks()
.create("generateEffectiveBom", MavenExec.class); .create("generateEffectiveBom", MavenExec.class);
generateEffectiveBom.setProjectDir(generatedBomDir); generateEffectiveBom.getProjectDir().set(generatedBomDir);
File effectiveBom = new File(this.project.getBuildDir(), File effectiveBom = new File(this.project.getBuildDir(),
"generated/effective-bom/" + this.project.getName() + "-effective-bom.xml"); "generated/effective-bom/" + this.project.getName() + "-effective-bom.xml");
generateEffectiveBom.args("--settings", "settings.xml", "help:effective-pom", generateEffectiveBom.args("--settings", "settings.xml", "help:effective-pom",

View File

@ -45,7 +45,7 @@ import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckBom extends DefaultTask { public abstract class CheckBom extends DefaultTask {
private final BomExtension bom; private final BomExtension bom;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -48,7 +48,7 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckClasspathForConflicts extends DefaultTask { public abstract class CheckClasspathForConflicts extends DefaultTask {
private final List<Predicate<String>> ignores = new ArrayList<>(); private final List<Predicate<String>> ignores = new ArrayList<>();

View File

@ -34,7 +34,7 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckClasspathForProhibitedDependencies extends DefaultTask { public abstract class CheckClasspathForProhibitedDependencies extends DefaultTask {
private static final Set<String> PROHIBITED_GROUPS = Set.of("org.codehaus.groovy", "org.eclipse.jetty.toolchain", private static final Set<String> PROHIBITED_GROUPS = Set.of("org.codehaus.groovy", "org.eclipse.jetty.toolchain",
"commons-logging", "org.apache.geronimo.specs", "com.sun.activation"); "commons-logging", "org.apache.geronimo.specs", "com.sun.activation");

View File

@ -34,7 +34,7 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckClasspathForUnconstrainedDirectDependencies extends DefaultTask { public abstract class CheckClasspathForUnconstrainedDirectDependencies extends DefaultTask {
private Configuration classpath; private Configuration classpath;

View File

@ -48,7 +48,7 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckClasspathForUnnecessaryExclusions extends DefaultTask { public abstract class CheckClasspathForUnnecessaryExclusions extends DefaultTask {
private static final Map<String, String> SPRING_BOOT_DEPENDENCIES_PROJECT = Collections.singletonMap("path", private static final Map<String, String> SPRING_BOOT_DEPENDENCIES_PROJECT = Collections.singletonMap("path",
":spring-boot-project:spring-boot-dependencies"); ":spring-boot-project:spring-boot-dependencies");

View File

@ -18,16 +18,15 @@ package org.springframework.boot.build.cli;
import java.io.File; import java.io.File;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.RegularFile; import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.Provider; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitive;
@ -42,62 +41,14 @@ import org.springframework.boot.build.artifacts.ArtifactRelease;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class HomebrewFormula extends DefaultTask { public abstract class HomebrewFormula extends DefaultTask {
private Provider<RegularFile> archive;
private File template;
private File outputDir;
public HomebrewFormula() { public HomebrewFormula() {
getInputs().property("version", getProject().provider(getProject()::getVersion));
}
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
public RegularFile getArchive() {
return this.archive.get();
}
public void setArchive(Provider<RegularFile> archive) {
this.archive = archive;
}
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
public File getTemplate() {
return this.template;
}
public void setTemplate(File template) {
this.template = template;
}
@OutputDirectory
public File getOutputDir() {
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
protected void createDescriptor(Map<String, Object> additionalProperties) {
getProject().copy((copy) -> {
copy.from(this.template);
copy.into(this.outputDir);
copy.expand(getProperties(additionalProperties));
});
}
private Map<String, Object> getProperties(Map<String, Object> additionalProperties) {
Map<String, Object> properties = new HashMap<>(additionalProperties);
Project project = getProject(); Project project = getProject();
properties.put("hash", sha256(this.archive.get().getAsFile())); MapProperty<String, Object> properties = getProperties();
properties.put("repo", ArtifactRelease.forProject(project).getDownloadRepo()); properties.put("hash", getArchive().map((archive) -> sha256(archive.getAsFile())));
properties.put("project", project); getProperties().put("repo", ArtifactRelease.forProject(project).getDownloadRepo());
return properties; getProperties().put("version", project.getVersion().toString());
} }
private String sha256(File file) { private String sha256(File file) {
@ -110,9 +61,27 @@ public class HomebrewFormula extends DefaultTask {
} }
} }
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
public abstract RegularFileProperty getArchive();
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
public abstract RegularFileProperty getTemplate();
@OutputDirectory
public abstract DirectoryProperty getOutputDir();
@Input
abstract MapProperty<String, Object> getProperties();
@TaskAction @TaskAction
void createFormula() { void createFormula() {
createDescriptor(Collections.emptyMap()); getProject().copy((copy) -> {
copy.from(getTemplate());
copy.into(getOutputDir());
copy.expand(getProperties().get());
});
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,10 +21,8 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import javax.inject.Inject;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.model.ObjectFactory; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.SetProperty; import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
@ -37,38 +35,22 @@ import org.springframework.boot.build.constraints.ExtractVersionConstraints.Cons
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentConstrainedVersions extends DefaultTask { public abstract class DocumentConstrainedVersions extends DefaultTask {
private final SetProperty<ConstrainedVersion> constrainedVersions;
private File outputFile;
@Inject
public DocumentConstrainedVersions(ObjectFactory objectFactory) {
this.constrainedVersions = objectFactory.setProperty(ConstrainedVersion.class);
}
@Input @Input
public SetProperty<ConstrainedVersion> getConstrainedVersions() { public abstract SetProperty<ConstrainedVersion> getConstrainedVersions();
return this.constrainedVersions;
}
@OutputFile @OutputFile
public File getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
}
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}
@TaskAction @TaskAction
public void documentConstrainedVersions() throws IOException { public void documentConstrainedVersions() throws IOException {
this.outputFile.getParentFile().mkdirs(); File outputFile = getOutputFile().get().getAsFile();
try (PrintWriter writer = new PrintWriter(new FileWriter(this.outputFile))) { outputFile.getParentFile().mkdirs();
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
writer.println("|==="); writer.println("|===");
writer.println("| Group ID | Artifact ID | Version"); writer.println("| Group ID | Artifact ID | Version");
for (ConstrainedVersion constrainedVersion : this.constrainedVersions.get()) { for (ConstrainedVersion constrainedVersion : getConstrainedVersions().get()) {
writer.println(); writer.println();
writer.printf("| `%s`%n", constrainedVersion.getGroup()); writer.printf("| `%s`%n", constrainedVersion.getGroup());
writer.printf("| `%s`%n", constrainedVersion.getArtifact()); writer.printf("| `%s`%n", constrainedVersion.getArtifact());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,10 +21,8 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import javax.inject.Inject;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.model.ObjectFactory; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.SetProperty; import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
@ -37,38 +35,22 @@ import org.springframework.boot.build.constraints.ExtractVersionConstraints.Vers
* *
* @author Christoph Dreis * @author Christoph Dreis
*/ */
public class DocumentVersionProperties extends DefaultTask { public abstract class DocumentVersionProperties extends DefaultTask {
private final SetProperty<VersionProperty> versionProperties;
private File outputFile;
@Inject
public DocumentVersionProperties(ObjectFactory objectFactory) {
this.versionProperties = objectFactory.setProperty(VersionProperty.class);
}
@Input @Input
public SetProperty<VersionProperty> getVersionProperties() { public abstract SetProperty<VersionProperty> getVersionProperties();
return this.versionProperties;
}
@OutputFile @OutputFile
public File getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
}
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}
@TaskAction @TaskAction
public void documentVersionProperties() throws IOException { public void documentVersionProperties() throws IOException {
this.outputFile.getParentFile().mkdirs(); File outputFile = getOutputFile().getAsFile().get();
try (PrintWriter writer = new PrintWriter(new FileWriter(this.outputFile))) { outputFile.getParentFile().mkdirs();
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
writer.println("|==="); writer.println("|===");
writer.println("| Library | Version Property"); writer.println("| Library | Version Property");
for (VersionProperty versionProperty : this.versionProperties.get()) { for (VersionProperty versionProperty : getVersionProperties().get()) {
writer.println(); writer.println();
writer.printf("| `%s`%n", versionProperty.getLibraryName()); writer.printf("| `%s`%n", versionProperty.getLibraryName());
writer.printf("| `%s`%n", versionProperty.getVersionProperty()); writer.printf("| `%s`%n", versionProperty.getVersionProperty());

View File

@ -48,7 +48,7 @@ import org.springframework.boot.build.bom.Library;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class ExtractVersionConstraints extends DefaultTask { public abstract class ExtractVersionConstraints extends DefaultTask {
private final Configuration configuration; private final Configuration configuration;

View File

@ -46,21 +46,16 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckAdditionalSpringConfigurationMetadata extends SourceTask { public abstract class CheckAdditionalSpringConfigurationMetadata extends SourceTask {
private final File projectDir; private final File projectDir;
private final RegularFileProperty reportLocation;
public CheckAdditionalSpringConfigurationMetadata() { public CheckAdditionalSpringConfigurationMetadata() {
this.projectDir = getProject().getProjectDir(); this.projectDir = getProject().getProjectDir();
this.reportLocation = getProject().getObjects().fileProperty();
} }
@OutputFile @OutputFile
public RegularFileProperty getReportLocation() { public abstract RegularFileProperty getReportLocation();
return this.reportLocation;
}
@Override @Override
@InputFiles @InputFiles

View File

@ -32,6 +32,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException; import org.gradle.api.GradleException;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
@ -45,41 +46,23 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class CheckSpringConfigurationMetadata extends DefaultTask { public abstract class CheckSpringConfigurationMetadata extends DefaultTask {
private List<String> exclusions = new ArrayList<>(); private final Path projectRoot;
private final File projectDir;
private final RegularFileProperty reportLocation;
private final RegularFileProperty metadataLocation;
public CheckSpringConfigurationMetadata() { public CheckSpringConfigurationMetadata() {
this.projectDir = getProject().getProjectDir(); this.projectRoot = getProject().getProjectDir().toPath();
this.metadataLocation = getProject().getObjects().fileProperty();
this.reportLocation = getProject().getObjects().fileProperty();
} }
@OutputFile @OutputFile
public RegularFileProperty getReportLocation() { public abstract RegularFileProperty getReportLocation();
return this.reportLocation;
}
@InputFile @InputFile
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
public RegularFileProperty getMetadataLocation() { public abstract RegularFileProperty getMetadataLocation();
return this.metadataLocation;
}
public void setExclusions(List<String> exclusions) {
this.exclusions = exclusions;
}
@Input @Input
public List<String> getExclusions() { public abstract ListProperty<String> getExclusions();
return this.exclusions;
}
@TaskAction @TaskAction
void check() throws JsonParseException, IOException { void check() throws JsonParseException, IOException {
@ -95,8 +78,8 @@ public class CheckSpringConfigurationMetadata extends DefaultTask {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Report createReport() throws IOException, JsonParseException, JsonMappingException { private Report createReport() throws IOException, JsonParseException, JsonMappingException {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
File file = this.metadataLocation.get().getAsFile(); File file = getMetadataLocation().get().getAsFile();
Report report = new Report(this.projectDir.toPath().relativize(file.toPath())); Report report = new Report(this.projectRoot.relativize(file.toPath()));
Map<String, Object> json = objectMapper.readValue(file, Map.class); Map<String, Object> json = objectMapper.readValue(file, Map.class);
List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties"); List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties");
for (Map<String, Object> property : properties) { for (Map<String, Object> property : properties) {
@ -109,7 +92,7 @@ public class CheckSpringConfigurationMetadata extends DefaultTask {
} }
private boolean isExcluded(String propertyName) { private boolean isExcluded(String propertyName) {
for (String exclusion : this.exclusions) { for (String exclusion : getExclusions().get()) {
if (propertyName.equals(exclusion)) { if (propertyName.equals(exclusion)) {
return true; return true;
} }

View File

@ -16,11 +16,11 @@
package org.springframework.boot.build.context.properties; package org.springframework.boot.build.context.properties;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
@ -36,12 +36,10 @@ import org.springframework.boot.build.context.properties.Snippet.Config;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
*/ */
public class DocumentConfigurationProperties extends DefaultTask { public abstract class DocumentConfigurationProperties extends DefaultTask {
private FileCollection configurationPropertyMetadata; private FileCollection configurationPropertyMetadata;
private File outputDir;
@InputFiles @InputFiles
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
public FileCollection getConfigurationPropertyMetadata() { public FileCollection getConfigurationPropertyMetadata() {
@ -53,13 +51,7 @@ public class DocumentConfigurationProperties extends DefaultTask {
} }
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract DirectoryProperty getOutputDir();
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@TaskAction @TaskAction
void documentConfigurationProperties() throws IOException { void documentConfigurationProperties() throws IOException {
@ -83,7 +75,7 @@ public class DocumentConfigurationProperties extends DefaultTask {
snippets.add("application-properties.testcontainers", "Testcontainers Properties", snippets.add("application-properties.testcontainers", "Testcontainers Properties",
this::testcontainersPrefixes); this::testcontainersPrefixes);
snippets.add("application-properties.testing", "Testing Properties", this::testingPrefixes); snippets.add("application-properties.testing", "Testing Properties", this::testingPrefixes);
snippets.writeTo(this.outputDir.toPath()); snippets.writeTo(getOutputDir().getAsFile().get().toPath());
} }
private void corePrefixes(Config config) { private void corePrefixes(Config config) {

View File

@ -39,16 +39,13 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentDevtoolsPropertyDefaults extends DefaultTask { public abstract class DocumentDevtoolsPropertyDefaults extends DefaultTask {
private final Configuration devtools; private final Configuration devtools;
private final RegularFileProperty outputFile;
public DocumentDevtoolsPropertyDefaults() { public DocumentDevtoolsPropertyDefaults() {
this.devtools = getProject().getConfigurations().create("devtools"); this.devtools = getProject().getConfigurations().create("devtools");
this.outputFile = getProject().getObjects().fileProperty(); getOutputFile().convention(getProject().getLayout()
this.outputFile.convention(getProject().getLayout()
.getBuildDirectory() .getBuildDirectory()
.file("docs/generated/using/devtools-property-defaults.adoc")); .file("docs/generated/using/devtools-property-defaults.adoc"));
Map<String, String> dependency = new HashMap<>(); Map<String, String> dependency = new HashMap<>();
@ -63,9 +60,7 @@ public class DocumentDevtoolsPropertyDefaults extends DefaultTask {
} }
@OutputFile @OutputFile
public RegularFileProperty getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
}
@TaskAction @TaskAction
void documentPropertyDefaults() throws IOException { void documentPropertyDefaults() throws IOException {
@ -86,7 +81,7 @@ public class DocumentDevtoolsPropertyDefaults extends DefaultTask {
} }
private void documentProperties(Map<String, String> properties) throws IOException { private void documentProperties(Map<String, String> properties) throws IOException {
try (PrintWriter writer = new PrintWriter(new FileWriter(this.outputFile.getAsFile().get()))) { try (PrintWriter writer = new PrintWriter(new FileWriter(getOutputFile().getAsFile().get()))) {
writer.println("[cols=\"3,1\"]"); writer.println("[cols=\"3,1\"]");
writer.println("|==="); writer.println("|===");
writer.println("| Name | Default Value"); writer.println("| Name | Default Value");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,6 +34,7 @@ import org.gradle.api.Task;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
@ -47,29 +48,17 @@ import org.gradle.internal.jvm.Jvm;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class ApplicationRunner extends DefaultTask { public abstract class ApplicationRunner extends DefaultTask {
private final RegularFileProperty output = getProject().getObjects().fileProperty();
private final ListProperty<String> args = getProject().getObjects().listProperty(String.class);
private final Property<String> mainClass = getProject().getObjects().property(String.class);
private final Property<String> expectedLogging = getProject().getObjects().property(String.class);
private final Property<String> applicationJar = getProject().getObjects()
.property(String.class)
.convention("/opt/apps/myapp.jar");
private final Map<String, String> normalizations = new HashMap<>();
private FileCollection classpath; private FileCollection classpath;
@OutputFile public ApplicationRunner() {
public RegularFileProperty getOutput() { getApplicationJar().convention("/opt/apps/myapp.jar");
return this.output;
} }
@OutputFile
public abstract RegularFileProperty getOutput();
@Classpath @Classpath
public FileCollection getClasspath() { public FileCollection getClasspath() {
return this.classpath; return this.classpath;
@ -80,37 +69,27 @@ public class ApplicationRunner extends DefaultTask {
} }
@Input @Input
public ListProperty<String> getArgs() { public abstract ListProperty<String> getArgs();
return this.args;
}
@Input @Input
public Property<String> getMainClass() { public abstract Property<String> getMainClass();
return this.mainClass;
}
@Input @Input
public Property<String> getExpectedLogging() { public abstract Property<String> getExpectedLogging();
return this.expectedLogging;
}
@Input @Input
Map<String, String> getNormalizations() { abstract MapProperty<String, String> getNormalizations();
return this.normalizations;
}
@Input @Input
public Property<String> getApplicationJar() { abstract Property<String> getApplicationJar();
return this.applicationJar;
}
public void normalizeTomcatPort() { public void normalizeTomcatPort() {
this.normalizations.put("(Tomcat started on port )[\\d]+( \\(http\\))", "$18080$2"); getNormalizations().put("(Tomcat started on port )[\\d]+( \\(http\\))", "$18080$2");
this.normalizations.put("(Tomcat initialized with port )[\\d]+( \\(http\\))", "$18080$2"); getNormalizations().put("(Tomcat initialized with port )[\\d]+( \\(http\\))", "$18080$2");
} }
public void normalizeLiveReloadPort() { public void normalizeLiveReloadPort() {
this.normalizations.put("(LiveReload server is running on port )[\\d]+", "$135729"); getNormalizations().put("(LiveReload server is running on port )[\\d]+", "$135729");
} }
@TaskAction @TaskAction
@ -123,9 +102,9 @@ public class ApplicationRunner extends DefaultTask {
.stream() .stream()
.map(File::getAbsolutePath) .map(File::getAbsolutePath)
.collect(Collectors.joining(File.pathSeparator))); .collect(Collectors.joining(File.pathSeparator)));
command.add(this.mainClass.get()); command.add(getMainClass().get());
command.addAll(this.args.get()); command.addAll(getArgs().get());
File outputFile = this.output.getAsFile().get(); File outputFile = getOutput().getAsFile().get();
Process process = new ProcessBuilder().redirectOutput(outputFile) Process process = new ProcessBuilder().redirectOutput(outputFile)
.redirectError(outputFile) .redirectError(outputFile)
.command(command) .command(command)
@ -137,7 +116,7 @@ public class ApplicationRunner extends DefaultTask {
private void awaitLogging(Process process) { private void awaitLogging(Process process) {
long end = System.currentTimeMillis() + 60000; long end = System.currentTimeMillis() + 60000;
String expectedLogging = this.expectedLogging.get(); String expectedLogging = getExpectedLogging().get();
while (System.currentTimeMillis() < end) { while (System.currentTimeMillis() < end) {
for (String line : outputLines()) { for (String line : outputLines()) {
if (line.contains(expectedLogging)) { if (line.contains(expectedLogging)) {
@ -152,7 +131,7 @@ public class ApplicationRunner extends DefaultTask {
} }
private List<String> outputLines() { private List<String> outputLines() {
Path outputPath = this.output.get().getAsFile().toPath(); Path outputPath = getOutput().get().getAsFile().toPath();
try { try {
return Files.readAllLines(outputPath); return Files.readAllLines(outputPath);
} }
@ -164,7 +143,7 @@ public class ApplicationRunner extends DefaultTask {
private void normalizeLogging() { private void normalizeLogging() {
List<String> outputLines = outputLines(); List<String> outputLines = outputLines();
List<String> normalizedLines = normalize(outputLines); List<String> normalizedLines = normalize(outputLines);
Path outputPath = this.output.get().getAsFile().toPath(); Path outputPath = getOutput().get().getAsFile().toPath();
try { try {
Files.write(outputPath, normalizedLines); Files.write(outputPath, normalizedLines);
} }
@ -175,9 +154,9 @@ public class ApplicationRunner extends DefaultTask {
private List<String> normalize(List<String> lines) { private List<String> normalize(List<String> lines) {
List<String> normalizedLines = lines; List<String> normalizedLines = lines;
Map<String, String> normalizations = new HashMap<>(this.normalizations); Map<String, String> normalizations = new HashMap<>(getNormalizations().get());
normalizations.put("(Starting .* using Java .* with PID [\\d]+ \\().*( started by ).*( in ).*(\\))", normalizations.put("(Starting .* using Java .* with PID [\\d]+ \\().*( started by ).*( in ).*(\\))",
"$1" + this.applicationJar.get() + "$2myuser$3/opt/apps/$4"); "$1" + getApplicationJar().get() + "$2myuser$3/opt/apps/$4");
for (Entry<String, String> normalization : normalizations.entrySet()) { for (Entry<String, String> normalization : normalizations.entrySet()) {
Pattern pattern = Pattern.compile(normalization.getKey()); Pattern pattern = Pattern.compile(normalization.getKey());
normalizedLines = normalize(normalizedLines, pattern, normalization.getValue()); normalizedLines = normalize(normalizedLines, pattern, normalization.getValue());

View File

@ -21,10 +21,12 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List; import java.util.List;
import java.util.Map;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
@ -39,46 +41,22 @@ import org.springframework.boot.build.mavenplugin.PluginXmlParser.Plugin;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentPluginGoals extends DefaultTask { public abstract class DocumentPluginGoals extends DefaultTask {
private final PluginXmlParser parser = new PluginXmlParser(); private final PluginXmlParser parser = new PluginXmlParser();
private File pluginXml;
private File outputDir;
private Map<String, String> goalSections;
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract DirectoryProperty getOutputDir();
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@Input @Input
public Map<String, String> getGoalSections() { public abstract MapProperty<String, String> getGoalSections();
return this.goalSections;
}
public void setGoalSections(Map<String, String> goalSections) {
this.goalSections = goalSections;
}
@InputFile @InputFile
public File getPluginXml() { public abstract RegularFileProperty getPluginXml();
return this.pluginXml;
}
public void setPluginXml(File pluginXml) {
this.pluginXml = pluginXml;
}
@TaskAction @TaskAction
public void documentPluginGoals() throws IOException { public void documentPluginGoals() throws IOException {
Plugin plugin = this.parser.parse(this.pluginXml); Plugin plugin = this.parser.parse(getPluginXml().getAsFile().get());
writeOverview(plugin); writeOverview(plugin);
for (Mojo mojo : plugin.getMojos()) { for (Mojo mojo : plugin.getMojos()) {
documentMojo(plugin, mojo); documentMojo(plugin, mojo);
@ -86,7 +64,8 @@ public class DocumentPluginGoals extends DefaultTask {
} }
private void writeOverview(Plugin plugin) throws IOException { private void writeOverview(Plugin plugin) throws IOException {
try (PrintWriter writer = new PrintWriter(new FileWriter(new File(this.outputDir, "overview.adoc")))) { try (PrintWriter writer = new PrintWriter(
new FileWriter(new File(getOutputDir().getAsFile().get(), "overview.adoc")))) {
writer.println("[cols=\"1,3\"]"); writer.println("[cols=\"1,3\"]");
writer.println("|==="); writer.println("|===");
writer.println("| Goal | Description"); writer.println("| Goal | Description");
@ -101,7 +80,8 @@ public class DocumentPluginGoals extends DefaultTask {
} }
private void documentMojo(Plugin plugin, Mojo mojo) throws IOException { private void documentMojo(Plugin plugin, Mojo mojo) throws IOException {
try (PrintWriter writer = new PrintWriter(new FileWriter(new File(this.outputDir, mojo.getGoal() + ".adoc")))) { try (PrintWriter writer = new PrintWriter(
new FileWriter(new File(getOutputDir().getAsFile().get(), mojo.getGoal() + ".adoc")))) {
String sectionId = goalSectionId(mojo); String sectionId = goalSectionId(mojo);
writer.println(); writer.println();
writer.println(); writer.println();
@ -139,7 +119,7 @@ public class DocumentPluginGoals extends DefaultTask {
} }
private String goalSectionId(Mojo mojo) { private String goalSectionId(Mojo mojo) {
String goalSection = this.goalSections.get(mojo.getGoal()); String goalSection = getGoalSections().getting(mojo.getGoal()).get();
if (goalSection == null) { if (goalSection == null) {
throw new IllegalStateException("Goal '" + mojo.getGoal() + "' has not be assigned to a section"); throw new IllegalStateException("Goal '" + mojo.getGoal() + "' has not be assigned to a section");
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,8 +24,12 @@ import java.nio.file.Path;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.JavaExec; import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskExecutionException; import org.gradle.api.tasks.TaskExecutionException;
import org.gradle.process.internal.ExecException; import org.gradle.process.internal.ExecException;
@ -37,29 +41,29 @@ import org.slf4j.LoggerFactory;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class MavenExec extends JavaExec { public abstract class MavenExec extends JavaExec {
private final Logger log = LoggerFactory.getLogger(MavenExec.class); private final Logger log = LoggerFactory.getLogger(MavenExec.class);
private File projectDir;
public MavenExec() { public MavenExec() {
setClasspath(mavenConfiguration(getProject())); setClasspath(mavenConfiguration(getProject()));
args("--batch-mode"); args("--batch-mode");
getMainClass().set("org.apache.maven.cli.MavenCli"); getMainClass().set("org.apache.maven.cli.MavenCli");
getPom().set(getProjectDir().file("pom.xml"));
} }
public void setProjectDir(File projectDir) { @Internal
this.projectDir = projectDir; public abstract DirectoryProperty getProjectDir();
getInputs().file(new File(projectDir, "pom.xml"))
.withPathSensitivity(PathSensitivity.RELATIVE) @InputFile
.withPropertyName("pom"); @PathSensitive(PathSensitivity.RELATIVE)
} abstract RegularFileProperty getPom();
@Override @Override
public void exec() { public void exec() {
workingDir(this.projectDir); File workingDir = getProjectDir().getAsFile().get();
systemProperty("maven.multiModuleProjectDirectory", this.projectDir.getAbsolutePath()); workingDir(workingDir);
systemProperty("maven.multiModuleProjectDirectory", workingDir.getAbsolutePath());
try { try {
Path logFile = Files.createTempFile(getName(), ".log"); Path logFile = Files.createTempFile(getName(), ".log");
try { try {
@ -97,9 +101,4 @@ public class MavenExec extends JavaExec {
}); });
} }
@Internal
public File getProjectDir() {
return this.projectDir;
}
} }

View File

@ -168,7 +168,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
project.getObjects().named(DocsType.class, "maven-repository"))); project.getObjects().named(DocsType.class, "maven-repository")));
RuntimeClasspathMavenRepository runtimeClasspathMavenRepository = project.getTasks() RuntimeClasspathMavenRepository runtimeClasspathMavenRepository = project.getTasks()
.create("runtimeClasspathMavenRepository", RuntimeClasspathMavenRepository.class); .create("runtimeClasspathMavenRepository", RuntimeClasspathMavenRepository.class);
runtimeClasspathMavenRepository.getOutputDirectory() runtimeClasspathMavenRepository.getOutputDir()
.set(new File(project.getBuildDir(), "runtime-classpath-repository")); .set(new File(project.getBuildDir(), "runtime-classpath-repository"));
project.getDependencies() project.getDependencies()
.components((components) -> components.all(MavenRepositoryComponentMetadataRule.class)); .components((components) -> components.all(MavenRepositoryComponentMetadataRule.class));
@ -195,8 +195,8 @@ public class MavenPluginPlugin implements Plugin<Project> {
private void addDocumentPluginGoalsTask(Project project, MavenExec generatePluginDescriptorTask) { private void addDocumentPluginGoalsTask(Project project, MavenExec generatePluginDescriptorTask) {
DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class); DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class);
File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml"); File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml");
task.setPluginXml(pluginXml); task.getPluginXml().set(pluginXml);
task.setOutputDir(new File(project.getBuildDir(), "docs/generated/goals/")); task.getOutputDir().set(new File(project.getBuildDir(), "docs/generated/goals/"));
task.dependsOn(generatePluginDescriptorTask); task.dependsOn(generatePluginDescriptorTask);
} }
@ -210,7 +210,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
private MavenExec createGenerateHelpMojoTask(Project project, File helpMojoDir) { private MavenExec createGenerateHelpMojoTask(Project project, File helpMojoDir) {
MavenExec task = project.getTasks().create("generateHelpMojo", MavenExec.class); MavenExec task = project.getTasks().create("generateHelpMojo", MavenExec.class);
task.setProjectDir(helpMojoDir); task.getProjectDir().set(helpMojoDir);
task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:helpmojo"); task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:helpmojo");
task.getOutputs().dir(new File(helpMojoDir, "target/generated-sources/plugin")); task.getOutputs().dir(new File(helpMojoDir, "target/generated-sources/plugin"));
return task; return task;
@ -261,7 +261,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
FormatHelpMojoSource formatHelpMojoSource = project.getTasks() FormatHelpMojoSource formatHelpMojoSource = project.getTasks()
.create("formatHelpMojoSource", FormatHelpMojoSource.class); .create("formatHelpMojoSource", FormatHelpMojoSource.class);
formatHelpMojoSource.setGenerator(generateHelpMojoTask); formatHelpMojoSource.setGenerator(generateHelpMojoTask);
formatHelpMojoSource.setOutputDir(generatedHelpMojoDir); formatHelpMojoSource.getOutputDir().set(generatedHelpMojoDir);
return formatHelpMojoSource; return formatHelpMojoSource;
} }
@ -284,7 +284,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
.dir(new File(mavenDir, "target/classes/org")) .dir(new File(mavenDir, "target/classes/org"))
.withPathSensitivity(PathSensitivity.RELATIVE) .withPathSensitivity(PathSensitivity.RELATIVE)
.withPropertyName("plugin classes"); .withPropertyName("plugin classes");
generatePluginDescriptor.setProjectDir(mavenDir); generatePluginDescriptor.getProjectDir().set(mavenDir);
return generatePluginDescriptor; return generatePluginDescriptor;
} }
@ -295,8 +295,9 @@ public class MavenPluginPlugin implements Plugin<Project> {
private void addPrepareMavenBinariesTask(Project project) { private void addPrepareMavenBinariesTask(Project project) {
TaskProvider<PrepareMavenBinaries> task = project.getTasks() TaskProvider<PrepareMavenBinaries> task = project.getTasks()
.register("prepareMavenBinaries", PrepareMavenBinaries.class, (prepareMavenBinaries) -> prepareMavenBinaries .register("prepareMavenBinaries", PrepareMavenBinaries.class,
.setOutputDir(new File(project.getBuildDir(), "maven-binaries"))); (prepareMavenBinaries) -> prepareMavenBinaries.getOutputDir()
.set(new File(project.getBuildDir(), "maven-binaries")));
project.getTasks() project.getTasks()
.getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME) .getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME)
.getInputs() .getInputs()
@ -324,12 +325,10 @@ public class MavenPluginPlugin implements Plugin<Project> {
.map((dir) -> dir.file("extracted-versions.properties"))); .map((dir) -> dir.file("extracted-versions.properties")));
} }
public static class FormatHelpMojoSource extends DefaultTask { public abstract static class FormatHelpMojoSource extends DefaultTask {
private Task generator; private Task generator;
private File outputDir;
void setGenerator(Task generator) { void setGenerator(Task generator) {
this.generator = generator; this.generator = generator;
getInputs().files(this.generator) getInputs().files(this.generator)
@ -338,13 +337,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract DirectoryProperty getOutputDir();
return this.outputDir;
}
void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@TaskAction @TaskAction
void syncAndFormat() { void syncAndFormat() {
@ -357,7 +350,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
private void save(File output, FileEdit edit) { private void save(File output, FileEdit edit) {
Path relativePath = output.toPath().relativize(edit.getFile().toPath()); Path relativePath = output.toPath().relativize(edit.getFile().toPath());
Path outputLocation = this.outputDir.toPath().resolve(relativePath); Path outputLocation = getOutputDir().getAsFile().get().toPath().resolve(relativePath);
try { try {
Files.createDirectories(outputLocation.getParent()); Files.createDirectories(outputLocation.getParent());
Files.writeString(outputLocation, edit.getFormattedContent()); Files.writeString(outputLocation, edit.getFormattedContent());
@ -401,21 +394,16 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
public static class RuntimeClasspathMavenRepository extends DefaultTask { public abstract static class RuntimeClasspathMavenRepository extends DefaultTask {
private final Configuration runtimeClasspath; private final Configuration runtimeClasspath;
private final DirectoryProperty outputDirectory;
public RuntimeClasspathMavenRepository() { public RuntimeClasspathMavenRepository() {
this.runtimeClasspath = getProject().getConfigurations().getByName("runtimeClasspathWithMetadata"); this.runtimeClasspath = getProject().getConfigurations().getByName("runtimeClasspathWithMetadata");
this.outputDirectory = getProject().getObjects().directoryProperty();
} }
@OutputDirectory @OutputDirectory
public DirectoryProperty getOutputDirectory() { public abstract DirectoryProperty getOutputDir();
return this.outputDirectory;
}
@Classpath @Classpath
public Configuration getRuntimeClasspath() { public Configuration getRuntimeClasspath() {
@ -429,7 +417,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
String fileName = result.getFile() String fileName = result.getFile()
.getName() .getName()
.replace(identifier.getVersion() + "-" + identifier.getVersion(), identifier.getVersion()); .replace(identifier.getVersion() + "-" + identifier.getVersion(), identifier.getVersion());
File repositoryLocation = this.outputDirectory File repositoryLocation = getOutputDir()
.dir(identifier.getGroup().replace('.', '/') + "/" + identifier.getModule() + "/" .dir(identifier.getGroup().replace('.', '/') + "/" + identifier.getModule() + "/"
+ identifier.getVersion() + "/" + fileName) + identifier.getVersion() + "/" + fileName)
.get() .get()
@ -448,16 +436,10 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
public static class ExtractVersionProperties extends DefaultTask { public abstract static class ExtractVersionProperties extends DefaultTask {
private final RegularFileProperty destination;
private FileCollection effectiveBoms; private FileCollection effectiveBoms;
public ExtractVersionProperties() {
this.destination = getProject().getObjects().fileProperty();
}
@InputFiles @InputFiles
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
public FileCollection getEffectiveBoms() { public FileCollection getEffectiveBoms() {
@ -469,9 +451,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
@OutputFile @OutputFile
public RegularFileProperty getDestination() { public abstract RegularFileProperty getDestination();
return this.destination;
}
@TaskAction @TaskAction
public void extractVersionProperties() { public void extractVersionProperties() {
@ -481,7 +461,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
private void writeProperties(Properties versions) { private void writeProperties(Properties versions) {
File outputFile = this.destination.getAsFile().get(); File outputFile = getDestination().getAsFile().get();
outputFile.getParentFile().mkdirs(); outputFile.getParentFile().mkdirs();
try (Writer writer = new FileWriter(outputFile)) { try (Writer writer = new FileWriter(outputFile)) {
versions.store(writer, null); versions.store(writer, null);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,14 +16,11 @@
package org.springframework.boot.build.mavenplugin; package org.springframework.boot.build.mavenplugin;
import java.io.File;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
@ -33,38 +30,22 @@ import org.gradle.api.tasks.TaskAction;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class PrepareMavenBinaries extends DefaultTask { public abstract class PrepareMavenBinaries extends DefaultTask {
private final Set<String> versions = new LinkedHashSet<>();
private File outputDir;
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract DirectoryProperty getOutputDir();
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@Input @Input
public Set<String> getVersions() { public abstract SetProperty<String> getVersions();
return this.versions;
}
public void versions(String... versions) {
this.versions.addAll(Arrays.asList(versions));
}
@TaskAction @TaskAction
public void prepareBinaries() { public void prepareBinaries() {
for (String version : this.versions) { for (String version : getVersions().get()) {
Configuration configuration = getProject().getConfigurations() Configuration configuration = getProject().getConfigurations()
.detachedConfiguration( .detachedConfiguration(
getProject().getDependencies().create("org.apache.maven:apache-maven:" + version + ":bin@zip")); getProject().getDependencies().create("org.apache.maven:apache-maven:" + version + ":bin@zip"));
getProject() getProject()
.copy((copy) -> copy.into(this.outputDir).from(getProject().zipTree(configuration.getSingleFile()))); .copy((copy) -> copy.into(getOutputDir()).from(getProject().zipTree(configuration.getSingleFile())));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,6 +33,7 @@ import java.util.stream.Stream;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
@ -47,12 +48,10 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentStarters extends DefaultTask { public abstract class DocumentStarters extends DefaultTask {
private final Configuration starters; private final Configuration starters;
private File outputDir;
public DocumentStarters() { public DocumentStarters() {
this.starters = getProject().getConfigurations().create("starters"); this.starters = getProject().getConfigurations().create("starters");
getProject().getGradle().projectsEvaluated((gradle) -> { getProject().getGradle().projectsEvaluated((gradle) -> {
@ -68,13 +67,7 @@ public class DocumentStarters extends DefaultTask {
} }
@OutputDirectory @OutputDirectory
public File getOutputDir() { public abstract DirectoryProperty getOutputDir();
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
@InputFiles @InputFiles
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
@ -106,7 +99,7 @@ public class DocumentStarters extends DefaultTask {
} }
private void writeTable(String name, Stream<Starter> starters) { private void writeTable(String name, Stream<Starter> starters) {
File output = new File(this.outputDir, name + ".adoc"); File output = new File(getOutputDir().getAsFile().get(), name + ".adoc");
output.getParentFile().mkdirs(); output.getParentFile().mkdirs();
try (PrintWriter writer = new PrintWriter(new FileWriter(output))) { try (PrintWriter writer = new PrintWriter(new FileWriter(output))) {
writer.println("|==="); writer.println("|===");

View File

@ -32,6 +32,7 @@ import java.util.TreeSet;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitive;
@ -46,12 +47,10 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class DocumentTestSlices extends DefaultTask { public abstract class DocumentTestSlices extends DefaultTask {
private FileCollection testSlices; private FileCollection testSlices;
private File outputFile;
@InputFiles @InputFiles
@PathSensitive(PathSensitivity.RELATIVE) @PathSensitive(PathSensitivity.RELATIVE)
public FileCollection getTestSlices() { public FileCollection getTestSlices() {
@ -63,13 +62,7 @@ public class DocumentTestSlices extends DefaultTask {
} }
@OutputFile @OutputFile
public File getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
}
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}
@TaskAction @TaskAction
void documentTestSlices() throws IOException { void documentTestSlices() throws IOException {
@ -94,8 +87,9 @@ public class DocumentTestSlices extends DefaultTask {
} }
private void writeTable(Set<TestSlice> testSlices) throws IOException { private void writeTable(Set<TestSlice> testSlices) throws IOException {
this.outputFile.getParentFile().mkdirs(); File outputFile = getOutputFile().getAsFile().get();
try (PrintWriter writer = new PrintWriter(new FileWriter(this.outputFile))) { outputFile.getParentFile().mkdirs();
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) {
writer.println("[cols=\"d,a\"]"); writer.println("[cols=\"d,a\"]");
writer.println("|==="); writer.println("|===");
writer.println("| Test slice | Imported auto-configuration"); writer.println("| Test slice | Imported auto-configuration");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,7 +32,6 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -41,7 +40,12 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
@ -59,44 +63,57 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class TestSliceMetadata extends DefaultTask { public abstract class TestSliceMetadata extends DefaultTask {
private SourceSet sourceSet; private FileCollection classpath;
private File outputFile; private FileCollection importsFiles;
private FileCollection classesDirs;
public TestSliceMetadata() { public TestSliceMetadata() {
getInputs().dir((Callable<File>) () -> this.sourceSet.getOutput().getResourcesDir()) Configuration testSliceMetadata = getProject().getConfigurations().maybeCreate("testSliceMetadata");
.withPathSensitivity(PathSensitivity.RELATIVE) getProject().afterEvaluate((evaluated) -> evaluated.getArtifacts()
.withPropertyName("resources"); .add(testSliceMetadata.getName(), getOutputFile(), (artifact) -> artifact.builtBy(this)));
dependsOn((Callable<String>) () -> this.sourceSet.getProcessResourcesTaskName());
getInputs().files((Callable<FileCollection>) () -> this.sourceSet.getOutput().getClassesDirs())
.withPathSensitivity(PathSensitivity.RELATIVE)
.withPropertyName("classes");
} }
public void setSourceSet(SourceSet sourceSet) { public void setSourceSet(SourceSet sourceSet) {
this.sourceSet = sourceSet; this.classpath = sourceSet.getRuntimeClasspath();
this.importsFiles = getProject().fileTree(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring"),
(tree) -> tree.filter((file) -> file.getName().endsWith(".imports")));
getSpringFactories().set(new File(sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories"));
this.classesDirs = sourceSet.getOutput().getClassesDirs();
} }
@OutputFile @OutputFile
public File getOutputFile() { public abstract RegularFileProperty getOutputFile();
return this.outputFile;
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
abstract RegularFileProperty getSpringFactories();
@Classpath
FileCollection getClasspath() {
return this.classpath;
} }
public void setOutputFile(File outputFile) { @InputFiles
this.outputFile = outputFile; @PathSensitive(PathSensitivity.RELATIVE)
Configuration testSliceMetadata = getProject().getConfigurations().maybeCreate("testSliceMetadata"); FileCollection getImportFiles() {
getProject().getArtifacts() return this.importsFiles;
.add(testSliceMetadata.getName(), getProject().provider((Callable<File>) this::getOutputFile), }
(artifact) -> artifact.builtBy(this));
@Classpath
FileCollection getClassesDirs() {
return this.classesDirs;
} }
@TaskAction @TaskAction
void documentTestSlices() throws IOException { void documentTestSlices() throws IOException {
Properties testSlices = readTestSlices(); Properties testSlices = readTestSlices();
getOutputFile().getParentFile().mkdirs(); File outputFile = getOutputFile().getAsFile().get();
try (FileWriter writer = new FileWriter(getOutputFile())) { outputFile.getParentFile().mkdirs();
try (FileWriter writer = new FileWriter(outputFile)) {
testSlices.store(writer, null); testSlices.store(writer, null);
} }
} }
@ -104,15 +121,11 @@ public class TestSliceMetadata extends DefaultTask {
private Properties readTestSlices() throws IOException { private Properties readTestSlices() throws IOException {
Properties testSlices = CollectionFactory.createSortedProperties(true); Properties testSlices = CollectionFactory.createSortedProperties(true);
try (URLClassLoader classLoader = new URLClassLoader( try (URLClassLoader classLoader = new URLClassLoader(
StreamSupport.stream(this.sourceSet.getRuntimeClasspath().spliterator(), false) StreamSupport.stream(this.classpath.spliterator(), false).map(this::toURL).toArray(URL[]::new))) {
.map(this::toURL)
.toArray(URL[]::new))) {
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(classLoader); MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(classLoader);
Properties springFactories = readSpringFactories( Properties springFactories = readSpringFactories(getSpringFactories().getAsFile().get());
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories")); readImportsFiles(springFactories, this.importsFiles);
readTestSlicesDirectory(springFactories, for (File classesDir : this.classesDirs) {
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring/"));
for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) {
addTestSlices(testSlices, classesDir, metadataReaderFactory, springFactories); addTestSlices(testSlices, classesDir, metadataReaderFactory, springFactories);
} }
} }
@ -120,18 +133,14 @@ public class TestSliceMetadata extends DefaultTask {
} }
/** /**
* Reads files from the given directory and puts them in springFactories. The key is * Reads the given imports files and puts them in springFactories. The key is the file
* the file name, the value is the file contents, split by line, delimited with comma. * name, the value is the file contents, split by line, delimited with a comma. This
* This is done to mimic the spring.factories structure. * is done to mimic the spring.factories structure.
* @param springFactories spring.factories parsed as properties * @param springFactories spring.factories parsed as properties
* @param directory directory to scan * @param importsFiles the imports files to read
*/ */
private void readTestSlicesDirectory(Properties springFactories, File directory) { private void readImportsFiles(Properties springFactories, FileCollection importsFiles) {
File[] files = directory.listFiles((dir, name) -> name.endsWith(".imports")); for (File file : importsFiles.getFiles()) {
if (files == null) {
return;
}
for (File file : files) {
try { try {
List<String> lines = removeComments(Files.readAllLines(file.toPath())); List<String> lines = removeComments(Files.readAllLines(file.toPath()));
String fileNameWithoutExtension = file.getName() String fileNameWithoutExtension = file.getName()

View File

@ -2,8 +2,8 @@ require 'formula'
class SpringBoot < Formula class SpringBoot < Formula
homepage 'https://spring.io/projects/spring-boot' homepage 'https://spring.io/projects/spring-boot'
url '${repo}/org/springframework/boot/spring-boot-cli/${project.version}/spring-boot-cli-${project.version}-bin.tar.gz' url '${repo}/org/springframework/boot/spring-boot-cli/${version}/spring-boot-cli-${version}-bin.tar.gz'
version '${project.version}' version '${version}'
sha256 '${hash}' sha256 '${hash}'
head 'https://github.com/spring-projects/spring-boot.git', :branch => "main" head 'https://github.com/spring-projects/spring-boot.git', :branch => "main"

View File

@ -169,7 +169,7 @@ task xsdResources(type: Sync) {
} }
prepareMavenBinaries { prepareMavenBinaries {
versions "3.9.6", "3.6.3" versions = [ "3.9.6", "3.6.3" ]
} }
artifacts { artifacts {