YamlProcessor embraces SnakeYAML 1.18+ duplicate key handling
Includes removal of StrictMapAppenderConstructor for compatibility with SnakeYAML 1.21. Issue: SPR-16791
This commit is contained in:
parent
7b894fe73b
commit
138b0d0bbd
|
@ -5,7 +5,7 @@ apply plugin: "groovy"
|
||||||
dependencies {
|
dependencies {
|
||||||
compile(project(':spring-core'))
|
compile(project(':spring-core'))
|
||||||
optional("javax.inject:javax.inject:1")
|
optional("javax.inject:javax.inject:1")
|
||||||
optional("org.yaml:snakeyaml:1.20")
|
optional("org.yaml:snakeyaml:1.21")
|
||||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -64,6 +64,8 @@ import org.springframework.lang.Nullable;
|
||||||
* Note that the value of "foo" in the first document is not simply replaced
|
* Note that the value of "foo" in the first document is not simply replaced
|
||||||
* with the value in the second, but its nested values are merged.
|
* with the value in the second, but its nested values are merged.
|
||||||
*
|
*
|
||||||
|
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.beans.factory.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -26,14 +25,11 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.yaml.snakeyaml.LoaderOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
import org.yaml.snakeyaml.constructor.Constructor;
|
|
||||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
|
||||||
import org.yaml.snakeyaml.parser.ParserException;
|
|
||||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
@ -45,6 +41,8 @@ import org.springframework.util.StringUtils;
|
||||||
/**
|
/**
|
||||||
* Base class for YAML factories.
|
* Base class for YAML factories.
|
||||||
*
|
*
|
||||||
|
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
@ -144,9 +142,14 @@ public abstract class YamlProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the {@link Yaml} instance to use.
|
* Create the {@link Yaml} instance to use.
|
||||||
|
* <p>The default implementation sets the "allowDuplicateKeys" flag to {@code false},
|
||||||
|
* enabling built-in duplicate key handling in SnakeYAML 1.18+.
|
||||||
|
* @see LoaderOptions#setAllowDuplicateKeys(boolean)
|
||||||
*/
|
*/
|
||||||
protected Yaml createYaml() {
|
protected Yaml createYaml() {
|
||||||
return new Yaml(new StrictMapAppenderConstructor());
|
LoaderOptions options = new LoaderOptions();
|
||||||
|
options.setAllowDuplicateKeys(false);
|
||||||
|
return new Yaml(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||||
|
@ -390,45 +393,4 @@ public abstract class YamlProcessor {
|
||||||
FIRST_FOUND
|
FIRST_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A specialized {@link Constructor} that checks for duplicate keys.
|
|
||||||
*/
|
|
||||||
protected static class StrictMapAppenderConstructor extends Constructor {
|
|
||||||
|
|
||||||
// Declared as public for use in subclasses
|
|
||||||
public StrictMapAppenderConstructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<Object, Object> constructMapping(MappingNode node) {
|
|
||||||
try {
|
|
||||||
return super.constructMapping(node);
|
|
||||||
}
|
|
||||||
catch (IllegalStateException ex) {
|
|
||||||
throw new ParserException("while parsing MappingNode",
|
|
||||||
node.getStartMark(), ex.getMessage(), node.getEndMark());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<Object, Object> createDefaultMap() {
|
|
||||||
final Map<Object, Object> delegate = super.createDefaultMap();
|
|
||||||
return new AbstractMap<Object, Object>() {
|
|
||||||
@Override
|
|
||||||
public Object put(Object key, Object value) {
|
|
||||||
if (delegate.containsKey(key)) {
|
|
||||||
throw new IllegalStateException("Duplicate key: " + key);
|
|
||||||
}
|
|
||||||
return delegate.put(key, value);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Set<Entry<Object, Object>> entrySet() {
|
|
||||||
return delegate.entrySet();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -74,6 +74,8 @@ import org.springframework.lang.Nullable;
|
||||||
* servers[1]=foo.bar.com
|
* servers[1]=foo.bar.com
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|
|
@ -19,10 +19,10 @@ package org.springframework.beans.factory.config;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.yaml.snakeyaml.constructor.DuplicateKeyException;
|
||||||
|
|
||||||
import org.springframework.core.io.AbstractResource;
|
import org.springframework.core.io.AbstractResource;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
@ -42,27 +42,27 @@ public class YamlMapFactoryBeanTests {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
public void testSetIgnoreResourceNotFound() {
|
||||||
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||||
assertEquals(0, this.factory.getObject().size());
|
assertEquals(0, this.factory.getObject().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
public void testSetBarfOnResourceNotFound() {
|
||||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||||
assertEquals(0, this.factory.getObject().size());
|
assertEquals(0, this.factory.getObject().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetObject() throws Exception {
|
public void testGetObject() {
|
||||||
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
|
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
|
||||||
assertEquals(1, this.factory.getObject().size());
|
assertEquals(1, this.factory.getObject().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testOverrideAndRemoveDefaults() throws Exception {
|
public void testOverrideAndRemoveDefaults() {
|
||||||
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||||
new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class YamlMapFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFirstFound() throws Exception {
|
public void testFirstFound() {
|
||||||
this.factory.setResolutionMethod(YamlProcessor.ResolutionMethod.FIRST_FOUND);
|
this.factory.setResolutionMethod(YamlProcessor.ResolutionMethod.FIRST_FOUND);
|
||||||
this.factory.setResources(new AbstractResource() {
|
this.factory.setResources(new AbstractResource() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,7 +88,7 @@ public class YamlMapFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMapWithPeriodsInKey() throws Exception {
|
public void testMapWithPeriodsInKey() {
|
||||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
|
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
|
||||||
Map<String, Object> map = this.factory.getObject();
|
Map<String, Object> map = this.factory.getObject();
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ public class YamlMapFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMapWithIntegerValue() throws Exception {
|
public void testMapWithIntegerValue() {
|
||||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
|
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
|
||||||
Map<String, Object> map = this.factory.getObject();
|
Map<String, Object> map = this.factory.getObject();
|
||||||
|
|
||||||
|
@ -117,33 +117,10 @@ public class YamlMapFactoryBeanTests {
|
||||||
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
|
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = DuplicateKeyException.class)
|
||||||
public void mapWithEmptyArrayValue() {
|
public void testDuplicateKey() {
|
||||||
this.factory.setResources(new ByteArrayResource("a: alpha\ntest: []".getBytes()));
|
|
||||||
assertTrue(this.factory.getObject().containsKey("test"));
|
|
||||||
assertEquals(((List<?>)this.factory.getObject().get("test")).size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mapWithEmptyValue() {
|
|
||||||
this.factory.setResources(new ByteArrayResource("a: alpha\ntest:".getBytes()));
|
|
||||||
assertTrue(this.factory.getObject().containsKey("test"));
|
|
||||||
assertNull(this.factory.getObject().get("test"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDuplicateKey() throws Exception {
|
|
||||||
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
|
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
|
||||||
Map<String, Object> map = this.factory.getObject();
|
this.factory.getObject().get("mymap");
|
||||||
|
|
||||||
assertEquals(1, map.size());
|
|
||||||
assertTrue(map.containsKey("mymap"));
|
|
||||||
Object object = map.get("mymap");
|
|
||||||
assertTrue(object instanceof LinkedHashMap);
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> sub = (Map<String, Object>) object;
|
|
||||||
assertEquals(1, sub.size());
|
|
||||||
assertEquals("foo", sub.get("bar"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,7 +18,6 @@ package org.springframework.beans.factory.config;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -29,7 +28,6 @@ import org.yaml.snakeyaml.scanner.ScannerException;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.springframework.beans.factory.config.YamlProcessor.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link YamlProcessor}.
|
* Tests for {@link YamlProcessor}.
|
||||||
|
@ -48,9 +46,7 @@ public class YamlProcessorTests {
|
||||||
@Test
|
@Test
|
||||||
public void arrayConvertedToIndexedBeanReference() {
|
public void arrayConvertedToIndexedBeanReference() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals(4, properties.size());
|
assertEquals(4, properties.size());
|
||||||
assertEquals("bar", properties.get("foo"));
|
assertEquals("bar", properties.get("foo"));
|
||||||
assertEquals("bar", properties.getProperty("foo"));
|
assertEquals("bar", properties.getProperty("foo"));
|
||||||
|
@ -60,79 +56,55 @@ public class YamlProcessorTests {
|
||||||
assertEquals("2", properties.getProperty("bar[1]"));
|
assertEquals("2", properties.getProperty("bar[1]"));
|
||||||
assertEquals(3, properties.get("bar[2]"));
|
assertEquals(3, properties.get("bar[2]"));
|
||||||
assertEquals("3", properties.getProperty("bar[2]"));
|
assertEquals("3", properties.getProperty("bar[2]"));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStringResource() throws Exception {
|
public void testStringResource() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> assertEquals("foo", map.get("document")));
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("foo", map.get("document"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadDocumentStart() throws Exception {
|
public void testBadDocumentStart() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
||||||
this.exception.expect(ParserException.class);
|
this.exception.expect(ParserException.class);
|
||||||
this.exception.expectMessage("line 2, column 1");
|
this.exception.expectMessage("line 2, column 1");
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {});
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadResource() throws Exception {
|
public void testBadResource() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||||
this.exception.expect(ScannerException.class);
|
this.exception.expect(ScannerException.class);
|
||||||
this.exception.expectMessage("line 3, column 1");
|
this.exception.expectMessage("line 3, column 1");
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {});
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mapConvertedToIndexedBeanReference() {
|
public void mapConvertedToIndexedBeanReference() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
// System.err.println(properties);
|
|
||||||
assertEquals("bucket", properties.get("bar.spam"));
|
assertEquals("bucket", properties.get("bar.spam"));
|
||||||
assertEquals(2, properties.size());
|
assertEquals(2, properties.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void integerKeyBehaves() {
|
public void integerKeyBehaves() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("bar", properties.get("[1]"));
|
assertEquals("bar", properties.get("[1]"));
|
||||||
assertEquals(2, properties.size());
|
assertEquals(2, properties.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void integerDeepKeyBehaves() {
|
public void integerDeepKeyBehaves() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("bar", properties.get("foo[1]"));
|
assertEquals("bar", properties.get("foo[1]"));
|
||||||
assertEquals(1, properties.size());
|
assertEquals(1, properties.size());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +112,7 @@ public class YamlProcessorTests {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||||
this.processor.process(new MatchCallback() {
|
this.processor.process((properties, map) -> {
|
||||||
@Override
|
|
||||||
public void process(Properties properties, Map<String, Object> map) {
|
|
||||||
assertEquals("bucket", properties.get("bar.spam"));
|
assertEquals("bucket", properties.get("bar.spam"));
|
||||||
assertEquals(2, properties.size());
|
assertEquals(2, properties.size());
|
||||||
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
|
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
|
||||||
|
@ -151,7 +121,6 @@ public class YamlProcessorTests {
|
||||||
assertTrue(flattenedMap instanceof LinkedHashMap);
|
assertTrue(flattenedMap instanceof LinkedHashMap);
|
||||||
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
|
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
|
||||||
assertEquals("bucket", bar.get("spam"));
|
assertEquals("bucket", bar.get("spam"));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,11 @@ package org.springframework.beans.factory.config;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.DuplicateKeyException;
|
||||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||||
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
@ -46,17 +46,16 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResource() throws Exception {
|
public void testLoadResource() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()));
|
||||||
"foo: bar\nspam:\n foo: baz".getBytes()));
|
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadResource() throws Exception {
|
public void testBadResource() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||||
|
@ -66,7 +65,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourcesWithOverride() throws Exception {
|
public void testLoadResourcesWithOverride() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(
|
factory.setResources(
|
||||||
new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()),
|
new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()),
|
||||||
|
@ -77,27 +76,24 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = DuplicateKeyException.class)
|
||||||
public void testLoadResourcesWithInternalOverride() throws Exception {
|
public void testLoadResourcesWithInternalOverride() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo: bar\nspam:\n foo: baz\nfoo: bucket".getBytes()));
|
"foo: bar\nspam:\n foo: baz\nfoo: bucket".getBytes()));
|
||||||
Properties properties = factory.getObject();
|
factory.getObject();
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bucket"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = DuplicateKeyException.class)
|
||||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
public void testLoadResourcesWithNestedInternalOverride() {
|
||||||
public void testLoadResourcesWithNestedInternalOverride() throws Exception {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo:\n bar: spam\n foo: baz\nbreak: it\nfoo: bucket".getBytes()));
|
"foo:\n bar: spam\n foo: baz\nbreak: it\nfoo: bucket".getBytes()));
|
||||||
Properties properties = factory.getObject();
|
factory.getObject();
|
||||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourceWithMultipleDocuments() throws Exception {
|
public void testLoadResourceWithMultipleDocuments() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo: bar\nspam: baz\n---\nfoo: bag".getBytes()));
|
"foo: bar\nspam: baz\n---\nfoo: bag".getBytes()));
|
||||||
|
@ -107,37 +103,29 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourceWithSelectedDocuments() throws Exception {
|
public void testLoadResourceWithSelectedDocuments() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
"foo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
factory.setDocumentMatchers((DocumentMatcher) properties -> ("bag".equals(properties.getProperty("foo")) ?
|
||||||
@Override
|
MatchStatus.FOUND : MatchStatus.NOT_FOUND));
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
return ("bag".equals(properties.getProperty("foo")) ?
|
|
||||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourceWithDefaultMatch() throws Exception {
|
public void testLoadResourceWithDefaultMatch() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setMatchDefault(true);
|
factory.setMatchDefault(true);
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
factory.setDocumentMatchers((DocumentMatcher) properties -> {
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
if (!properties.containsKey("foo")) {
|
if (!properties.containsKey("foo")) {
|
||||||
return MatchStatus.ABSTAIN;
|
return MatchStatus.ABSTAIN;
|
||||||
}
|
}
|
||||||
return ("bag".equals(properties.getProperty("foo")) ?
|
return ("bag".equals(properties.getProperty("foo")) ?
|
||||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||||
|
@ -146,7 +134,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourceWithoutDefaultMatch() throws Exception {
|
public void testLoadResourceWithoutDefaultMatch() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setMatchDefault(false);
|
factory.setMatchDefault(false);
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
|
@ -168,20 +156,17 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() throws Exception {
|
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setMatchDefault(true);
|
factory.setMatchDefault(true);
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"one: two\n---\nfoo: bag\nspam: bad\n---\nfoo: bar\nspam: baz".getBytes()));
|
"one: two\n---\nfoo: bag\nspam: bad\n---\nfoo: bar\nspam: baz".getBytes()));
|
||||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
factory.setDocumentMatchers((DocumentMatcher) properties -> {
|
||||||
@Override
|
|
||||||
public MatchStatus matches(Properties properties) {
|
|
||||||
if (!properties.containsKey("foo")) {
|
if (!properties.containsKey("foo")) {
|
||||||
return MatchStatus.ABSTAIN;
|
return MatchStatus.ABSTAIN;
|
||||||
}
|
}
|
||||||
return ("bag".equals(properties.getProperty("foo")) ?
|
return ("bag".equals(properties.getProperty("foo")) ?
|
||||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||||
|
@ -190,7 +175,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadNonExistentResource() throws Exception {
|
public void testLoadNonExistentResource() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResolutionMethod(ResolutionMethod.OVERRIDE_AND_IGNORE);
|
factory.setResolutionMethod(ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||||
factory.setResources(new ClassPathResource("no-such-file.yml"));
|
factory.setResources(new ClassPathResource("no-such-file.yml"));
|
||||||
|
@ -199,7 +184,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadNull() throws Exception {
|
public void testLoadNull() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
|
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
|
@ -217,7 +202,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadArrayOfString() throws Exception {
|
public void testLoadArrayOfString() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
|
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
|
@ -227,7 +212,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadArrayOfInteger() throws Exception {
|
public void testLoadArrayOfInteger() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
|
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
|
@ -237,7 +222,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadArrayOfObject() throws Exception {
|
public void testLoadArrayOfObject() {
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(new ByteArrayResource(
|
factory.setResources(new ByteArrayResource(
|
||||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
|
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
|
||||||
|
@ -255,8 +240,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||||
public void testYaml() {
|
public void testYaml() {
|
||||||
Yaml yaml = new Yaml();
|
Yaml yaml = new Yaml();
|
||||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
||||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
assertThat(map.get("foo"), equalTo("bar"));
|
||||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo((Object) "baz"));
|
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo("baz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue