Added PathEditor for NIO file system resolution

Issue: SPR-14436
(cherry picked from commit 23c2b6a)
This commit is contained in:
Juergen Hoeller
2016-07-08 14:58:38 +02:00
parent a1b58ee601
commit f85d48dd31
14 changed files with 278 additions and 58 deletions

View File

@@ -59,6 +59,7 @@ import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.LocaleEditor;
import org.springframework.beans.propertyeditors.PathEditor;
import org.springframework.beans.propertyeditors.PatternEditor;
import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
@@ -87,11 +88,21 @@ import org.springframework.util.ClassUtils;
*/
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
private static Class<?> pathClass;
private static Class<?> zoneIdClass;
static {
ClassLoader cl = PropertyEditorRegistrySupport.class.getClassLoader();
try {
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
pathClass = ClassUtils.forName("java.nio.file.Path", cl);
}
catch (ClassNotFoundException ex) {
// Java 7 Path class not available
pathClass = null;
}
try {
zoneIdClass = ClassUtils.forName("java.time.ZoneId", cl);
}
catch (ClassNotFoundException ex) {
// Java 8 ZoneId class not available
@@ -211,6 +222,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
this.defaultEditors.put(Locale.class, new LocaleEditor());
if (pathClass != null) {
this.defaultEditors.put(pathClass, new PathEditor());
}
this.defaultEditors.put(Pattern.class, new PatternEditor());
this.defaultEditors.put(Properties.class, new PropertiesEditor());
this.defaultEditors.put(Reader.class, new ReaderEditor());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
/**
* Create a new FileEditor,
* using the default ResourceEditor underneath.
* Create a new FileEditor, using a default ResourceEditor underneath.
*/
public FileEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new FileEditor,
* using the given ResourceEditor underneath.
* Create a new FileEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public FileEditor(ResourceEditor resourceEditor) {
@@ -105,7 +103,7 @@ public class FileEditor extends PropertyEditorSupport {
}
catch (IOException ex) {
throw new IllegalArgumentException(
"Could not retrieve File for " + resource + ": " + ex.getMessage());
"Could not retrieve file for " + resource + ": " + ex.getMessage());
}
}
else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
/**
* Create a new InputStreamEditor,
* using the default ResourceEditor underneath.
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
*/
public InputStreamEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new InputStreamEditor,
* using the given ResourceEditor underneath.
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public InputStreamEditor(ResourceEditor resourceEditor) {

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2002-2016 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
*
* http://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.beans.propertyeditors;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.UsesJava7;
import org.springframework.util.Assert;
/**
* Editor for {@code java.nio.file.Path}, to directly populate a Path
* property instead of using a String property as bridge.
*
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
* registered NIO file system providers, including the default file system
* for "file:..." paths. Also supports Spring-style URL notation: any fully
* qualified standard URL and Spring's special "classpath:" pseudo-URL,
* as well as Spring's context-specific relative file paths.
*
* <p>Note that, in contrast to {@link FileEditor}, relative paths are only
* supported by Spring's resource abstraction here. Direct {@code Paths.get}
* resolution in a file system always has to go through the corresponding
* file system provider's scheme, i.e. "file" for the default file system.
*
* @author Juergen Hoeller
* @since 4.3.2
* @see java.nio.file.Path
* @see Paths#get(URI)
* @see ResourceEditor
* @see org.springframework.core.io.ResourceLoader
* @see FileEditor
* @see URLEditor
*/
@UsesJava7
public class PathEditor extends PropertyEditorSupport {
private final ResourceEditor resourceEditor;
/**
* Create a new PathEditor, using the default ResourceEditor underneath.
*/
public PathEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new PathEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public PathEditor(ResourceEditor resourceEditor) {
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
this.resourceEditor = resourceEditor;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (!text.startsWith("/") && !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX)) {
try {
URI uri = new URI(text);
if (uri.getScheme() != null) {
// Let's try NIO file system providers via Paths.get(URI)
setValue(Paths.get(uri).normalize());
return;
}
}
catch (URISyntaxException ex) {
// Not a valid URI: Let's try as Spring resource location.
}
catch (FileSystemNotFoundException ex) {
// URI scheme not registered for NIO:
// Let's try URL protocol handlers via Spring's resource mechanism.
}
}
this.resourceEditor.setAsText(text);
Resource resource = (Resource) this.resourceEditor.getValue();
try {
setValue(resource != null ? resource.getFile().toPath() : null);
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
}
}
@Override
public String getAsText() {
Path value = (Path) getValue();
return (value != null ? value.toString() : "");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
/**
* Create a new ReaderEditor,
* using the default ResourceEditor underneath.
* Create a new ReaderEditor, using the default ResourceEditor underneath.
*/
public ReaderEditor() {
this.resourceEditor = new ResourceEditor();
}
/**
* Create a new ReaderEditor,
* using the given ResourceEditor underneath.
* Create a new ReaderEditor, using the given ResourceEditor underneath.
* @param resourceEditor the ResourceEditor to use
*/
public ReaderEditor(ResourceEditor resourceEditor) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
* standard URIs (not trying to resolve them into physical resources).
*/
public URIEditor() {
this.classLoader = null;
this.encode = true;
this(true);
}
/**
@@ -74,7 +73,6 @@ public class URIEditor extends PropertyEditorSupport {
this.encode = encode;
}
/**
* Create a new URIEditor, using the given ClassLoader to resolve
* "classpath:" locations into physical resource URLs.
@@ -82,8 +80,7 @@ public class URIEditor extends PropertyEditorSupport {
* (may be {@code null} to indicate the default ClassLoader)
*/
public URIEditor(ClassLoader classLoader) {
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
this.encode = true;
this(classLoader, true);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -50,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
/**
* Create a new URLEditor, using the default ResourceEditor underneath.
* Create a new URLEditor, using a default ResourceEditor underneath.
*/
public URLEditor() {
this.resourceEditor = new ResourceEditor();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.beans.propertyeditors.ClassEditor;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputSourceEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.PathEditor;
import org.springframework.beans.propertyeditors.ReaderEditor;
import org.springframework.beans.propertyeditors.URIEditor;
import org.springframework.beans.propertyeditors.URLEditor;
@@ -43,6 +44,7 @@ import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ClassUtils;
/**
* PropertyEditorRegistrar implementation that populates a given
@@ -58,6 +60,19 @@ import org.springframework.core.io.support.ResourcePatternResolver;
*/
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
private static Class<?> pathClass;
static {
try {
pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 7 Path class not available
pathClass = null;
}
}
private final PropertyResolver propertyResolver;
private final ResourceLoader resourceLoader;
@@ -103,6 +118,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
if (pathClass != null) {
doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
}
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));