001/* 002 * Copyright 2002-2016 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.propertyeditors; 018 019import java.beans.PropertyEditorSupport; 020import java.io.IOException; 021import java.net.URI; 022import java.net.URISyntaxException; 023import java.nio.file.FileSystemNotFoundException; 024import java.nio.file.Path; 025import java.nio.file.Paths; 026 027import org.springframework.core.io.Resource; 028import org.springframework.core.io.ResourceEditor; 029import org.springframework.core.io.ResourceLoader; 030import org.springframework.lang.UsesJava7; 031import org.springframework.util.Assert; 032 033/** 034 * Editor for {@code java.nio.file.Path}, to directly populate a Path 035 * property instead of using a String property as bridge. 036 * 037 * <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking 038 * registered NIO file system providers, including the default file system 039 * for "file:..." paths. Also supports Spring-style URL notation: any fully 040 * qualified standard URL and Spring's special "classpath:" pseudo-URL, as 041 * well as Spring's context-specific relative file paths. As a fallback, a 042 * path will be resolved in the file system via {@code Paths#get(String)} 043 * if no existing context-relative resource could be found. 044 * 045 * @author Juergen Hoeller 046 * @since 4.3.2 047 * @see java.nio.file.Path 048 * @see Paths#get(URI) 049 * @see ResourceEditor 050 * @see org.springframework.core.io.ResourceLoader 051 * @see FileEditor 052 * @see URLEditor 053 */ 054@UsesJava7 055public class PathEditor extends PropertyEditorSupport { 056 057 private final ResourceEditor resourceEditor; 058 059 060 /** 061 * Create a new PathEditor, using the default ResourceEditor underneath. 062 */ 063 public PathEditor() { 064 this.resourceEditor = new ResourceEditor(); 065 } 066 067 /** 068 * Create a new PathEditor, using the given ResourceEditor underneath. 069 * @param resourceEditor the ResourceEditor to use 070 */ 071 public PathEditor(ResourceEditor resourceEditor) { 072 Assert.notNull(resourceEditor, "ResourceEditor must not be null"); 073 this.resourceEditor = resourceEditor; 074 } 075 076 077 @Override 078 public void setAsText(String text) throws IllegalArgumentException { 079 boolean nioPathCandidate = !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX); 080 if (nioPathCandidate && !text.startsWith("/")) { 081 try { 082 URI uri = new URI(text); 083 if (uri.getScheme() != null) { 084 nioPathCandidate = false; 085 // Let's try NIO file system providers via Paths.get(URI) 086 setValue(Paths.get(uri).normalize()); 087 return; 088 } 089 } 090 catch (URISyntaxException ex) { 091 // Not a valid URI: Let's try as Spring resource location. 092 } 093 catch (FileSystemNotFoundException ex) { 094 // URI scheme not registered for NIO: 095 // Let's try URL protocol handlers via Spring's resource mechanism. 096 } 097 } 098 099 this.resourceEditor.setAsText(text); 100 Resource resource = (Resource) this.resourceEditor.getValue(); 101 if (resource == null) { 102 setValue(null); 103 } 104 else if (!resource.exists() && nioPathCandidate) { 105 setValue(Paths.get(text).normalize()); 106 } 107 else { 108 try { 109 setValue(resource.getFile().toPath()); 110 } 111 catch (IOException ex) { 112 throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex); 113 } 114 } 115 } 116 117 @Override 118 public String getAsText() { 119 Path value = (Path) getValue(); 120 return (value != null ? value.toString() : ""); 121 } 122 123}