From fdafd38d2fcdf302c90e9af89a5103534493f218 Mon Sep 17 00:00:00 2001
From: Juergen Hoeller <hoellerj@vmware.com>
Date: Thu, 25 Feb 2021 19:08:18 +0100
Subject: [PATCH] Fix handling of file: paths to non-existent files

For setAsText, if the text argument is a file: URL for a path that does not exist, Paths.get(text) is called where text is a file: URL, which doesn't work - the result is an InvalidPathException.

To fix this issue, also check that the resource isn't a file before calling Paths.get(). That way, resources that are files skip to the other branch.

Closes gh-26575
---
 .../beans/propertyeditors/PathEditor.java     |  5 ++-
 .../propertyeditors/PathEditorTests.java      | 38 +++++++++++++++----
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/spring-beans/src/main/java/org/springframework/beans/propertyeditors/PathEditor.java b/spring-beans/src/main/java/org/springframework/beans/propertyeditors/PathEditor.java
index f1edae00c793..39754c169702 100644
--- a/spring-beans/src/main/java/org/springframework/beans/propertyeditors/PathEditor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/propertyeditors/PathEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -97,7 +97,8 @@ public void setAsText(String text) throws IllegalArgumentException {
 		if (resource == null) {
 			setValue(null);
 		}
-		else if (!resource.exists() && nioPathCandidate) {
+		else if (!resource.isFile() && !resource.exists() && nioPathCandidate) {
+			// Prefer getFile().toPath() below for non-existent file handles
 			setValue(Paths.get(text).normalize());
 		}
 		else {
diff --git a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/PathEditorTests.java b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/PathEditorTests.java
index 40354fc44643..30cec400bd3c 100644
--- a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/PathEditorTests.java
+++ b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/PathEditorTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -34,7 +34,7 @@
 public class PathEditorTests {
 
 	@Test
-	public void testClasspathPathName() throws Exception {
+	public void testClasspathPathName() {
 		PropertyEditor pathEditor = new PathEditor();
 		pathEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
 				ClassUtils.getShortName(getClass()) + ".class");
@@ -46,14 +46,14 @@ public void testClasspathPathName() throws Exception {
 	}
 
 	@Test
-	public void testWithNonExistentResource() throws Exception {
+	public void testWithNonExistentResource() {
 		PropertyEditor propertyEditor = new PathEditor();
 		assertThatIllegalArgumentException().isThrownBy(() ->
 				propertyEditor.setAsText("classpath:/no_way_this_file_is_found.doc"));
 	}
 
 	@Test
-	public void testWithNonExistentPath() throws Exception {
+	public void testWithNonExistentPath() {
 		PropertyEditor pathEditor = new PathEditor();
 		pathEditor.setAsText("file:/no_way_this_file_is_found.doc");
 		Object value = pathEditor.getValue();
@@ -65,7 +65,7 @@ public void testWithNonExistentPath() throws Exception {
 	}
 
 	@Test
-	public void testAbsolutePath() throws Exception {
+	public void testAbsolutePath() {
 		PropertyEditor pathEditor = new PathEditor();
 		pathEditor.setAsText("/no_way_this_file_is_found.doc");
 		Object value = pathEditor.getValue();
@@ -77,7 +77,31 @@ public void testAbsolutePath() throws Exception {
 	}
 
 	@Test
-	public void testUnqualifiedPathNameFound() throws Exception {
+	public void testWindowsAbsolutePath() {
+		PropertyEditor pathEditor = new PathEditor();
+		pathEditor.setAsText("C:\\no_way_this_file_is_found.doc");
+		Object value = pathEditor.getValue();
+		boolean condition1 = value instanceof Path;
+		assertThat(condition1).isTrue();
+		Path path = (Path) value;
+		boolean condition = !path.toFile().exists();
+		assertThat(condition).isTrue();
+	}
+
+	@Test
+	public void testWindowsAbsoluteFilePath() {
+		PropertyEditor pathEditor = new PathEditor();
+		pathEditor.setAsText("file://C:\\no_way_this_file_is_found.doc");
+		Object value = pathEditor.getValue();
+		boolean condition1 = value instanceof Path;
+		assertThat(condition1).isTrue();
+		Path path = (Path) value;
+		boolean condition = !path.toFile().exists();
+		assertThat(condition).isTrue();
+	}
+
+	@Test
+	public void testUnqualifiedPathNameFound() {
 		PropertyEditor pathEditor = new PathEditor();
 		String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
 				ClassUtils.getShortName(getClass()) + ".class";
@@ -96,7 +120,7 @@ public void testUnqualifiedPathNameFound() throws Exception {
 	}
 
 	@Test
-	public void testUnqualifiedPathNameNotFound() throws Exception {
+	public void testUnqualifiedPathNameNotFound() {
 		PropertyEditor pathEditor = new PathEditor();
 		String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
 				ClassUtils.getShortName(getClass()) + ".clazz";