Skip to content

Commit 64158eb

Browse files
committed
Reinstate use of ConversionService for String -> File conversion
Prior to 3db5c70, RelaxedDataBinder would use a ConversionService to convert a String into a File via its ObjectToObjectConverter. 3db5c70 changed the configuration of the data binder such that a FileEditor was registered. Property editors take precedence over any conversion service so the FileEditor was used instead. This caused a regression as the FileEditor uses slightly unusual logic for a String to File conversion. Specifically, when given a value of ".", it will locate a ClassPathResource for the root of the classpath and use the result of calling getFile() on that resource. This fails when the root of the classpath is in a jar file and also provides a different result when the root of the classpath is not the current directory. This commit updates RelaxedDataBinder to suppress the registration of an editor for File. This restores the behaviour prior to 3db5c70 by allowing the ConversionService to be used instead. Closes gh-12786
1 parent 700faab commit 64158eb

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.bind;
1818

19+
import java.beans.PropertyEditor;
1920
import java.net.InetAddress;
2021
import java.util.ArrayList;
2122
import java.util.Collection;
@@ -35,6 +36,7 @@
3536
import org.springframework.beans.MutablePropertyValues;
3637
import org.springframework.beans.NotWritablePropertyException;
3738
import org.springframework.beans.PropertyValue;
39+
import org.springframework.beans.propertyeditors.FileEditor;
3840
import org.springframework.core.convert.ConversionService;
3941
import org.springframework.core.convert.TypeDescriptor;
4042
import org.springframework.core.env.StandardEnvironment;
@@ -58,6 +60,13 @@
5860
*/
5961
public class RelaxedDataBinder extends DataBinder {
6062

63+
private static final Set<Class<?>> EXCLUDED_EDITORS;
64+
static {
65+
Set<Class<?>> excluded = new HashSet<Class<?>>();
66+
excluded.add(FileEditor.class);
67+
EXCLUDED_EDITORS = Collections.unmodifiableSet(excluded);
68+
}
69+
6170
private static final Object BLANK = new Object();
6271

6372
private String namePrefix;
@@ -453,6 +462,24 @@ private static Object wrapTarget(Object target) {
453462
return target;
454463
}
455464

465+
@Override
466+
public void registerCustomEditor(Class<?> requiredType,
467+
PropertyEditor propertyEditor) {
468+
if (propertyEditor == null
469+
|| !EXCLUDED_EDITORS.contains(propertyEditor.getClass())) {
470+
super.registerCustomEditor(requiredType, propertyEditor);
471+
}
472+
}
473+
474+
@Override
475+
public void registerCustomEditor(Class<?> requiredType, String field,
476+
PropertyEditor propertyEditor) {
477+
if (propertyEditor == null
478+
|| !EXCLUDED_EDITORS.contains(propertyEditor.getClass())) {
479+
super.registerCustomEditor(requiredType, field, propertyEditor);
480+
}
481+
}
482+
456483
/**
457484
* Holder to allow Map targets to be bound.
458485
*/

spring-boot/src/test/java/org/springframework/boot/bind/PropertiesConfigurationFactoryTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot.bind;
1818

19+
import java.io.File;
1920
import java.io.IOException;
2021
import java.util.Collections;
2122
import java.util.Properties;
@@ -27,7 +28,9 @@
2728

2829
import org.springframework.beans.NotWritablePropertyException;
2930
import org.springframework.boot.context.config.RandomValuePropertySource;
31+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3032
import org.springframework.context.support.StaticMessageSource;
33+
import org.springframework.core.convert.support.DefaultConversionService;
3134
import org.springframework.core.env.MutablePropertySources;
3235
import org.springframework.core.env.PropertiesPropertySource;
3336
import org.springframework.core.env.StandardEnvironment;
@@ -209,6 +212,22 @@ public void propertyWithAllUpperCaseInTheMiddleCanBeBound() throws Exception {
209212
assertThat(foo.fooDLQBar).isEqualTo(("baz"));
210213
}
211214

215+
@Test
216+
public void currentDirectoryCanBeBoundToFileProperty() throws Exception {
217+
PropertiesConfigurationFactory<FileProperties> factory = new PropertiesConfigurationFactory<FileProperties>(
218+
FileProperties.class);
219+
factory.setApplicationContext(new AnnotationConfigApplicationContext());
220+
factory.setConversionService(new DefaultConversionService());
221+
Properties properties = PropertiesLoaderUtils
222+
.loadProperties(new ByteArrayResource("someFile: .".getBytes()));
223+
MutablePropertySources propertySources = new MutablePropertySources();
224+
propertySources.addFirst(new PropertiesPropertySource("test", properties));
225+
factory.setPropertySources(propertySources);
226+
factory.afterPropertiesSet();
227+
FileProperties fileProperties = factory.getObject();
228+
assertThat(fileProperties.getSomeFile()).isEqualTo(new File("."));
229+
}
230+
212231
private Foo createFoo(final String values) throws Exception {
213232
setupFactory();
214233
return bindFoo(values);
@@ -298,4 +317,18 @@ public void setFooDLQBar(String fooDLQBar) {
298317

299318
}
300319

320+
public static class FileProperties {
321+
322+
private File someFile;
323+
324+
public File getSomeFile() {
325+
return this.someFile;
326+
}
327+
328+
public void setSomeFile(File someFile) {
329+
this.someFile = someFile;
330+
}
331+
332+
}
333+
301334
}

0 commit comments

Comments
 (0)