From f11fa0c309fced83e147f6b62d6754f25a6c6299 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 4 Mar 2016 17:14:34 +0100 Subject: [PATCH] Use `java.util.Date` rather than a raw String This commit updates `GitInfo` to use a proper `java.util.Date` rather than a raw String. Because the Maven and Gradle plugin do not agree on a format, `ProjectInfoAutoConfiguration` now registers a `Converter` that is taking care of translating the raw `String` to a `Date`. See gh-2484 --- .../boot/autoconfigure/info/GitInfo.java | 8 +- .../info/ProjectInfoAutoConfiguration.java | 89 ++++++++++++++++--- .../ProjectInfoAutoConfigurationTests.java | 15 ++-- .../autoconfigure/info/git-epoch.properties | 5 ++ 4 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/info/git-epoch.properties diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/GitInfo.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/GitInfo.java index 13e1b1b481..8e8bfc1b40 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/GitInfo.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/GitInfo.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.info; +import java.util.Date; + /** * Provide git-related information such as commit id and time. * @@ -45,7 +47,7 @@ public class GitInfo { private String id; - private String time; + private Date time; public String getId() { return (this.id == null ? "" : getShortId(this.id)); @@ -59,11 +61,11 @@ public class GitInfo { this.id = id; } - public String getTime() { + public Date getTime() { return this.time; } - public void setTime(String time) { + public void setTime(Date time) { this.time = time; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java index f3e43a04e5..852cc379a4 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java @@ -16,8 +16,14 @@ package org.springframework.boot.autoconfigure.info; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; import java.util.Properties; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -29,11 +35,18 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.env.PropertyResolver; import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.validation.BindException; /** * {@link EnableAutoConfiguration Auto-configuration} for various project information. @@ -45,24 +58,38 @@ import org.springframework.core.type.AnnotatedTypeMetadata; @EnableConfigurationProperties(ProjectInfoProperties.class) public class ProjectInfoAutoConfiguration { - @Configuration + @Autowired + private ProjectInfoProperties properties; + + private final ConversionService conversionService = createConversionService(); + @Conditional(GitResourceAvailableCondition.class) - protected static class GitInfoAutoConfiguration { - - @ConditionalOnMissingBean - @Bean - public GitInfo gitInfo(ProjectInfoProperties properties) throws Exception { - PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory( - new GitInfo()); - factory.setTargetName("git"); - Properties gitInfoProperties = PropertiesLoaderUtils - .loadProperties(properties.getGit().getLocation()); - factory.setProperties(gitInfoProperties); - return factory.getObject(); - } + @ConditionalOnMissingBean + @Bean + public GitInfo gitInfo() throws Exception { + GitInfo gitInfo = new GitInfo(); + bindPropertiesTo(gitInfo, this.properties.getGit().getLocation(), "git"); + return gitInfo; + } + + protected void bindPropertiesTo(Object target, Resource location, String prefix) + throws BindException, IOException { + PropertiesConfigurationFactory factory = + new PropertiesConfigurationFactory(target); + factory.setConversionService(this.conversionService); + factory.setTargetName(prefix); + Properties gitInfoProperties = PropertiesLoaderUtils.loadProperties(location); + factory.setProperties(gitInfoProperties); + factory.bindPropertiesToTarget(); + } + private static ConversionService createConversionService() { + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.addConverter(new StringToDateConverter()); + return conversionService; } + static class GitResourceAvailableCondition extends SpringBootCondition { private final ResourceLoader defaultResourceLoader = new DefaultResourceLoader(); @@ -90,4 +117,38 @@ public class ProjectInfoAutoConfiguration { } + private static class StringToDateConverter implements Converter { + + @Override + public Date convert(String s) { + Long epoch = parseEpochSecond(s); + if (epoch != null) { + return new Date(epoch); + } + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.US); + try { + return format.parse(s); + } + catch (ParseException ex) { + throw new ConversionFailedException(TypeDescriptor.valueOf(String.class), + TypeDescriptor.valueOf(Date.class), s, ex); + } + } + + /** + * Attempt to parse a {@code Long} from the specified input, representing the + * epoch time in seconds. + * @param s the input + * @return the epoch time in msec + */ + private Long parseEpochSecond(String s) { + try { + return Long.parseLong(s) * 1000; + } + catch (NumberFormatException e) { + return null; + } + } + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfigurationTests.java index da6daf2908..72ec269b37 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfigurationTests.java @@ -57,14 +57,18 @@ public class ProjectInfoAutoConfigurationTests { load("spring.info.git.location=classpath:/org/springframework/boot/autoconfigure/info/git.properties", "spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-no-data.properties"); GitInfo gitInfo = this.context.getBean(GitInfo.class); - assertGitInfo(gitInfo); + assertThat(gitInfo.getBranch()).isNull(); + assertThat(gitInfo.getCommit().getId()).isEqualTo("f95038e"); + assertThat(gitInfo.getCommit().getTime()).isEqualTo("2016-03-03T10:02:00"); } @Test public void gitLegacyKeyIsUsedAsFallback() { - load("spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git.properties"); + load("spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-epoch.properties"); GitInfo gitInfo = this.context.getBean(GitInfo.class); - assertGitInfo(gitInfo); + assertThat(gitInfo.getBranch()).isEqualTo("master"); + assertThat(gitInfo.getCommit().getId()).isEqualTo("5009933"); + assertThat(gitInfo.getCommit().getTime()).isEqualTo("2016-03-04T16:04:10"); } @Test @@ -82,11 +86,6 @@ public class ProjectInfoAutoConfigurationTests { assertThat(gitInfo).isSameAs(this.context.getBean("customGitInfo")); } - private void assertGitInfo(GitInfo gitInfo) { - assertThat(gitInfo.getBranch()).isNull(); - assertThat(gitInfo.getCommit().getId()).isEqualTo("f95038e"); - assertThat(gitInfo.getCommit().getTime()).isEqualTo("2016-03-03T10:02:00+0100"); - } private void load(String... environment) { load(null, environment); diff --git a/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/info/git-epoch.properties b/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/info/git-epoch.properties new file mode 100644 index 0000000000..2f7c545d06 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/info/git-epoch.properties @@ -0,0 +1,5 @@ +git.branch=master +git.commit.user.email=john@example.com +git.commit.id=5009933788f5f8c687719de6a697074ff80b1b69 +git.commit.user.name=John Smith +git.commit.time=1457103850