diff --git a/buildSrc/src/main/java/org/springframework/boot/build/ConventionsPlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/ConventionsPlugin.java index 52c3b03de1c..3454a2efa51 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/ConventionsPlugin.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/ConventionsPlugin.java @@ -16,283 +16,36 @@ package org.springframework.boot.build; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.function.Consumer; - -import io.spring.javaformat.gradle.FormatTask; -import io.spring.javaformat.gradle.SpringJavaFormatPlugin; -import org.apache.maven.artifact.repository.MavenArtifactRepository; import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin; -import org.gradle.api.GradleException; import org.gradle.api.Plugin; import org.gradle.api.Project; -import org.gradle.api.artifacts.DependencySet; -import org.gradle.api.file.CopySpec; import org.gradle.api.plugins.JavaBasePlugin; -import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.plugins.quality.CheckstyleExtension; -import org.gradle.api.plugins.quality.CheckstylePlugin; -import org.gradle.api.publish.PublishingExtension; -import org.gradle.api.publish.maven.MavenPom; -import org.gradle.api.publish.maven.MavenPomDeveloperSpec; -import org.gradle.api.publish.maven.MavenPomIssueManagement; -import org.gradle.api.publish.maven.MavenPomLicenseSpec; -import org.gradle.api.publish.maven.MavenPomOrganization; -import org.gradle.api.publish.maven.MavenPomScm; -import org.gradle.api.publish.maven.MavenPublication; import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; -import org.gradle.api.resources.TextResourceFactory; -import org.gradle.api.tasks.bundling.Jar; -import org.gradle.api.tasks.compile.JavaCompile; -import org.gradle.api.tasks.javadoc.Javadoc; -import org.gradle.api.tasks.testing.Test; -import org.gradle.testretry.TestRetryPlugin; -import org.gradle.testretry.TestRetryTaskExtension; - -import org.springframework.boot.build.testing.TestFailuresPlugin; -import org.springframework.util.FileCopyUtils; /** * Plugin to apply conventions to projects that are part of Spring Boot's build. * Conventions are applied in response to various plugins being applied. * - *

+ * When the {@link JavaBasePlugin} is applied, the conventions in {@link JavaConventions} + * are applied. * - * When the {@link JavaBasePlugin Java base plugin} is applied: - * - *

- * - *

- * - * When the {@link MavenPublishPlugin Maven Publish plugin} is applied: - * - *

- * - *

+ * When the {@link MavenPublishPlugin} is applied, the conventions in + * {@link MavenPublishingConventions} are applied. * * When the {@link AsciidoctorJPlugin} is applied, the conventions in * {@link AsciidoctorConventions} are applied. * * @author Andy Wilkinson * @author Christoph Dreis + * @author Mike Smithson */ public class ConventionsPlugin implements Plugin { @Override public void apply(Project project) { - applyJavaConventions(project); - applyAsciidoctorConventions(project); - applyMavenPublishingConventions(project); - } - - private void applyJavaConventions(Project project) { - project.getPlugins().withType(JavaBasePlugin.class, (java) -> { - project.getPlugins().apply(TestFailuresPlugin.class); - configureSpringJavaFormat(project); - project.setProperty("sourceCompatibility", "1.8"); - project.getTasks().withType(JavaCompile.class, (compile) -> { - compile.getOptions().setEncoding("UTF-8"); - withOptionalBuildJavaHome(project, (javaHome) -> { - compile.getOptions().setFork(true); - compile.getOptions().getForkOptions().setJavaHome(new File(javaHome)); - compile.getOptions().getForkOptions().setExecutable(javaHome + "/bin/javac"); - }); - List args = compile.getOptions().getCompilerArgs(); - if (!args.contains("-parameters")) { - args.add("-parameters"); - } - }); - project.getTasks().withType(Javadoc.class, (javadoc) -> { - javadoc.getOptions().source("1.8").encoding("UTF-8"); - withOptionalBuildJavaHome(project, (javaHome) -> javadoc.setExecutable(javaHome + "/bin/javadoc")); - }); - project.getPlugins().apply(TestRetryPlugin.class); - project.getTasks().withType(Test.class, (test) -> { - withOptionalBuildJavaHome(project, (javaHome) -> test.setExecutable(javaHome + "/bin/java")); - test.useJUnitPlatform(); - test.setMaxHeapSize("1024M"); - project.getPlugins().withType(TestRetryPlugin.class, (testRetryPlugin) -> { - TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class); - testRetry.getFailOnPassedAfterRetry().set(true); - testRetry.getMaxRetries().set(3); - }); - }); - project.getTasks().withType(Jar.class, (jar) -> { - project.afterEvaluate((evaluated) -> { - jar.metaInf((metaInf) -> copyLegalFiles(project, metaInf)); - jar.manifest((manifest) -> { - Map attributes = new TreeMap<>(); - attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); - attributes.put("Build-Jdk-Spec", project.property("sourceCompatibility")); - attributes.put("Built-By", "Spring"); - attributes.put("Implementation-Title", project.getDescription()); - attributes.put("Implementation-Version", project.getVersion()); - manifest.attributes(attributes); - }); - }); - }); - }); - } - - private void copyLegalFiles(Project project, CopySpec metaInf) { - copyNoticeFile(project, metaInf); - copyLicenseFile(project, metaInf); - } - - private void copyNoticeFile(Project project, CopySpec metaInf) { - try { - InputStream notice = getClass().getClassLoader().getResourceAsStream("NOTICE.txt"); - String noticeContent = FileCopyUtils.copyToString(new InputStreamReader(notice, StandardCharsets.UTF_8)) - .replace("${version}", project.getVersion().toString()); - TextResourceFactory resourceFactory = project.getResources().getText(); - File file = createLegalFile(resourceFactory.fromString(noticeContent).asFile(), "NOTICE.txt"); - metaInf.from(file); - } - catch (IOException ex) { - throw new GradleException("Failed to copy NOTICE.txt", ex); - } - } - - private void copyLicenseFile(Project project, CopySpec metaInf) { - URL license = getClass().getClassLoader().getResource("LICENSE.txt"); - try { - TextResourceFactory resourceFactory = project.getResources().getText(); - File file = createLegalFile(resourceFactory.fromUri(license.toURI()).asFile(), "LICENSE.txt"); - metaInf.from(file); - } - catch (URISyntaxException ex) { - throw new GradleException("Failed to copy LICENSE.txt", ex); - } - } - - private File createLegalFile(File source, String filename) { - File legalFile = new File(source.getParentFile(), filename); - source.renameTo(legalFile); - return legalFile; - } - - private void withOptionalBuildJavaHome(Project project, Consumer consumer) { - String buildJavaHome = (String) project.findProperty("buildJavaHome"); - if (buildJavaHome != null && !buildJavaHome.isEmpty()) { - consumer.accept(buildJavaHome); - } - } - - private void configureSpringJavaFormat(Project project) { - project.getPlugins().apply(SpringJavaFormatPlugin.class); - project.getTasks().withType(FormatTask.class, (formatTask) -> formatTask.setEncoding("UTF-8")); - project.getPlugins().apply(CheckstylePlugin.class); - CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class); - checkstyle.setToolVersion("8.29"); - checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle")); - String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion(); - DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies(); - checkstyleDependencies - .add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version)); - checkstyleDependencies - .add(project.getDependencies().create("io.spring.nohttp:nohttp-checkstyle:0.0.3.RELEASE")); - } - - private void applyAsciidoctorConventions(Project project) { + new JavaConventions().apply(project); + new MavenPublishingConventions().apply(project); new AsciidoctorConventions().apply(project); } - private void applyMavenPublishingConventions(Project project) { - project.getPlugins().withType(MavenPublishPlugin.class).all((mavenPublish) -> { - PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); - if (project.hasProperty("deploymentRepository")) { - publishing.getRepositories().maven((mavenRepository) -> { - mavenRepository.setUrl(project.property("deploymentRepository")); - mavenRepository.setName("deployment"); - }); - } - publishing.getPublications().withType(MavenPublication.class) - .all((mavenPublication) -> customizePom(mavenPublication.getPom(), project)); - project.getPlugins().withType(JavaPlugin.class).all((javaPlugin) -> { - JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class); - extension.withJavadocJar(); - extension.withSourcesJar(); - }); - }); - } - - private void customizePom(MavenPom pom, Project project) { - pom.getUrl().set("https://projects.spring.io/spring-boot/#"); - pom.getDescription().set(project.provider(project::getDescription)); - pom.organization(this::customizeOrganization); - pom.licenses(this::customizeLicences); - pom.developers(this::customizeDevelopers); - pom.scm(this::customizeScm); - pom.issueManagement(this::customizeIssueManagement); - } - - private void customizeOrganization(MavenPomOrganization organization) { - organization.getName().set("Pivotal Software, Inc."); - organization.getUrl().set("https://spring.io"); - } - - private void customizeLicences(MavenPomLicenseSpec licences) { - licences.license((licence) -> { - licence.getName().set("Apache License, Version 2.0"); - licence.getUrl().set("http://www.apache.org/licenses/LICENSE-2.0"); - }); - } - - private void customizeDevelopers(MavenPomDeveloperSpec developers) { - developers.developer((developer) -> { - developer.getName().set("Pivotal"); - developer.getEmail().set("info@pivotal.io"); - developer.getOrganization().set("Pivotal Software, Inc."); - developer.getOrganizationUrl().set("https://www.spring.io"); - }); - } - - private void customizeScm(MavenPomScm scm) { - scm.getConnection().set("scm:git:git://github.com/spring-projects/spring-boot.git"); - scm.getDeveloperConnection().set("scm:git:ssh://git@github.com/spring-projects/spring-boot.git"); - scm.getUrl().set("https://github.com/spring-projects/spring-boot"); - - } - - private void customizeIssueManagement(MavenPomIssueManagement issueManagement) { - issueManagement.getSystem().set("GitHub"); - issueManagement.getUrl().set("https://github.com/spring-projects/spring-boot/issues"); - } - } diff --git a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java new file mode 100644 index 00000000000..c92a20ba45a --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java @@ -0,0 +1,204 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.boot.build; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Consumer; + +import io.spring.javaformat.gradle.FormatTask; +import io.spring.javaformat.gradle.SpringJavaFormatPlugin; +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.api.artifacts.DependencySet; +import org.gradle.api.file.CopySpec; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.quality.CheckstyleExtension; +import org.gradle.api.plugins.quality.CheckstylePlugin; +import org.gradle.api.resources.TextResourceFactory; +import org.gradle.api.tasks.bundling.Jar; +import org.gradle.api.tasks.compile.JavaCompile; +import org.gradle.api.tasks.javadoc.Javadoc; +import org.gradle.api.tasks.testing.Test; +import org.gradle.testretry.TestRetryPlugin; +import org.gradle.testretry.TestRetryTaskExtension; + +import org.springframework.boot.build.testing.TestFailuresPlugin; +import org.springframework.util.FileCopyUtils; + +/** + * Conventions that are applied in the presence of the {@link JavaBasePlugin}. When the + * plugin is applied: + * + *

+ * + *

+ * + * @author Andy Wilkinson + * @author Christoph Dreis + * @author Mike Smithson + */ +class JavaConventions { + + void apply(Project project) { + project.getPlugins().withType(JavaBasePlugin.class, (java) -> { + project.getPlugins().apply(TestFailuresPlugin.class); + configureSpringJavaFormat(project); + project.setProperty("sourceCompatibility", "1.8"); + configureJavaCompileConventions(project); + configureJavadocConventions(project); + configureTestConventions(project); + configureJarManifestConventions(project); + }); + } + + private void configureJarManifestConventions(Project project) { + project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate((evaluated) -> { + jar.metaInf((metaInf) -> copyLegalFiles(project, metaInf)); + jar.manifest((manifest) -> { + Map attributes = new TreeMap<>(); + attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); + attributes.put("Build-Jdk-Spec", project.property("sourceCompatibility")); + attributes.put("Built-By", "Spring"); + attributes.put("Implementation-Title", project.getDescription()); + attributes.put("Implementation-Version", project.getVersion()); + manifest.attributes(attributes); + }); + })); + } + + private void configureTestConventions(Project project) { + project.getPlugins().apply(TestRetryPlugin.class); + project.getTasks().withType(Test.class, (test) -> { + withOptionalBuildJavaHome(project, (javaHome) -> test.setExecutable(javaHome + "/bin/java")); + test.useJUnitPlatform(); + test.setMaxHeapSize("1024M"); + project.getPlugins().withType(TestRetryPlugin.class, (testRetryPlugin) -> { + TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class); + testRetry.getFailOnPassedAfterRetry().set(true); + testRetry.getMaxRetries().set(3); + }); + }); + } + + private void configureJavadocConventions(Project project) { + project.getTasks().withType(Javadoc.class, (javadoc) -> { + javadoc.getOptions().source("1.8").encoding("UTF-8"); + withOptionalBuildJavaHome(project, (javaHome) -> javadoc.setExecutable(javaHome + "/bin/javadoc")); + }); + } + + private void configureJavaCompileConventions(Project project) { + project.getTasks().withType(JavaCompile.class, (compile) -> { + compile.getOptions().setEncoding("UTF-8"); + withOptionalBuildJavaHome(project, (javaHome) -> { + compile.getOptions().setFork(true); + compile.getOptions().getForkOptions().setJavaHome(new File(javaHome)); + compile.getOptions().getForkOptions().setExecutable(javaHome + "/bin/javac"); + }); + List args = compile.getOptions().getCompilerArgs(); + if (!args.contains("-parameters")) { + args.add("-parameters"); + } + }); + } + + private void withOptionalBuildJavaHome(Project project, Consumer consumer) { + String buildJavaHome = (String) project.findProperty("buildJavaHome"); + if (buildJavaHome != null && !buildJavaHome.isEmpty()) { + consumer.accept(buildJavaHome); + } + } + + private void configureSpringJavaFormat(Project project) { + project.getPlugins().apply(SpringJavaFormatPlugin.class); + project.getTasks().withType(FormatTask.class, (formatTask) -> formatTask.setEncoding("UTF-8")); + project.getPlugins().apply(CheckstylePlugin.class); + CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class); + checkstyle.setToolVersion("8.29"); + checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle")); + String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion(); + DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies(); + checkstyleDependencies + .add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version)); + checkstyleDependencies + .add(project.getDependencies().create("io.spring.nohttp:nohttp-checkstyle:0.0.3.RELEASE")); + } + + void copyLegalFiles(Project project, CopySpec metaInf) { + copyNoticeFile(project, metaInf); + copyLicenseFile(project, metaInf); + } + + void copyNoticeFile(Project project, CopySpec metaInf) { + try { + InputStream notice = getClass().getClassLoader().getResourceAsStream("NOTICE.txt"); + String noticeContent = FileCopyUtils.copyToString(new InputStreamReader(notice, StandardCharsets.UTF_8)) + .replace("${version}", project.getVersion().toString()); + TextResourceFactory resourceFactory = project.getResources().getText(); + File file = createLegalFile(resourceFactory.fromString(noticeContent).asFile(), "NOTICE.txt"); + metaInf.from(file); + } + catch (IOException ex) { + throw new GradleException("Failed to copy NOTICE.txt", ex); + } + } + + void copyLicenseFile(Project project, CopySpec metaInf) { + URL license = getClass().getClassLoader().getResource("LICENSE.txt"); + try { + TextResourceFactory resourceFactory = project.getResources().getText(); + File file = createLegalFile(resourceFactory.fromUri(license.toURI()).asFile(), "LICENSE.txt"); + metaInf.from(file); + } + catch (URISyntaxException ex) { + throw new GradleException("Failed to copy LICENSE.txt", ex); + } + } + + File createLegalFile(File source, String filename) { + File legalFile = new File(source.getParentFile(), filename); + source.renameTo(legalFile); + return legalFile; + } + +} diff --git a/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java new file mode 100644 index 00000000000..91d0b27dac1 --- /dev/null +++ b/buildSrc/src/main/java/org/springframework/boot/build/MavenPublishingConventions.java @@ -0,0 +1,116 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.build; + +import org.apache.maven.artifact.repository.MavenArtifactRepository; +import org.gradle.api.Project; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.publish.PublishingExtension; +import org.gradle.api.publish.maven.MavenPom; +import org.gradle.api.publish.maven.MavenPomDeveloperSpec; +import org.gradle.api.publish.maven.MavenPomIssueManagement; +import org.gradle.api.publish.maven.MavenPomLicenseSpec; +import org.gradle.api.publish.maven.MavenPomOrganization; +import org.gradle.api.publish.maven.MavenPomScm; +import org.gradle.api.publish.maven.MavenPublication; +import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; + +/** + * Conventions that are applied in the presence of the {@link MavenPublishPlugin}. When + * the plugin is applied: + * + *

+ * + *

+ * + * @author Andy Wilkinson + * @author Christoph Dreis + * @author Mike Smithson + */ +class MavenPublishingConventions { + + void apply(Project project) { + project.getPlugins().withType(MavenPublishPlugin.class).all((mavenPublish) -> { + PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); + if (project.hasProperty("deploymentRepository")) { + publishing.getRepositories().maven((mavenRepository) -> { + mavenRepository.setUrl(project.property("deploymentRepository")); + mavenRepository.setName("deployment"); + }); + } + publishing.getPublications().withType(MavenPublication.class) + .all((mavenPublication) -> customizePom(mavenPublication.getPom(), project)); + project.getPlugins().withType(JavaPlugin.class).all((javaPlugin) -> { + JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class); + extension.withJavadocJar(); + extension.withSourcesJar(); + }); + }); + } + + private void customizePom(MavenPom pom, Project project) { + pom.getUrl().set("https://projects.spring.io/spring-boot/#"); + pom.getDescription().set(project.provider(project::getDescription)); + pom.organization(this::customizeOrganization); + pom.licenses(this::customizeLicences); + pom.developers(this::customizeDevelopers); + pom.scm(this::customizeScm); + pom.issueManagement(this::customizeIssueManagement); + } + + private void customizeOrganization(MavenPomOrganization organization) { + organization.getName().set("Pivotal Software, Inc."); + organization.getUrl().set("https://spring.io"); + } + + private void customizeLicences(MavenPomLicenseSpec licences) { + licences.license((licence) -> { + licence.getName().set("Apache License, Version 2.0"); + licence.getUrl().set("http://www.apache.org/licenses/LICENSE-2.0"); + }); + } + + private void customizeDevelopers(MavenPomDeveloperSpec developers) { + developers.developer((developer) -> { + developer.getName().set("Pivotal"); + developer.getEmail().set("info@pivotal.io"); + developer.getOrganization().set("Pivotal Software, Inc."); + developer.getOrganizationUrl().set("https://www.spring.io"); + }); + } + + private void customizeScm(MavenPomScm scm) { + scm.getConnection().set("scm:git:git://github.com/spring-projects/spring-boot.git"); + scm.getDeveloperConnection().set("scm:git:ssh://git@github.com/spring-projects/spring-boot.git"); + scm.getUrl().set("https://github.com/spring-projects/spring-boot"); + } + + private void customizeIssueManagement(MavenPomIssueManagement issueManagement) { + issueManagement.getSystem().set("GitHub"); + issueManagement.getUrl().set("https://github.com/spring-projects/spring-boot/issues"); + } + +}