From ccff52645459be77919d2703e35e322d4b6abc0b Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 26 Sep 2022 19:49:40 +0200 Subject: [PATCH] Reintroduce logging and exception handling for file system resource scanning See gh-29163 --- .../PathMatchingResourcePatternResolver.java | 105 ++++++++++++------ 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java index 603311f447e5..c474db8ed42a 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java @@ -34,11 +34,9 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.Collections; import java.util.Enumeration; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; @@ -738,49 +736,88 @@ protected JarFile getJarFile(String jarFileUrl) throws IOException { protected Set doFindPathMatchingFileResources(Resource rootDirResource, String subPattern) throws IOException { - URI rootDirUri = rootDirResource.getURI(); - String rootDir = rootDirUri.getPath(); - // If the URI is for a "resource" in the GraalVM native image file system, we have to - // ensure that the root directory does not end in a slash while simultaneously ensuring - // that the root directory is not an empty string (since fileSystem.getPath("").resolve(str) - // throws an ArrayIndexOutOfBoundsException in a native image). - if ("resource".equals(rootDirUri.getScheme()) && (rootDir.length() > 1) && rootDir.endsWith("/")) { - rootDir = rootDir.substring(0, rootDir.length() - 1); - } - - FileSystem fileSystem; + URI rootDirUri; + String rootDir; try { - fileSystem = FileSystems.getFileSystem(rootDirUri.resolve("/")); + rootDirUri = rootDirResource.getURI(); + rootDir = rootDirUri.getPath(); + // If the URI is for a "resource" in the GraalVM native image file system, we have to + // ensure that the root directory does not end in a slash while simultaneously ensuring + // that the root directory is not an empty string (since fileSystem.getPath("").resolve(str) + // throws an ArrayIndexOutOfBoundsException in a native image). + if ("resource".equals(rootDirUri.getScheme()) && (rootDir.length() > 1) && rootDir.endsWith("/")) { + rootDir = rootDir.substring(0, rootDir.length() - 1); + } } catch (Exception ex) { - fileSystem = FileSystems.newFileSystem(rootDirUri.resolve("/"), Map.of(), - ClassUtils.getDefaultClassLoader()); + if (logger.isInfoEnabled()) { + logger.info("Failed to resolve %s in the file system: %s".formatted(rootDirResource, ex)); + } + return Collections.emptySet(); } - Path rootPath = fileSystem.getPath(rootDir); - String resourcePattern = rootPath.resolve(subPattern).toString(); - Predicate resourcePatternMatches = path -> getPathMatcher().match(resourcePattern, path.toString()); - Set result = new HashSet<>(); - try (Stream files = Files.walk(rootPath)) { - files.filter(resourcePatternMatches).sorted().forEach(file -> { - try { - result.add(convertToResource(file.toUri())); - } - catch (Exception ex) { - // TODO Introduce logging + FileSystem fileSystem = getFileSystem(rootDirUri); + if (fileSystem == null) { + return Collections.emptySet(); + } + + try { + Path rootPath = fileSystem.getPath(rootDir); + String resourcePattern = rootPath.resolve(subPattern).toString(); + Predicate resourcePatternMatches = path -> getPathMatcher().match(resourcePattern, path.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Searching directory [%s] for files matching pattern [%s]" + .formatted(rootPath.toAbsolutePath(), subPattern)); + } + Set result = new LinkedHashSet<>(); + try (Stream files = Files.walk(rootPath)) { + files.filter(resourcePatternMatches).sorted().forEach(file -> { + try { + result.add(convertToResource(file.toUri())); + } + catch (Exception ex) { + if (logger.isDebugEnabled()) { + logger.debug("Failed to convert file %s to an org.springframework.core.io.Resource: %s" + .formatted(file, ex)); + } + } + }); + } + catch (Exception ex) { + if (logger.isDebugEnabled()) { + logger.debug("Faild to complete search in directory [%s] for files matching pattern [%s]: %s" + .formatted(rootPath.toAbsolutePath(), subPattern, ex)); } - }); + } + return result; } - catch (NoSuchFileException ex) { - // TODO Introduce logging + finally { + try { + fileSystem.close(); + } + catch (UnsupportedOperationException ex) { + // ignore + } } + } + + @Nullable + private FileSystem getFileSystem(URI uri) { try { - fileSystem.close(); + URI root = uri.resolve("/"); + try { + return FileSystems.getFileSystem(root); + } + catch (Exception ex) { + return FileSystems.newFileSystem(root, Map.of(), ClassUtils.getDefaultClassLoader()); + } } - catch (UnsupportedOperationException ex) { - // TODO Introduce logging + catch (Exception ex) { + if (logger.isInfoEnabled()) { + logger.info("Failed to resolve java.nio.file.FileSystem for %s: %s".formatted(uri, ex)); + } + return null; } - return result; } /**