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 e4dec3c88f5b..28d87cad3333 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 @@ -405,8 +405,19 @@ protected Set doFindAllClassPathResources(String path) throws IOExcept * @see #doFindPathMatchingFileResources */ protected Resource convertClassLoaderURL(URL url) { - return (ResourceUtils.URL_PROTOCOL_FILE.equals(url.getProtocol()) ? - new FileSystemResource(url.getPath()) : new UrlResource(url)); + if (ResourceUtils.URL_PROTOCOL_FILE.equals(url.getProtocol())) { + try { + // URI decoding for special characters such as spaces. + return new FileSystemResource(ResourceUtils.toURI(url).getSchemeSpecificPart()); + } + catch (URISyntaxException ex) { + // Fallback for URLs that are not valid URIs (should hardly ever happen). + return new FileSystemResource(url.getFile()); + } + } + else { + return new UrlResource(url); + } } /** @@ -748,8 +759,8 @@ protected Set doFindPathMatchingFileResources(Resource rootDirResource rootDirUri = rootDirResource.getURI(); } catch (Exception ex) { - if (logger.isInfoEnabled()) { - logger.info("Failed to resolve %s as URI: %s".formatted(rootDirResource, ex)); + if (logger.isWarnEnabled()) { + logger.warn("Failed to resolve directory [%s] as URI: %s".formatted(rootDirResource, ex)); } return Collections.emptySet(); } @@ -797,21 +808,11 @@ protected Set doFindPathMatchingFileResources(Resource rootDirResource Set result = new LinkedHashSet<>(); try (Stream files = Files.walk(rootPath)) { - files.filter(isMatchingFile).sorted().forEach(file -> { - try { - result.add(new FileSystemResource(file)); - } - catch (Exception ex) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to convert file %s to an org.springframework.core.io.Resource: %s" - .formatted(file, ex)); - } - } - }); + files.filter(isMatchingFile).sorted().forEach(file -> result.add(new FileSystemResource(file))); } catch (Exception ex) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to complete search in directory [%s] for files matching pattern [%s]: %s" + if (logger.isWarnEnabled()) { + logger.warn("Failed to search in directory [%s] for files matching pattern [%s]: %s" .formatted(rootPath.toAbsolutePath(), subPattern, ex)); } } diff --git a/spring-core/src/main/java/org/springframework/util/ResourceUtils.java b/spring-core/src/main/java/org/springframework/util/ResourceUtils.java index 110c9342105f..af5b6746b960 100644 --- a/spring-core/src/main/java/org/springframework/util/ResourceUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ResourceUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -219,6 +219,7 @@ public static File getFile(URL resourceUrl, String description) throws FileNotFo "because it does not reside in the file system: " + resourceUrl); } try { + // URI decoding for special characters such as spaces. return new File(toURI(resourceUrl).getSchemeSpecificPart()); } catch (URISyntaxException ex) {