Commit f9da1139 authored by Phillip Webb's avatar Phillip Webb

Exclude FileEditor from binding conversion

Exclude `FileEditor` from the `BindConverter` since it uses slightly
unusual logic to create the file. Specifically, given a value of "."
the editor will locate a `ClassPathResource` then return `getFile()`
from that resource. For back-compatibility, binding should use the
simpler conversion service logic.

Fixes gh-12163
parent 7e10d86e
...@@ -20,6 +20,7 @@ import java.beans.PropertyEditor; ...@@ -20,6 +20,7 @@ import java.beans.PropertyEditor;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
...@@ -27,6 +28,7 @@ import java.util.function.Consumer; ...@@ -27,6 +28,7 @@ import java.util.function.Consumer;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.PropertyEditorRegistry; import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.boot.convert.ApplicationConversionService; import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
...@@ -43,6 +45,13 @@ import org.springframework.util.Assert; ...@@ -43,6 +45,13 @@ import org.springframework.util.Assert;
*/ */
class BindConverter { class BindConverter {
private static final Set<Class<?>> EXCLUDED_EDITORS;
static {
Set<Class<?>> excluded = new HashSet<>();
excluded.add(FileEditor.class); // gh-12163
EXCLUDED_EDITORS = Collections.unmodifiableSet(excluded);
}
private final ConversionService typeConverterConversionService; private final ConversionService typeConverterConversionService;
private final ConversionService conversionService; private final ConversionService conversionService;
...@@ -163,6 +172,9 @@ class BindConverter { ...@@ -163,6 +172,9 @@ class BindConverter {
if (editor == null && String.class != type) { if (editor == null && String.class != type) {
editor = BeanUtils.findEditorByConvention(type); editor = BeanUtils.findEditorByConvention(type);
} }
if (editor == null || EXCLUDED_EDITORS.contains(editor.getClass())) {
return null;
}
return editor; return editor;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.context.properties; package org.springframework.boot.context.properties;
import java.beans.PropertyEditorSupport; import java.beans.PropertyEditorSupport;
import java.io.File;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
...@@ -737,6 +738,13 @@ public class ConfigurationPropertiesTests { ...@@ -737,6 +738,13 @@ public class ConfigurationPropertiesTests {
assertThat(bean.getList()).containsExactly(RuntimeException.class); assertThat(bean.getList()).containsExactly(RuntimeException.class);
} }
@Test
public void loadWhenBindingCurrentDirectoryToFileShouldBind() {
load(FileProperties.class, "test.file=.");
FileProperties bean = this.context.getBean(FileProperties.class);
assertThat(bean.getFile()).isEqualTo(new File("."));
}
private AnnotationConfigApplicationContext load(Class<?> configuration, private AnnotationConfigApplicationContext load(Class<?> configuration,
String... inlinedProperties) { String... inlinedProperties) {
return load(new Class<?>[] { configuration }, inlinedProperties); return load(new Class<?>[] { configuration }, inlinedProperties);
...@@ -1624,6 +1632,22 @@ public class ConfigurationPropertiesTests { ...@@ -1624,6 +1632,22 @@ public class ConfigurationPropertiesTests {
} }
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "test")
static class FileProperties {
private File file;
public File getFile() {
return this.file;
}
public void setFile(File file) {
this.file = file;
}
}
static class CustomPropertiesValidator implements Validator { static class CustomPropertiesValidator implements Validator {
@Override @Override
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.context.properties.bind; package org.springframework.boot.context.properties.bind;
import java.beans.PropertyEditorSupport; import java.beans.PropertyEditorSupport;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
...@@ -195,6 +196,18 @@ public class BindConverterTests { ...@@ -195,6 +196,18 @@ public class BindConverterTests {
bindConverter.convert("test", ResolvableType.forClass(SampleType.class)); bindConverter.convert("test", ResolvableType.forClass(SampleType.class));
} }
@Test
public void convertWhenConvertingToFileShouldExcludeFileEditor() {
// For back compatibility we want true file conversion and not an accidental
// classpath resource reference. See gh-12163
BindConverter bindConverter = new BindConverter(new GenericConversionService(),
null);
assertThat(bindConverter.canConvert(".", ResolvableType.forClass(File.class)))
.isFalse();
this.thrown.expect(ConverterNotFoundException.class);
bindConverter.convert(".", ResolvableType.forClass(File.class));
}
private BindConverter getPropertyEditorOnlyBindConverter( private BindConverter getPropertyEditorOnlyBindConverter(
Consumer<PropertyEditorRegistry> propertyEditorInitializer) { Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
return new BindConverter(new ThrowingConversionService(), return new BindConverter(new ThrowingConversionService(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment