From 3c7d3f9482a11fbc7613101afbae109c4b4fefc9 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 2 Oct 2019 21:39:07 -0700 Subject: [PATCH] Add String to File conversion support Add `String` -> `File` support to the `ApplicationConversionService` that can support both simple filename as well as file URLs. This allows Spring Boot application to work in a similar way to vanilla Spring applications where Spring's `FileEditor` provides similar support. Closes gh-16931 --- .../convert/ApplicationConversionService.java | 1 + .../boot/convert/StringToFileConverter.java | 63 +++++++++++++++++++ .../convert/StringToFileConverterTests.java | 60 ++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/StringToFileConverter.java create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/convert/StringToFileConverterTests.java diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java index bce598e43b..948314c661 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java @@ -115,6 +115,7 @@ public class ApplicationConversionService extends FormattingConversionService { registry.addConverter(new DurationToNumberConverter()); registry.addConverter(new StringToDataSizeConverter()); registry.addConverter(new NumberToDataSizeConverter()); + registry.addConverter(new StringToFileConverter()); registry.addConverterFactory(new LenientStringToEnumConverterFactory()); registry.addConverterFactory(new LenientBooleanToEnumConverterFactory()); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/StringToFileConverter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/StringToFileConverter.java new file mode 100644 index 0000000000..60b6f1b627 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/StringToFileConverter.java @@ -0,0 +1,63 @@ +/* + * Copyright 2012-2019 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 + * + * https://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.boot.convert; + +import java.io.File; +import java.io.IOException; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.ResourceUtils; + +/** + * {@link Converter} to convert from a {@link String} to a {@link File}. Supports basic + * file conversion as well as file URLs. + * + * @author Phillip Webb + */ +class StringToFileConverter implements Converter { + + private static final ResourceLoader resourceLoader = new DefaultResourceLoader(); + + @Override + public File convert(String source) { + if (ResourceUtils.isUrl(source)) { + return getFile(resourceLoader.getResource(source)); + } + File file = new File(source); + if (file.isAbsolute()) { + return file; + } + Resource resource = resourceLoader.getResource(source); + if (resource.exists()) { + return getFile(resource); + } + return file; + } + + private File getFile(Resource resource) { + try { + return resource.getFile(); + } + catch (IOException ex) { + throw new IllegalStateException("Could not retrieve file for " + resource + ": " + ex.getMessage()); + } + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/convert/StringToFileConverterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/convert/StringToFileConverterTests.java new file mode 100644 index 0000000000..a10dbbfedc --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/convert/StringToFileConverterTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2019 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 + * + * https://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.boot.convert; + +import java.io.File; +import java.util.stream.Stream; + +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.provider.Arguments; + +import org.springframework.core.convert.ConversionService; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link StringToFileConverter}. + * + * @author Phillip Webb + */ +class StringToFileConverterTests { + + @TempDir + File temp; + + @ConversionServiceTest + void convertWhenSimpleFileReturnsFile(ConversionService conversionService) { + assertThat(convert(conversionService, this.temp.getAbsolutePath() + "/test")) + .isEqualTo(new File(this.temp, "test").getAbsoluteFile()); + } + + @ConversionServiceTest + void convertWhenFilePrefixedReturnsFile(ConversionService conversionService) { + assertThat(convert(conversionService, "file:" + this.temp.getAbsolutePath() + "/test").getAbsoluteFile()) + .isEqualTo(new File(this.temp, "test").getAbsoluteFile()); + } + + private File convert(ConversionService conversionService, String source) { + return conversionService.convert(source, File.class); + } + + static Stream conversionServices() { + return ConversionServiceArguments + .with((conversionService) -> conversionService.addConverter(new StringToFileConverter())); + } + +}