From 68c7c65d525d569a99cf677ad72e831b4d03e819 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 29 Jan 2015 11:02:24 +0000 Subject: [PATCH] Configure SnakeYAML so the timestamp-like strings do not become Dates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default, SnakeYAML will convert a timestamp-like string into a java.util.Date. This differs to properties file-based configuration where the values are always strings. Dates are problematic as the round trip (string -> Date -> string) can change the value. For example, “2015-01-27” becomes “Tue Jan 27 00:00:00 GMT 2015”. This commit updates YamlPropertySourceLoader to use a Yaml with a custom Resolver subclass that suppresses the addition of the implicit resolver for timestamps. Supressing the addition of the unwanted resolver, rather than overriding addImplicitResolvers and registering the resolvers that we do want, ensures that we get all of the other default Resolvers in their default order. Fixes gh-2422 --- spring-boot-dependencies/pom.xml | 2 +- .../boot/env/YamlPropertySourceLoader.java | 24 ++++++++++++++++++- .../env/YamlPropertySourceLoaderTests.java | 11 ++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index 9575bc32d7..533b41f4fd 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -111,7 +111,7 @@ 1.14 4.7.2 0.7-groovy-2.0 - 4.1.4.RELEASE + 4.1.5.BUILD-SNAPSHOT 1.4.2.RELEASE 1.1.1.RELEASE 3.0.2.RELEASE diff --git a/spring-boot/src/main/java/org/springframework/boot/env/YamlPropertySourceLoader.java b/spring-boot/src/main/java/org/springframework/boot/env/YamlPropertySourceLoader.java index 58e8bde5f4..ea606f16f5 100644 --- a/spring-boot/src/main/java/org/springframework/boot/env/YamlPropertySourceLoader.java +++ b/spring-boot/src/main/java/org/springframework/boot/env/YamlPropertySourceLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 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. @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; import org.springframework.beans.factory.config.YamlProcessor; import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; @@ -28,12 +29,18 @@ import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.Resource; import org.springframework.util.ClassUtils; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; +import org.yaml.snakeyaml.resolver.Resolver; /** * Strategy to load '.yml' (or '.yaml') files into a {@link PropertySource}. * * @author Dave Syer * @author Phillip Webb + * @author Andy Wilkinson */ public class YamlPropertySourceLoader implements PropertySourceLoader { @@ -73,6 +80,21 @@ public class YamlPropertySourceLoader implements PropertySourceLoader { setResources(new Resource[] { resource }); } + @Override + protected Yaml createYaml() { + return new Yaml(new StrictMapAppenderConstructor(), new Representer(), + new DumperOptions(), new Resolver() { + @Override + public void addImplicitResolver(Tag tag, Pattern regexp, + String first) { + if (tag == Tag.TIMESTAMP) { + return; + } + super.addImplicitResolver(tag, regexp, first); + } + }); + } + public Map process() { final Map result = new LinkedHashMap(); process(new MatchCallback() { diff --git a/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderTests.java b/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderTests.java index c2bf7ce3c3..d8af41fefc 100644 --- a/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/env/YamlPropertySourceLoaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 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. @@ -34,6 +34,7 @@ import static org.junit.Assert.assertThat; * * @author Dave Syer * @author Phillip Webb + * @author Andy Wilkinson */ public class YamlPropertySourceLoaderTests { @@ -75,4 +76,12 @@ public class YamlPropertySourceLoaderTests { assertEquals("wham", source.getProperty("foo.baz")); } + @Test + public void timestampLikeItemsDoNotBecomeDates() throws Exception { + ByteArrayResource resource = new ByteArrayResource("foo: 2015-01-28".getBytes()); + PropertySource source = this.loader.load("resource", resource, null); + assertNotNull(source); + assertEquals("2015-01-28", source.getProperty("foo")); + } + }