From 027093d852d3bd8a69f3e4617356e86a517fa7ea Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 18 Feb 2022 15:55:25 +0000 Subject: [PATCH] Use a templated source file for SpringBootVersion Closes gh-29670 --- .../build/GeneratePropertiesResource.java | 81 ------------------- .../boot/build/JavaConventions.java | 49 +++++------ .../boot/build/ConventionsPluginTests.java | 10 --- spring-boot-project/spring-boot/build.gradle | 19 +++++ .../boot/SpringBootVersion.java | 28 +------ .../boot/SpringBootVersionTests.java | 56 +++++++++++++ 6 files changed, 97 insertions(+), 146 deletions(-) delete mode 100644 buildSrc/src/main/java/org/springframework/boot/build/GeneratePropertiesResource.java rename spring-boot-project/spring-boot/src/main/{java => javaTemplates}/org/springframework/boot/SpringBootVersion.java (54%) create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringBootVersionTests.java diff --git a/buildSrc/src/main/java/org/springframework/boot/build/GeneratePropertiesResource.java b/buildSrc/src/main/java/org/springframework/boot/build/GeneratePropertiesResource.java deleted file mode 100644 index 7f766ac0a8..0000000000 --- a/buildSrc/src/main/java/org/springframework/boot/build/GeneratePropertiesResource.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; - -import org.gradle.api.DefaultTask; -import org.gradle.api.Task; -import org.gradle.api.file.DirectoryProperty; -import org.gradle.api.model.ObjectFactory; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.OutputDirectory; -import org.gradle.api.tasks.TaskAction; - -/** - * {@link Task} to generate properties and write them to disk as a properties file. - * - * @author Scott Frederick - */ -public class GeneratePropertiesResource extends DefaultTask { - - private final Property propertiesFileName; - - private final DirectoryProperty destinationDirectory; - - private final Map properties = new HashMap<>(); - - public GeneratePropertiesResource() { - ObjectFactory objects = getProject().getObjects(); - this.propertiesFileName = objects.property(String.class); - this.destinationDirectory = objects.directoryProperty(); - } - - @OutputDirectory - public DirectoryProperty getDestinationDirectory() { - return this.destinationDirectory; - } - - @Input - public Property getPropertiesFileName() { - return this.propertiesFileName; - } - - public void property(String name, String value) { - this.properties.put(name, value); - } - - @Input - public Map getProperties() { - return this.properties; - } - - @TaskAction - void generatePropertiesFile() throws IOException { - File outputFile = this.destinationDirectory.file(this.propertiesFileName).get().getAsFile(); - try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) { - this.properties.forEach((key, value) -> writer.printf("%s=%s\n", key, value)); - } - } - -} diff --git a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java index 8fd944299f..d82ba98cec 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -104,8 +104,6 @@ class JavaConventions { private static final String SOURCE_AND_TARGET_COMPATIBILITY = "1.8"; - private static final String SPRING_BOOT_PROPERTIES_FILE = "spring-boot.properties"; - void apply(Project project) { project.getPlugins().withType(JavaBasePlugin.class, (java) -> { project.getPlugins().apply(TestFailuresPlugin.class); @@ -114,7 +112,6 @@ class JavaConventions { configureJavadocConventions(project); configureTestConventions(project); configureJarManifestConventions(project); - configureMetaInfResourcesConventions(project); configureDependencyManagement(project); configureToolchain(project); configureProhibitedDependencyChecks(project); @@ -122,37 +119,29 @@ class JavaConventions { } private void configureJarManifestConventions(Project project) { - SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); - Set sourceJarTaskNames = sourceSets.stream().map(SourceSet::getSourcesJarTaskName) - .collect(Collectors.toSet()); - Set javadocJarTaskNames = sourceSets.stream().map(SourceSet::getJavadocJarTaskName) - .collect(Collectors.toSet()); - project.getTasks().withType(Jar.class, - (jar) -> project.afterEvaluate((evaluated) -> jar.manifest((manifest) -> { - Map attributes = new TreeMap<>(); - attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); - attributes.put("Build-Jdk-Spec", SOURCE_AND_TARGET_COMPATIBILITY); - attributes.put("Built-By", "Spring"); - attributes.put("Implementation-Title", - determineImplementationTitle(project, sourceJarTaskNames, javadocJarTaskNames, jar)); - attributes.put("Implementation-Version", project.getVersion()); - manifest.attributes(attributes); - }))); - } - - private void configureMetaInfResourcesConventions(Project project) { ExtractResources extractLegalResources = project.getTasks().create("extractLegalResources", ExtractResources.class); extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal")); extractLegalResources.setResourcesNames(Arrays.asList("LICENSE.txt", "NOTICE.txt")); extractLegalResources.property("version", project.getVersion().toString()); - GeneratePropertiesResource generateInfo = project.getTasks().create("generateSpringBootInfo", - GeneratePropertiesResource.class); - generateInfo.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("info")); - generateInfo.getPropertiesFileName().set(SPRING_BOOT_PROPERTIES_FILE); - generateInfo.property("version", project.getVersion().toString()); - project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate( - (evaluated) -> jar.metaInf((metaInf) -> metaInf.from(extractLegalResources, generateInfo)))); + SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); + Set sourceJarTaskNames = sourceSets.stream().map(SourceSet::getSourcesJarTaskName) + .collect(Collectors.toSet()); + Set javadocJarTaskNames = sourceSets.stream().map(SourceSet::getJavadocJarTaskName) + .collect(Collectors.toSet()); + project.getTasks().withType(Jar.class, (jar) -> project.afterEvaluate((evaluated) -> { + jar.metaInf((metaInf) -> metaInf.from(extractLegalResources)); + jar.manifest((manifest) -> { + Map attributes = new TreeMap<>(); + attributes.put("Automatic-Module-Name", project.getName().replace("-", ".")); + attributes.put("Build-Jdk-Spec", SOURCE_AND_TARGET_COMPATIBILITY); + attributes.put("Built-By", "Spring"); + attributes.put("Implementation-Title", + determineImplementationTitle(project, sourceJarTaskNames, javadocJarTaskNames, jar)); + attributes.put("Implementation-Version", project.getVersion()); + manifest.attributes(attributes); + }); + })); } private String determineImplementationTitle(Project project, Set sourceJarTaskNames, diff --git a/buildSrc/src/test/java/org/springframework/boot/build/ConventionsPluginTests.java b/buildSrc/src/test/java/org/springframework/boot/build/ConventionsPluginTests.java index 9ac6a05dcd..8bfd16d586 100644 --- a/buildSrc/src/test/java/org/springframework/boot/build/ConventionsPluginTests.java +++ b/buildSrc/src/test/java/org/springframework/boot/build/ConventionsPluginTests.java @@ -83,7 +83,6 @@ class ConventionsPluginTests { try (JarFile jar = new JarFile(file)) { assertThatLicenseIsPresent(jar); assertThatNoticeIsPresent(jar); - assertThatSpringBootPropertiesIsPresent(jar); Attributes mainAttributes = jar.getManifest().getMainAttributes(); assertThat(mainAttributes.getValue("Implementation-Title")) .isEqualTo("Test project for manifest customization"); @@ -113,7 +112,6 @@ class ConventionsPluginTests { try (JarFile jar = new JarFile(file)) { assertThatLicenseIsPresent(jar); assertThatNoticeIsPresent(jar); - assertThatSpringBootPropertiesIsPresent(jar); Attributes mainAttributes = jar.getManifest().getMainAttributes(); assertThat(mainAttributes.getValue("Implementation-Title")) .isEqualTo("Source for " + this.projectDir.getName()); @@ -143,7 +141,6 @@ class ConventionsPluginTests { try (JarFile jar = new JarFile(file)) { assertThatLicenseIsPresent(jar); assertThatNoticeIsPresent(jar); - assertThatSpringBootPropertiesIsPresent(jar); Attributes mainAttributes = jar.getManifest().getMainAttributes(); assertThat(mainAttributes.getValue("Implementation-Title")) .isEqualTo("Javadoc for " + this.projectDir.getName()); @@ -168,13 +165,6 @@ class ConventionsPluginTests { assertThat(noticeContent).doesNotContain("${"); } - private void assertThatSpringBootPropertiesIsPresent(JarFile jar) throws IOException { - JarEntry properties = jar.getJarEntry("META-INF/spring-boot.properties"); - assertThat(properties).isNotNull(); - String content = FileCopyUtils.copyToString(new InputStreamReader(jar.getInputStream(properties))); - assertThat(content).contains("version="); - } - @Test void testRetryIsConfiguredWithThreeRetriesOnCI() throws IOException { try (PrintWriter out = new PrintWriter(new FileWriter(this.buildFile))) { diff --git a/spring-boot-project/spring-boot/build.gradle b/spring-boot-project/spring-boot/build.gradle index 246b24ae2f..a018bd1dc3 100644 --- a/spring-boot-project/spring-boot/build.gradle +++ b/spring-boot-project/spring-boot/build.gradle @@ -155,7 +155,26 @@ task extractTomcatConfigProperties(type: Sync) { } } +def syncJavaTemplates = tasks.register("syncJavaTemplates", Sync) { + from("src/main/javaTemplates") + into("build/generated-sources/main") + def properties = ["springBootVersion": project.version] + expand(properties) + inputs.properties(properties) +} + +plugins.withType(EclipsePlugin) { + eclipse { + synchronizationTasks syncJavaTemplates + } +} + sourceSets { + main { + java { + srcDirs syncJavaTemplates + } + } test { output.dir(tomcatConfigProperties, builtBy: "extractTomcatConfigProperties") } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringBootVersion.java b/spring-boot-project/spring-boot/src/main/javaTemplates/org/springframework/boot/SpringBootVersion.java similarity index 54% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringBootVersion.java rename to spring-boot-project/spring-boot/src/main/javaTemplates/org/springframework/boot/SpringBootVersion.java index f507461800..978e53aa3c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringBootVersion.java +++ b/spring-boot-project/spring-boot/src/main/javaTemplates/org/springframework/boot/SpringBootVersion.java @@ -16,18 +16,9 @@ package org.springframework.boot; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - /** * Exposes the Spring Boot version. * - * The version information is read from a file that is stored in the Spring Boot library. - * If the version information cannot be read from the file, consider using a - * reflection-based check instead (for example, checking for the presence of a specific - * Spring Boot method that you intend to call). - * * @author Drummond Dawson * @author Hendrig Sellik * @author Andy Wilkinson @@ -40,24 +31,11 @@ public final class SpringBootVersion { } /** - * Return the full version string of the present Spring Boot codebase, or {@code null} - * if it cannot be determined. - * @return the version of Spring Boot or {@code null} + * Return the full version string of the present Spring Boot codebase. + * @return the version of Spring Boot */ public static String getVersion() { - InputStream input = SpringBootVersion.class.getClassLoader() - .getResourceAsStream("META-INF/spring-boot.properties"); - if (input != null) { - try { - Properties properties = new Properties(); - properties.load(input); - return properties.getProperty("version"); - } - catch (IOException ex) { - // fall through - } - } - return null; + return "${springBootVersion}"; } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringBootVersionTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringBootVersionTests.java new file mode 100644 index 0000000000..9e6995b3b5 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringBootVersionTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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; + +import java.io.File; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringBootVersion}. + * + * @author Andy Wilkinson + */ +public class SpringBootVersionTests { + + @Test + void getVersionShouldReturnVersionMatchingGradleProperties() throws IOException { + String expectedVersion = PropertiesLoaderUtils.loadProperties(new FileSystemResource(findGradleProperties())) + .getProperty("version"); + assertThat(SpringBootVersion.getVersion()).isEqualTo(expectedVersion); + } + + private File findGradleProperties() { + File current = new File(".").getAbsoluteFile(); + while (current != null) { + File gradleProperties = new File(current, "gradle.properties"); + System.out.println(gradleProperties); + if (gradleProperties.isFile()) { + return gradleProperties; + } + current = current.getParentFile(); + } + throw new IllegalStateException("Could not find gradle.properties"); + } + +}