diff --git a/spring-core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java b/spring-core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java index 0bc2a661235..f54fc1f5261 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/ResourceArrayPropertyEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -33,6 +33,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Editor for {@link org.springframework.core.io.Resource} arrays, to @@ -50,6 +51,8 @@ import org.springframework.util.Assert; * * @author Juergen Hoeller * @author Chris Beams + * @author Yanming Zhou + * @author Stephane Nicoll * @since 1.1.2 * @see org.springframework.core.io.Resource * @see ResourcePatternResolver @@ -108,17 +111,30 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport { /** - * Treat the given text as a location pattern and convert it to a Resource array. + * Treat the given text as a location pattern or comma delimited location patterns + * and convert it to a Resource array. */ @Override public void setAsText(String text) { String pattern = resolvePath(text).trim(); + String[] locationPatterns = StringUtils.commaDelimitedListToStringArray(pattern); + if (locationPatterns.length == 1) { + setValue(getResources(locationPatterns[0])); + } + else { + Resource[] resources = Arrays.stream(locationPatterns).map(String::trim) + .map(this::getResources).flatMap(Arrays::stream).toArray(Resource[]::new); + setValue(resources); + } + } + + private Resource[] getResources(String locationPattern) { try { - setValue(this.resourcePatternResolver.getResources(pattern)); + return this.resourcePatternResolver.getResources(locationPattern); } catch (IOException ex) { throw new IllegalArgumentException( - "Could not resolve resource location pattern [" + pattern + "]: " + ex.getMessage()); + "Could not resolve resource location pattern [" + locationPattern + "]: " + ex.getMessage()); } } diff --git a/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java b/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java index 4bb19cdc33d..b17f1a4637f 100644 --- a/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/support/ResourceArrayPropertyEditorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 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. @@ -21,14 +21,20 @@ import java.beans.PropertyEditor; import org.junit.jupiter.api.Test; import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileUrlResource; import org.springframework.core.io.Resource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** + * Tests for {@link ResourceArrayPropertyEditor}. + * * @author Dave Syer * @author Juergen Hoeller + * @author Yanming Zhou + * @author Stephane Nicoll */ class ResourceArrayPropertyEditorTests { @@ -83,4 +89,31 @@ class ResourceArrayPropertyEditorTests { } } + @Test + void commaDelimitedResourcesWithSingleResource() { + PropertyEditor editor = new ResourceArrayPropertyEditor(); + editor.setAsText("classpath:org/springframework/core/io/support/ResourceArrayPropertyEditor.class,file:/test.txt"); + Resource[] resources = (Resource[]) editor.getValue(); + assertThat(resources).isNotNull(); + assertThat(resources[0]).isInstanceOfSatisfying(ClassPathResource.class, + resource -> assertThat(resource.exists()).isTrue()); + assertThat(resources[1]).isInstanceOfSatisfying(FileUrlResource.class, + resource -> assertThat(resource.getFilename()).isEqualTo("test.txt")); + } + + @Test + void commaDelimitedResourcesWithMultipleResources() { + PropertyEditor editor = new ResourceArrayPropertyEditor(); + editor.setAsText("file:/test.txt, classpath:org/springframework/core/io/support/test-resources/*.txt"); + Resource[] resources = (Resource[]) editor.getValue(); + assertThat(resources).isNotNull(); + assertThat(resources[0]).isInstanceOfSatisfying(FileUrlResource.class, + resource -> assertThat(resource.getFilename()).isEqualTo("test.txt")); + assertThat(resources).anySatisfy(candidate -> + assertThat(candidate.getFilename()).isEqualTo("resource1.txt")); + assertThat(resources).anySatisfy(candidate -> + assertThat(candidate.getFilename()).isEqualTo("resource2.txt")); + assertThat(resources).hasSize(3); + } + } diff --git a/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource1.txt b/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource1.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource2.txt b/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource2.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource3.text b/spring-core/src/test/resources/org/springframework/core/io/support/test-resources/resource3.text new file mode 100644 index 00000000000..e69de29bb2d