Add support of YAML
This commit migrates the YAML support available in Spring Boot to the core framework. YAML documents can be loaded either as a properties object or as a map. Issue: SPR-9897
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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
|
||||
*
|
||||
* http://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.beans.factory.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.AbstractResource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Tests for {@link YamlMapFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class YamlMapFactoryBeanTests {
|
||||
|
||||
private final YamlMapFactoryBean factory = new YamlMapFactoryBean();
|
||||
|
||||
@Test
|
||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
||||
this.factory
|
||||
.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObject() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo: bar".getBytes())});
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testOverrideAndremoveDefaults() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {
|
||||
new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes())});
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
assertEquals(2,
|
||||
((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstFound() throws Exception {
|
||||
this.factory.setResolutionMethod(YamlProcessor.ResolutionMethod.FIRST_FOUND);
|
||||
this.factory.setResources(new Resource[] {new AbstractResource() {
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "non-existent";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
throw new IOException("planned");
|
||||
}
|
||||
}, new ByteArrayResource("foo:\n spam: bar".getBytes())});
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithPeriodsInKey() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo:\n ? key1.key2\n : value".getBytes())});
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("foo"));
|
||||
Object object = map.get("foo");
|
||||
assertTrue(object instanceof LinkedHashMap);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> sub = (Map<String, Object>) object;
|
||||
assertTrue(sub.containsKey("key1.key2"));
|
||||
assertEquals("value", sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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
|
||||
*
|
||||
* http://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.beans.factory.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.beans.factory.config.YamlProcessor.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Tests for {@link YamlProcessor}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class YamlProcessorTests {
|
||||
|
||||
private final YamlProcessor processor = new YamlProcessor() {
|
||||
};
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void arrayConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nbar: [1,2,3]".getBytes())});
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals(4, properties.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringResource() throws Exception {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo # a document that is a literal".getBytes())});
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("foo", map.get("document"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadDocumentStart() throws Exception {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo # a document\nbar: baz".getBytes())});
|
||||
this.exception.expect(ParserException.class);
|
||||
this.exception.expectMessage("line 2, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes())});
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nbar:\n spam: bucket".getBytes())});
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
// System.err.println(properties);
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integerKeyBehaves() {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\n1: bar".getBytes())});
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("[1]"));
|
||||
assertEquals(2, properties.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integerDeepKeyBehaves() {
|
||||
this.processor.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo:\n 1: bar".getBytes())});
|
||||
this.processor.process(new MatchCallback() {
|
||||
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
assertEquals(1, properties.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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
|
||||
*
|
||||
* http://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.beans.factory.config;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.beans.factory.config.YamlProcessor.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Tests for {@link YamlPropertiesFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class YamlPropertiesFactoryBeanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testLoadResource() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nspam:\n foo: baz".getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes())});
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
factory.getObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourcesWithOverride() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {
|
||||
new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()),
|
||||
new ByteArrayResource("foo:\n bar: spam".getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
||||
public void testLoadResourcesWithInternalOverride() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nspam:\n foo: baz\nfoo: bucket".getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
||||
public void testLoadResourcesWithNestedInternalOverride() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo:\n bar: spam\n foo: baz\nbreak: it\nfoo: bucket".getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithMultipleDocuments() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nspam: baz\n---\nfoo: bag".getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithSelectedDocuments() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes())});
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithDefaultMatch() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(true);
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes())});
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||
assertThat(properties.getProperty("one"), equalTo("two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithoutDefaultMatch() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(false);
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes())});
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||
assertThat(properties.getProperty("one"), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(true);
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"one: two\n---\nfoo: bag\nspam: bad\n---\nfoo: bar\nspam: baz".getBytes())});
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||
assertThat(properties.getProperty("one"), equalTo("two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadNonExistentResource() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResolutionMethod(ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
factory.setResources(new Resource[] {new ClassPathResource("no-such-file.yml")});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadNull() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource("foo: bar\nspam:"
|
||||
.getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam"), equalTo(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfString() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource("foo:\n- bar\n- baz"
|
||||
.getBytes())});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0]"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfObject() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new Resource[] {new ByteArrayResource(
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four"
|
||||
.getBytes()
|
||||
)});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0].bar.spam"), equalTo("crap"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
||||
assertThat(properties.getProperty("foo[2].one"), equalTo("two"));
|
||||
assertThat(properties.getProperty("foo[2].three"), equalTo("four"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testYaml() {
|
||||
Yaml yaml = new Yaml();
|
||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"),
|
||||
equalTo((Object) "baz"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user