diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/GitProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/GitProperties.java index ba5aff3c9c7..fba523be0aa 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/GitProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/info/GitProperties.java @@ -19,7 +19,11 @@ package org.springframework.boot.info; import java.time.Instant; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.Objects; import java.util.Properties; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; @@ -35,6 +39,9 @@ import org.springframework.context.annotation.ImportRuntimeHints; @ImportRuntimeHints(GitPropertiesRuntimeHints.class) public class GitProperties extends InfoProperties { + static final Set coercers = Set.of(Coercer.milliseconds(), + Coercer.dateTimePattern("yyyy-MM-dd'T'HH:mm:ssXXX"), Coercer.dateTimePattern("yyyy-MM-dd'T'HH:mm:ssZ")); + public GitProperties(Properties entries) { super(processEntries(entries)); } @@ -97,41 +104,18 @@ public class GitProperties extends InfoProperties { private static void coercePropertyToEpoch(Properties properties, String key) { String value = properties.getProperty(key); if (value != null) { - properties.setProperty(key, coerceToEpoch(value)); + properties.setProperty(key, + coercers.stream() + .map((coercer) -> coercer.apply(value)) + .filter(Objects::nonNull) + .findFirst() + .orElse(value)); } } /** - * Attempt to convert the specified value to epoch time. Git properties information - * are known to be specified either as epoch time in seconds or using a specific date - * format. - * @param s the value to coerce to - * @return the epoch time in milliseconds or the original value if it couldn't be - * converted + * {@link RuntimeHintsRegistrar} for git properties. */ - private static String coerceToEpoch(String s) { - Long epoch = parseEpochSecond(s); - if (epoch != null) { - return String.valueOf(epoch); - } - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); - try { - return String.valueOf(format.parse(s, Instant::from).toEpochMilli()); - } - catch (DateTimeParseException ex) { - return s; - } - } - - private static Long parseEpochSecond(String s) { - try { - return Long.parseLong(s) * 1000; - } - catch (NumberFormatException ex) { - return null; - } - } - static class GitPropertiesRuntimeHints implements RuntimeHintsRegistrar { @Override @@ -141,4 +125,39 @@ public class GitProperties extends InfoProperties { } + /** + * Coercer used to convert a source value to epoch time. + */ + private record Coercer(Function action, Predicate ignoredExceptions) { + + /** + * Attempt to convert the specified value to epoch time. + * @param value the value to coerce to + * @return the epoch time in milliseconds or {@code null} + */ + String apply(String value) { + try { + Long result = this.action.apply(value); + return (result != null) ? String.valueOf(result) : null; + } + catch (RuntimeException ex) { + if (this.ignoredExceptions.test(ex)) { + return null; + } + throw ex; + } + } + + static Coercer milliseconds() { + return new Coercer((value) -> Long.parseLong(value) * 1000, NumberFormatException.class::isInstance); + } + + static Coercer dateTimePattern(String pattern) { + return new Coercer( + (value) -> DateTimeFormatter.ofPattern(pattern).parse(value, Instant::from).toEpochMilli(), + DateTimeParseException.class::isInstance); + } + + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/GitPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/GitPropertiesTests.java index 0a6d583d8e2..3481bea392c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/GitPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/info/GitPropertiesTests.java @@ -60,7 +60,7 @@ class GitPropertiesTests { } @Test - void coerceDateString() { + void coerceLegacyDateString() { GitProperties properties = new GitProperties( createProperties("master", "abcdefg", null, "2016-03-04T14:36:33+0100")); assertThat(properties.getCommitTime()).isNotNull(); @@ -68,6 +68,15 @@ class GitPropertiesTests { assertThat(properties.getCommitTime().toEpochMilli()).isEqualTo(1457098593000L); } + @Test + void coerceDateString() { + GitProperties properties = new GitProperties( + createProperties("master", "abcdefg", null, "2016-03-04T14:36:33+01:00")); + assertThat(properties.getCommitTime()).isNotNull(); + assertThat(properties.get("commit.time")).isEqualTo("1457098593000"); + assertThat(properties.getCommitTime().toEpochMilli()).isEqualTo(1457098593000L); + } + @Test void coerceUnsupportedFormat() { GitProperties properties = new GitProperties(