From 40c1748e3c11a5c416f20c0c19ade618bb735efa Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 1 Feb 2021 16:20:55 -0800 Subject: [PATCH] Remove hardcoded versions from MavenBuild Use the dependencies BOM to ensure versions used in the `MavenBuild` test class are always aligned. Closes gh-23936 --- .../spring-boot-maven-plugin/build.gradle | 14 ++++ .../boot/maven/MavenBuild.java | 61 +++++++------- .../boot/maven/SpringBootDependenciesBom.java | 80 +++++++++++++++++++ .../intTest/projects/run-toolchains/pom.xml | 2 +- 4 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/SpringBootDependenciesBom.java diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle index 85b633b8b6..6c53789eaa 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/build.gradle @@ -9,6 +9,7 @@ plugins { description = "Spring Boot Maven Plugin" configurations { + dependenciesBom documentation } @@ -16,6 +17,8 @@ dependencies { compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations") compileOnly("org.sonatype.plexus:plexus-build-api") + dependenciesBom(project(path: ":spring-boot-project:spring-boot-dependencies", configuration: "effectiveBom")) + implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools")) implementation("org.apache.maven.shared:maven-common-artifact-filters") @@ -41,12 +44,23 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher") } +task syncSpringBootDependenciesBom(type: Sync) { + destinationDir = file("${buildDir}/generated/sources/dependencies-bom/org/springframework/boot/maven") + from configurations.dependenciesBom +} + syncDocumentationSourceForAsciidoctor { from(documentPluginGoals) { into "asciidoc/goals" } } +sourceSets { + main { + output.dir("${buildDir}/generated/sources/dependencies-bom", builtBy: "syncSpringBootDependenciesBom") + } +} + tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) { doFirst { def versionEl = version.split("\\.") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java index 3eede5f474..abd52b5635 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/MavenBuild.java @@ -17,11 +17,9 @@ package org.springframework.boot.maven; import java.io.File; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; -import java.io.Reader; import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -62,7 +60,7 @@ class MavenBuild { private final File temp; - private final Map pomReplacements = new HashMap<>(); + private final Map pomReplacements; private final List goals = new ArrayList<>(); @@ -74,24 +72,38 @@ class MavenBuild { MavenBuild(File home) { this.home = home; + this.temp = createTempDirectory(); + this.pomReplacements = getPomReplacements(); + } + + private File createTempDirectory() { try { - this.temp = Files.createTempDirectory("maven-build").toFile().getCanonicalFile(); + return Files.createTempDirectory("maven-build").toFile().getCanonicalFile(); } catch (IOException ex) { - throw new RuntimeException(ex); + throw new IllegalStateException(ex); } - this.pomReplacements.put("java.version", "1.8"); - this.pomReplacements.put("project.groupId", "org.springframework.boot"); - this.pomReplacements.put("project.artifactId", "spring-boot-maven-plugin"); - this.pomReplacements.put("project.version", determineVersion()); - this.pomReplacements.put("log4j2.version", "2.13.3"); - this.pomReplacements.put("maven-jar-plugin.version", "3.2.0"); - this.pomReplacements.put("maven-toolchains-plugin.version", "3.0.0"); - this.pomReplacements.put("maven-war-plugin.version", "3.2.3"); - this.pomReplacements.put("build-helper-maven-plugin.version", "3.0.0"); - this.pomReplacements.put("spring-framework.version", "5.2.10.RELEASE"); - this.pomReplacements.put("jakarta-servlet.version", "4.0.4"); - this.pomReplacements.put("kotlin.version", "1.3.72"); + } + + private Map getPomReplacements() { + Map replacements = new HashMap<>(); + SpringBootDependenciesBom bom = new SpringBootDependenciesBom(); + replacements.put("java.version", "1.8"); + replacements.put("project.groupId", "org.springframework.boot"); + replacements.put("project.artifactId", "spring-boot-maven-plugin"); + replacements.put("project.version", bom.get("version")); + putReplacement(replacements, bom, "log4j2.version"); + putReplacement(replacements, bom, "maven-jar-plugin.version"); + putReplacement(replacements, bom, "maven-war-plugin.version"); + putReplacement(replacements, bom, "build-helper-maven-plugin.version"); + putReplacement(replacements, bom, "spring-framework.version"); + putReplacement(replacements, bom, "jakarta-servlet.version"); + putReplacement(replacements, bom, "kotlin.version"); + return Collections.unmodifiableMap(replacements); + } + + private void putReplacement(Map replacements, SpringBootDependenciesBom bom, String property) { + replacements.put(property, bom.get("properties/" + property)); } MavenBuild project(String project) { @@ -196,21 +208,6 @@ class MavenBuild { } } - private String determineVersion() { - File gradleProperties = new File("gradle.properties").getAbsoluteFile(); - while (!gradleProperties.isFile()) { - gradleProperties = new File(gradleProperties.getParentFile().getParentFile(), "gradle.properties"); - } - Properties properties = new Properties(); - try (Reader reader = new FileReader(gradleProperties)) { - properties.load(reader); - return properties.getProperty("version"); - } - catch (IOException ex) { - throw new RuntimeException(ex); - } - } - /** * Action to take on a maven project directory. */ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/SpringBootDependenciesBom.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/SpringBootDependenciesBom.java new file mode 100644 index 0000000000..9a3e089356 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/SpringBootDependenciesBom.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.maven; + +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import org.springframework.util.Assert; + +/** + * Provides access to values in the spring-boot-dependencies effective BOM. + * + * @author Phillip Webb + */ +class SpringBootDependenciesBom { + + private static final String XML = "spring-boot-dependencies-effective-bom.xml"; + + private final Document document; + + private final XPath xpath; + + SpringBootDependenciesBom() { + this.document = loadDocument(); + this.xpath = XPathFactory.newInstance().newXPath(); + } + + private Document loadDocument() { + try { + try (InputStream inputStream = getClass().getResourceAsStream(XML)) { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + return builder.parse(inputStream); + } + } + catch (ParserConfigurationException | SAXException | IOException ex) { + throw new IllegalStateException(ex); + } + } + + String get(String expression) { + try { + Node node = (Node) this.xpath.compile("/project/" + expression).evaluate(this.document, + XPathConstants.NODE); + String text = (node != null) ? node.getTextContent() : null; + Assert.hasLength(text, () -> "No result for expression " + expression); + return text; + } + catch (XPathExpressionException ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/run-toolchains/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/run-toolchains/pom.xml index 507d7922f2..73800467e8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/run-toolchains/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/run-toolchains/pom.xml @@ -15,7 +15,7 @@ org.apache.maven.plugins maven-toolchains-plugin - @maven-toolchains-plugin.version@ + 3.0.0