mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Handle fully-qualified Windows paths correctly in the CLI
Previously, the CLI would always use the class loader to try to locate a source file. This was contrary to the SourceOptions javadoc which states that the class loader is “used to try and load files that are not found in the local filesystem”. This provide to be problematic on Windows when a fully-qualified source file was supplied. The driver letter colon slash (e.g. c:/) at the start of the path is considered invalid for a class path resource by URLClassPath.Loader resulting in an IllegalArgumentException being thrown. A workaround for this URLClassPath behaviour was added ina71c9b5d
. It was removed as part of reworking LaunchedURLClassLoader to use a conventional delegation model in87fe0b2a
. It was then reinstated incc140b2c
. This work around is undesirable as it causes LaunchedURLClassLoader’s behaviour to diverge from URLClassLoader’s behaviour (this is contrary to the comments in the test added ina71c9b5d
which incorrectly tests the two class loader with different class paths. If the two class loaders are created with the same class path then their behaviour is the same). This commit updates SourceOptions to make its behaviour match its javadoc so that a search of the class path is only performed if the filename doesn’t exist on the filesystem. Furthermore, when running on Windows, if the filename is an absolute path no further searching is performed as the path cannot reliably be used to search the class path due to the behaviour of URLClassPath.Loader when given a path that is an absolute file path on Windows. This ensures that the user is presented with an error message indicating that the file could not be found. Closes gh-5650
This commit is contained in:
parent
c38bb9657d
commit
0c78b2fd3d
@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.cli.command.options;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -78,13 +79,20 @@ public class SourceOptions {
|
||||
if ("--".equals(filename)) {
|
||||
break;
|
||||
}
|
||||
List<String> urls = ResourceUtils.getUrls(filename, classLoader);
|
||||
List<String> urls = new ArrayList<String>();
|
||||
File fileCandidate = new File(filename);
|
||||
if (fileCandidate.isFile()) {
|
||||
urls.add(fileCandidate.getAbsoluteFile().toURI().toString());
|
||||
}
|
||||
else if (!isAbsoluteWindowsFile(fileCandidate)) {
|
||||
urls.addAll(ResourceUtils.getUrls(filename, classLoader));
|
||||
}
|
||||
for (String url : urls) {
|
||||
if (url.endsWith(".groovy") || url.endsWith(".java")) {
|
||||
if (isSource(url)) {
|
||||
sources.add(url);
|
||||
}
|
||||
}
|
||||
if ((filename.endsWith(".groovy") || filename.endsWith(".java"))) {
|
||||
if (isSource(filename)) {
|
||||
if (urls.isEmpty()) {
|
||||
throw new IllegalArgumentException("Can't find " + filename);
|
||||
}
|
||||
@ -100,6 +108,18 @@ public class SourceOptions {
|
||||
this.sources = Collections.unmodifiableList(sources);
|
||||
}
|
||||
|
||||
private boolean isAbsoluteWindowsFile(File file) {
|
||||
return isWindows() && file.isAbsolute();
|
||||
}
|
||||
|
||||
private boolean isWindows() {
|
||||
return File.separatorChar == '\\';
|
||||
}
|
||||
|
||||
private boolean isSource(String name) {
|
||||
return name.endsWith(".java") || name.endsWith(".groovy");
|
||||
}
|
||||
|
||||
public List<?> getArgs() {
|
||||
return this.args;
|
||||
}
|
||||
|
@ -50,12 +50,7 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
||||
public URL findResource(String name) {
|
||||
Handler.setUseFastConnectionExceptions(true);
|
||||
try {
|
||||
try {
|
||||
return super.findResource(name);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
return super.findResource(name);
|
||||
}
|
||||
finally {
|
||||
Handler.setUseFastConnectionExceptions(false);
|
||||
|
Loading…
Reference in New Issue
Block a user