Skip to content

Commit 23c2b6a

Browse files
committed
Added PathEditor for NIO file system resolution
Issue: SPR-14436
1 parent 40b2d26 commit 23c2b6a

File tree

14 files changed

+249
-57
lines changed

14 files changed

+249
-57
lines changed

spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.net.URI;
2626
import java.net.URL;
2727
import java.nio.charset.Charset;
28+
import java.nio.file.Path;
2829
import java.util.Collection;
2930
import java.util.Currency;
3031
import java.util.HashMap;
@@ -59,6 +60,7 @@
5960
import org.springframework.beans.propertyeditors.InputSourceEditor;
6061
import org.springframework.beans.propertyeditors.InputStreamEditor;
6162
import org.springframework.beans.propertyeditors.LocaleEditor;
63+
import org.springframework.beans.propertyeditors.PathEditor;
6264
import org.springframework.beans.propertyeditors.PatternEditor;
6365
import org.springframework.beans.propertyeditors.PropertiesEditor;
6466
import org.springframework.beans.propertyeditors.ReaderEditor;
@@ -211,6 +213,7 @@ private void createDefaultEditors() {
211213
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
212214
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
213215
this.defaultEditors.put(Locale.class, new LocaleEditor());
216+
this.defaultEditors.put(Path.class, new PathEditor());
214217
this.defaultEditors.put(Pattern.class, new PatternEditor());
215218
this.defaultEditors.put(Properties.class, new PropertiesEditor());
216219
this.defaultEditors.put(Reader.class, new ReaderEditor());

spring-beans/src/main/java/org/springframework/beans/propertyeditors/FileEditor.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
5959

6060

6161
/**
62-
* Create a new FileEditor,
63-
* using the default ResourceEditor underneath.
62+
* Create a new FileEditor, using a default ResourceEditor underneath.
6463
*/
6564
public FileEditor() {
6665
this.resourceEditor = new ResourceEditor();
6766
}
6867

6968
/**
70-
* Create a new FileEditor,
71-
* using the given ResourceEditor underneath.
69+
* Create a new FileEditor, using the given ResourceEditor underneath.
7270
* @param resourceEditor the ResourceEditor to use
7371
*/
7472
public FileEditor(ResourceEditor resourceEditor) {
@@ -105,7 +103,7 @@ public void setAsText(String text) throws IllegalArgumentException {
105103
}
106104
catch (IOException ex) {
107105
throw new IllegalArgumentException(
108-
"Could not retrieve File for " + resource + ": " + ex.getMessage());
106+
"Could not retrieve file for " + resource + ": " + ex.getMessage());
109107
}
110108
}
111109
else {

spring-beans/src/main/java/org/springframework/beans/propertyeditors/InputStreamEditor.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
4747

4848

4949
/**
50-
* Create a new InputStreamEditor,
51-
* using the default ResourceEditor underneath.
50+
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
5251
*/
5352
public InputStreamEditor() {
5453
this.resourceEditor = new ResourceEditor();
5554
}
5655

5756
/**
58-
* Create a new InputStreamEditor,
59-
* using the given ResourceEditor underneath.
57+
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
6058
* @param resourceEditor the ResourceEditor to use
6159
*/
6260
public InputStreamEditor(ResourceEditor resourceEditor) {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright 2002-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.beans.propertyeditors;
18+
19+
import java.beans.PropertyEditorSupport;
20+
import java.io.IOException;
21+
import java.net.URI;
22+
import java.net.URISyntaxException;
23+
import java.nio.file.FileSystemNotFoundException;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
27+
import org.springframework.core.io.Resource;
28+
import org.springframework.core.io.ResourceEditor;
29+
import org.springframework.core.io.ResourceLoader;
30+
import org.springframework.util.Assert;
31+
32+
/**
33+
* Editor for {@code java.nio.file.Path}, to directly populate a Path
34+
* property instead of using a String property as bridge.
35+
*
36+
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
37+
* registered NIO file system providers, including the default file system
38+
* for "file:..." paths. Also supports Spring-style URL notation: any fully
39+
* qualified standard URL and Spring's special "classpath:" pseudo-URL,
40+
* as well as Spring's context-specific relative file paths.
41+
*
42+
* <p>Note that, in contrast to {@link FileEditor}, relative paths are only
43+
* supported by Spring's resource abstraction here. Direct {@code Paths.get}
44+
* resolution in a file system always has to go through the corresponding
45+
* file system provider's scheme, i.e. "file" for the default file system.
46+
*
47+
* @author Juergen Hoeller
48+
* @since 4.3.2
49+
* @see java.nio.file.Path
50+
* @see Paths#get(URI)
51+
* @see ResourceEditor
52+
* @see org.springframework.core.io.ResourceLoader
53+
* @see FileEditor
54+
* @see URLEditor
55+
*/
56+
public class PathEditor extends PropertyEditorSupport {
57+
58+
private final ResourceEditor resourceEditor;
59+
60+
61+
/**
62+
* Create a new PathEditor, using the default ResourceEditor underneath.
63+
*/
64+
public PathEditor() {
65+
this.resourceEditor = new ResourceEditor();
66+
}
67+
68+
/**
69+
* Create a new PathEditor, using the given ResourceEditor underneath.
70+
* @param resourceEditor the ResourceEditor to use
71+
*/
72+
public PathEditor(ResourceEditor resourceEditor) {
73+
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
74+
this.resourceEditor = resourceEditor;
75+
}
76+
77+
78+
@Override
79+
public void setAsText(String text) throws IllegalArgumentException {
80+
if (!text.startsWith("/") && !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX)) {
81+
try {
82+
URI uri = new URI(text);
83+
if (uri.getScheme() != null) {
84+
// Let's try NIO file system providers via Paths.get(URI)
85+
setValue(Paths.get(uri).normalize());
86+
return;
87+
}
88+
}
89+
catch (URISyntaxException ex) {
90+
// Not a valid URI: Let's try as Spring resource location.
91+
}
92+
catch (FileSystemNotFoundException ex) {
93+
// URI scheme not registered for NIO:
94+
// Let's try URL protocol handlers via Spring's resource mechanism.
95+
}
96+
}
97+
98+
this.resourceEditor.setAsText(text);
99+
Resource resource = (Resource) this.resourceEditor.getValue();
100+
try {
101+
setValue(resource != null ? resource.getFile().toPath() : null);
102+
}
103+
catch (IOException ex) {
104+
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
105+
}
106+
}
107+
108+
@Override
109+
public String getAsText() {
110+
Path value = (Path) getValue();
111+
return (value != null ? value.toString() : "");
112+
}
113+
114+
}

spring-beans/src/main/java/org/springframework/beans/propertyeditors/ReaderEditor.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
4747

4848

4949
/**
50-
* Create a new ReaderEditor,
51-
* using the default ResourceEditor underneath.
50+
* Create a new ReaderEditor, using the default ResourceEditor underneath.
5251
*/
5352
public ReaderEditor() {
5453
this.resourceEditor = new ResourceEditor();
5554
}
5655

5756
/**
58-
* Create a new ReaderEditor,
59-
* using the given ResourceEditor underneath.
57+
* Create a new ReaderEditor, using the given ResourceEditor underneath.
6058
* @param resourceEditor the ResourceEditor to use
6159
*/
6260
public ReaderEditor(ResourceEditor resourceEditor) {

spring-beans/src/main/java/org/springframework/beans/propertyeditors/URIEditor.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
6060
* standard URIs (not trying to resolve them into physical resources).
6161
*/
6262
public URIEditor() {
63-
this.classLoader = null;
64-
this.encode = true;
63+
this(true);
6564
}
6665

6766
/**
@@ -74,16 +73,14 @@ public URIEditor(boolean encode) {
7473
this.encode = encode;
7574
}
7675

77-
7876
/**
7977
* Create a new URIEditor, using the given ClassLoader to resolve
8078
* "classpath:" locations into physical resource URLs.
8179
* @param classLoader the ClassLoader to use for resolving "classpath:" locations
8280
* (may be {@code null} to indicate the default ClassLoader)
8381
*/
8482
public URIEditor(ClassLoader classLoader) {
85-
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
86-
this.encode = true;
83+
this(classLoader, true);
8784
}
8885

8986
/**

spring-beans/src/main/java/org/springframework/beans/propertyeditors/URLEditor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -50,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
5050

5151

5252
/**
53-
* Create a new URLEditor, using the default ResourceEditor underneath.
53+
* Create a new URLEditor, using a default ResourceEditor underneath.
5454
*/
5555
public URLEditor() {
5656
this.resourceEditor = new ResourceEditor();

spring-beans/src/main/java/org/springframework/beans/support/ResourceEditorRegistrar.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -22,6 +22,7 @@
2222
import java.io.Reader;
2323
import java.net.URI;
2424
import java.net.URL;
25+
import java.nio.file.Path;
2526

2627
import org.xml.sax.InputSource;
2728

@@ -33,6 +34,7 @@
3334
import org.springframework.beans.propertyeditors.FileEditor;
3435
import org.springframework.beans.propertyeditors.InputSourceEditor;
3536
import org.springframework.beans.propertyeditors.InputStreamEditor;
37+
import org.springframework.beans.propertyeditors.PathEditor;
3638
import org.springframework.beans.propertyeditors.ReaderEditor;
3739
import org.springframework.beans.propertyeditors.URIEditor;
3840
import org.springframework.beans.propertyeditors.URLEditor;
@@ -103,6 +105,7 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
103105
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
104106
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
105107
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
108+
doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
106109
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
107110
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
108111

spring-beans/src/test/java/org/springframework/beans/propertyeditors/FileEditorTests.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -29,20 +29,20 @@
2929
* @author Thomas Risberg
3030
* @author Chris Beams
3131
*/
32-
public final class FileEditorTests {
32+
public class FileEditorTests {
3333

3434
@Test
3535
public void testClasspathFileName() throws Exception {
3636
PropertyEditor fileEditor = new FileEditor();
37-
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
38-
+ ClassUtils.getShortName(getClass()) + ".class");
37+
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
38+
ClassUtils.getShortName(getClass()) + ".class");
3939
Object value = fileEditor.getValue();
4040
assertTrue(value instanceof File);
4141
File file = (File) value;
4242
assertTrue(file.exists());
4343
}
4444

45-
@Test(expected=IllegalArgumentException.class)
45+
@Test(expected = IllegalArgumentException.class)
4646
public void testWithNonExistentResource() throws Exception {
4747
PropertyEditor propertyEditor = new FileEditor();
4848
propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
@@ -71,8 +71,8 @@ public void testAbsoluteFileName() throws Exception {
7171
@Test
7272
public void testUnqualifiedFileNameFound() throws Exception {
7373
PropertyEditor fileEditor = new FileEditor();
74-
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
75-
+ ".class";
74+
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
75+
ClassUtils.getShortName(getClass()) + ".class";
7676
fileEditor.setAsText(fileName);
7777
Object value = fileEditor.getValue();
7878
assertTrue(value instanceof File);
@@ -88,8 +88,8 @@ public void testUnqualifiedFileNameFound() throws Exception {
8888
@Test
8989
public void testUnqualifiedFileNameNotFound() throws Exception {
9090
PropertyEditor fileEditor = new FileEditor();
91-
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
92-
+ ".clazz";
91+
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
92+
ClassUtils.getShortName(getClass()) + ".clazz";
9393
fileEditor.setAsText(fileName);
9494
Object value = fileEditor.getValue();
9595
assertTrue(value instanceof File);
@@ -101,4 +101,5 @@ public void testUnqualifiedFileNameNotFound() throws Exception {
101101
}
102102
assertTrue(absolutePath.endsWith(fileName));
103103
}
104+
104105
}

spring-beans/src/test/java/org/springframework/beans/propertyeditors/InputStreamEditorTests.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 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.
@@ -60,9 +60,8 @@ public void testSunnyDay() throws Exception {
6060

6161
@Test(expected = IllegalArgumentException.class)
6262
public void testWhenResourceDoesNotExist() throws Exception {
63-
String resource = "classpath:bingo!";
6463
InputStreamEditor editor = new InputStreamEditor();
65-
editor.setAsText(resource);
64+
editor.setAsText("classpath:bingo!");
6665
}
6766

6867
@Test

0 commit comments

Comments
 (0)