diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java index a7ea8c8d1f..e34d7c25ce 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -52,6 +52,7 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Juergen Hoeller * @author Sam Brannen + * @author Brian Clozel * @since 4.1 */ public abstract class YamlProcessor { @@ -128,10 +129,11 @@ public abstract class YamlProcessor { /** * Set the supported types that can be loaded from YAML documents. - *

If no supported types are configured, all types encountered in YAML - * documents will be supported. If an unsupported type is encountered, an - * {@link IllegalStateException} will be thrown when the corresponding YAML - * node is processed. + *

If no supported types are configured, only Java standard classes + * (as defined in {@link org.yaml.snakeyaml.constructor.SafeConstructor}) + * encountered in YAML documents will be supported. + * If an unsupported type is encountered, an {@link IllegalStateException} + * will be thrown when the corresponding YAML node is processed. * @param supportedTypes the supported types, or an empty array to clear the * supported types * @since 5.1.16 @@ -182,12 +184,8 @@ public abstract class YamlProcessor { protected Yaml createYaml() { LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setAllowDuplicateKeys(false); - - if (!this.supportedTypes.isEmpty()) { - return new Yaml(new FilteringConstructor(loaderOptions), new Representer(), - new DumperOptions(), loaderOptions); - } - return new Yaml(loaderOptions); + return new Yaml(new FilteringConstructor(loaderOptions), new Representer(), + new DumperOptions(), loaderOptions); } private boolean process(MatchCallback callback, Yaml yaml, Resource resource) { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/config/YamlProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/config/YamlProcessorTests.java index 60fbd272ce..50c7f903a4 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/config/YamlProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/config/YamlProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -17,9 +17,11 @@ package org.springframework.beans.factory.config; import java.net.URL; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.junit.jupiter.api.Test; import org.yaml.snakeyaml.constructor.ConstructorException; @@ -28,7 +30,6 @@ import org.yaml.snakeyaml.scanner.ScannerException; import org.springframework.core.io.ByteArrayResource; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.entry; @@ -39,10 +40,12 @@ import static org.assertj.core.api.Assertions.entry; * @author Dave Syer * @author Juergen Hoeller * @author Sam Brannen + * @author Brian Clozel */ class YamlProcessorTests { - private final YamlProcessor processor = new YamlProcessor() {}; + private final YamlProcessor processor = new YamlProcessor() { + }; @Test @@ -79,8 +82,8 @@ class YamlProcessorTests { void badResource() { setYaml("foo: bar\ncd\nspam:\n foo: baz"); assertThatExceptionOfType(ScannerException.class) - .isThrownBy(() -> this.processor.process((properties, map) -> {})) - .withMessageContaining("line 3, column 1"); + .isThrownBy(() -> this.processor.process((properties, map) -> {})) + .withMessageContaining("line 3, column 1"); } @Test @@ -127,8 +130,8 @@ class YamlProcessorTests { Map bar = (Map) map.get("bar"); assertThat(bar.get("spam")).isEqualTo("bucket"); - List keysFromProperties = properties.keySet().stream().collect(toList()); - List keysFromFlattenedMap = flattenedMap.keySet().stream().collect(toList()); + List keysFromProperties = new ArrayList<>(properties.keySet()); + List keysFromFlattenedMap = new ArrayList<>(flattenedMap.keySet()); assertThat(keysFromProperties).containsExactlyInAnyOrderElementsOf(keysFromFlattenedMap); // Keys in the Properties object are sorted. assertThat(keysFromProperties).containsExactly("bar.spam", "cat", "foo"); @@ -138,14 +141,23 @@ class YamlProcessorTests { } @Test - void customTypeSupportedByDefault() throws Exception { + void standardTypesSupportedByDefault() throws Exception { + setYaml("value: !!set\n ? first\n ? second"); + this.processor.process((properties, map) -> { + assertThat(properties).containsExactly(entry("value[0]", "first"), entry("value[1]", "second")); + assertThat(map.get("value")).isInstanceOf(Set.class); + Set set = (Set) map.get("value"); + assertThat(set).containsExactly("first", "second"); + }); + } + + @Test + void customTypeNotSupportedByDefault() throws Exception { URL url = new URL("https://localhost:9000/"); setYaml("value: !!java.net.URL [\"" + url + "\"]"); - - this.processor.process((properties, map) -> { - assertThat(properties).containsExactly(entry("value", url)); - assertThat(map).containsExactly(entry("value", url)); - }); + assertThatExceptionOfType(ConstructorException.class) + .isThrownBy(() -> this.processor.process((properties, map) -> {})) + .withMessageContaining("Unsupported type encountered in YAML document: java.net.URL"); } @Test @@ -168,8 +180,8 @@ class YamlProcessorTests { setYaml("value: !!java.net.URL [\"https://localhost:9000/\"]"); assertThatExceptionOfType(ConstructorException.class) - .isThrownBy(() -> this.processor.process((properties, map) -> {})) - .withMessageContaining("Unsupported type encountered in YAML document: java.net.URL"); + .isThrownBy(() -> this.processor.process((properties, map) -> {})) + .withMessageContaining("Unsupported type encountered in YAML document: java.net.URL"); } private void setYaml(String yaml) {