diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java index 7e95a9040..a24694dca 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceFinder.java @@ -14,13 +14,16 @@ package org.dromara.hutool.core.io.resource; import org.dromara.hutool.core.collection.iter.EnumerationIter; import org.dromara.hutool.core.compress.ZipUtil; +import org.dromara.hutool.core.exception.HutoolException; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; +import org.dromara.hutool.core.io.file.FileUtil; import org.dromara.hutool.core.net.url.URLUtil; import org.dromara.hutool.core.text.AntPathMatcher; import org.dromara.hutool.core.text.CharUtil; import org.dromara.hutool.core.text.StrUtil; +import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; @@ -59,14 +62,18 @@ public class ResourceFinder { final MultiResource result = new MultiResource(); // 遍历根目录下所有资源,并过滤保留符合条件的资源 for (final Resource rootResource : ResourceUtil.getResources(rootDirPath, classLoader)) { - if (URLUtil.isJarURL(rootResource.getUrl())) { + if (rootResource instanceof JarResource) { + // 在jar包中 try { - result.addAll(findInJar(rootResource, subPattern)); + result.addAll(findInJar((JarResource) rootResource, subPattern)); } catch (final IOException e) { throw new IORuntimeException(e); } + } else if (rootResource instanceof FileResource) { + // 文件夹中 + result.addAll(findInDir((FileResource) rootResource, subPattern)); } else { - result.addAll(findInDir(rootResource, subPattern)); + throw new HutoolException("Unsupported resource type: {}", rootResource.getClass().getName()); } } @@ -81,12 +88,11 @@ public class ResourceFinder { * @return 符合条件的资源 * @throws IOException IO异常 */ - protected MultiResource findInJar(final Resource rootResource, final String subPattern) throws IOException { + protected MultiResource findInJar(final JarResource rootResource, final String subPattern) throws IOException { final URL rootDirURL = rootResource.getUrl(); final URLConnection conn = rootDirURL.openConnection(); final JarFile jarFile; - final String jarFileUrl; String rootEntryPath; final boolean closeJarFile; @@ -98,7 +104,7 @@ public class ResourceFinder { rootEntryPath = (jarEntry != null ? jarEntry.getName() : StrUtil.EMPTY); closeJarFile = !jarCon.getUseCaches(); } else { - // + // 去除子路径后重新获取jar文件 final String urlFile = rootDirURL.getFile(); try { int separatorIndex = urlFile.indexOf(URLUtil.WAR_URL_SEPARATOR); @@ -106,7 +112,7 @@ public class ResourceFinder { separatorIndex = urlFile.indexOf(URLUtil.JAR_URL_SEPARATOR); } if (separatorIndex != -1) { - jarFileUrl = urlFile.substring(0, separatorIndex); + final String jarFileUrl = urlFile.substring(0, separatorIndex); rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars jarFile = ZipUtil.ofJar(jarFileUrl); } else { @@ -130,7 +136,7 @@ public class ResourceFinder { if (entryPath.startsWith(rootEntryPath)) { final String relativePath = entryPath.substring(rootEntryPath.length()); if (pathMatcher.match(subPattern, relativePath)) { - result.add(new UrlResource(URLUtil.getURL(rootDirURL, relativePath))); + result.add(ResourceUtil.getResource(URLUtil.getURL(rootDirURL, relativePath))); } } } @@ -143,8 +149,23 @@ public class ResourceFinder { return result; } - protected MultiResource findInDir(final Resource rootResource, final String subPattern) { + /** + * 遍历目录查找指定表达式匹配的文件列表 + * + * @param resource 文件资源 + * @param subPattern 子表达式 + * @return 满足条件的文件 + */ + protected MultiResource findInDir(final FileResource resource, final String subPattern) { + final MultiResource result = new MultiResource(); + final File rootDir = resource.getFile(); + FileUtil.walkFiles(rootDir, (file -> { + if (pathMatcher.match(subPattern, file.getName())) { + result.add(new FileResource(file)); + } + })); + return result; } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java index 176a464d2..fd1c56fbb 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/ResourceUtil.java @@ -17,6 +17,7 @@ import org.dromara.hutool.core.collection.iter.IterUtil; import org.dromara.hutool.core.io.file.FileUtil; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.lang.Assert; +import org.dromara.hutool.core.net.url.UrlProtocolUtil; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.core.classloader.ClassLoaderUtil; import org.dromara.hutool.core.text.StrUtil; @@ -253,6 +254,11 @@ public class ResourceUtil { * @since 6.0.0 */ public static Resource getResource(final URL url) { + if(UrlProtocolUtil.isJarURL(url)){ + return new JarResource(url); + } else if(UrlProtocolUtil.isFileURL(url)){ + return new FileResource(url.getFile()); + } return new UrlResource(url); } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java index 490aeffed..0a605eb0c 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/resource/UrlResource.java @@ -15,6 +15,7 @@ package org.dromara.hutool.core.io.resource; import org.dromara.hutool.core.io.file.FileNameUtil; import org.dromara.hutool.core.io.file.FileUtil; import org.dromara.hutool.core.net.url.URLUtil; +import org.dromara.hutool.core.net.url.UrlProtocolUtil; import org.dromara.hutool.core.util.ObjUtil; import java.io.File; @@ -64,7 +65,7 @@ public class UrlResource implements Resource, Serializable { */ public UrlResource(final URL url, final String name) { this.url = url; - if (null != url && URLUtil.URL_PROTOCOL_FILE.equals(url.getProtocol())) { + if (null != url && UrlProtocolUtil.URL_PROTOCOL_FILE.equals(url.getProtocol())) { this.lastModified = FileUtil.file(url).lastModified(); } this.name = ObjUtil.defaultIfNull(name, () -> (null != url ? FileNameUtil.getName(url.getPath()) : null)); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java index 760455ba4..542c01de0 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/URLUtil.java @@ -16,7 +16,6 @@ import org.dromara.hutool.core.classloader.ClassLoaderUtil; import org.dromara.hutool.core.exception.HutoolException; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; -import org.dromara.hutool.core.io.file.FileNameUtil; import org.dromara.hutool.core.io.file.FileUtil; import org.dromara.hutool.core.io.resource.ResourceUtil; import org.dromara.hutool.core.lang.Assert; @@ -64,34 +63,6 @@ public class URLUtil { * URL 前缀表示war: "war:" */ public static final String WAR_URL_PREFIX = "war:"; - /** - * URL 协议表示文件: "file" - */ - public static final String URL_PROTOCOL_FILE = "file"; - /** - * URL 协议表示Jar文件: "jar" - */ - public static final String URL_PROTOCOL_JAR = "jar"; - /** - * URL 协议表示zip文件: "zip" - */ - public static final String URL_PROTOCOL_ZIP = "zip"; - /** - * URL 协议表示WebSphere文件: "wsjar" - */ - public static final String URL_PROTOCOL_WSJAR = "wsjar"; - /** - * URL 协议表示JBoss zip文件: "vfszip" - */ - public static final String URL_PROTOCOL_VFSZIP = "vfszip"; - /** - * URL 协议表示JBoss文件: "vfsfile" - */ - public static final String URL_PROTOCOL_VFSFILE = "vfsfile"; - /** - * URL 协议表示JBoss VFS资源: "vfs" - */ - public static final String URL_PROTOCOL_VFS = "vfs"; /** * Jar路径以及内部文件路径的分界符: "!/" */ @@ -429,50 +400,6 @@ public class URLUtil { } // endregion - /** - * 提供的URL是否为文件
- * 文件协议包括"file", "vfsfile" 或 "vfs". - * - * @param url {@link URL} - * @return 是否为文件 - * @since 3.0.9 - */ - public static boolean isFileURL(final URL url) { - Assert.notNull(url, "URL must be not null"); - final String protocol = url.getProtocol(); - return (URL_PROTOCOL_FILE.equals(protocol) || // - URL_PROTOCOL_VFSFILE.equals(protocol) || // - URL_PROTOCOL_VFS.equals(protocol)); - } - - /** - * 提供的URL是否为jar包URL 协议包括: "jar", "zip", "vfszip" 或 "wsjar". - * - * @param url {@link URL} - * @return 是否为jar包URL - */ - public static boolean isJarURL(final URL url) { - Assert.notNull(url, "URL must be not null"); - final String protocol = url.getProtocol(); - return (URL_PROTOCOL_JAR.equals(protocol) || // - URL_PROTOCOL_ZIP.equals(protocol) || // - URL_PROTOCOL_VFSZIP.equals(protocol) || // - URL_PROTOCOL_WSJAR.equals(protocol)); - } - - /** - * 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar - * - * @param url the URL to check - * @return whether the URL has been identified as a JAR file URL - * @since 4.1 - */ - public static boolean isJarFileURL(final URL url) { - Assert.notNull(url, "URL must be not null"); - return (URL_PROTOCOL_FILE.equals(url.getProtocol()) && // - url.getPath().toLowerCase().endsWith(FileNameUtil.EXT_JAR)); - } - /** * 从URL中获取流 * @@ -704,7 +631,7 @@ public class URLUtil { * @since 6.0.0 */ public static long size(final URL url) { - if (URLUtil.isFileURL(url)) { + if (UrlProtocolUtil.isFileOrVfsURL(url)) { // 如果资源以独立文件形式存在,尝试获取文件长度 final File file = FileUtil.file(url); final long length = file.length(); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java new file mode 100644 index 000000000..f2b543c25 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/net/url/UrlProtocolUtil.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.net.url; + +import org.dromara.hutool.core.io.file.FileNameUtil; +import org.dromara.hutool.core.lang.Assert; + +import java.net.URL; + +public class UrlProtocolUtil { + /** + * URL 协议表示文件: "file" + */ + public static final String URL_PROTOCOL_FILE = "file"; + /** + * URL 协议表示Jar文件: "jar" + */ + public static final String URL_PROTOCOL_JAR = "jar"; + /** + * URL 协议表示zip文件: "zip" + */ + public static final String URL_PROTOCOL_ZIP = "zip"; + /** + * URL 协议表示WebSphere文件: "wsjar" + */ + public static final String URL_PROTOCOL_WSJAR = "wsjar"; + /** + * URL 协议表示JBoss zip文件: "vfszip" + */ + public static final String URL_PROTOCOL_VFSZIP = "vfszip"; + /** + * URL 协议表示JBoss文件: "vfsfile" + */ + public static final String URL_PROTOCOL_VFSFILE = "vfsfile"; + /** + * URL 协议表示JBoss VFS资源: "vfs" + */ + public static final String URL_PROTOCOL_VFS = "vfs"; + + /** + * 提供的URL是否为文件
+ * 文件协议包括"file", "vfsfile" 或 "vfs". + * + * @param url {@link URL} + * @return 是否为文件 + * @since 3.0.9 + */ + public static boolean isFileOrVfsURL(final URL url) { + Assert.notNull(url, "URL must be not null"); + return isFileURL(url) || isVfsURL(url); + } + + /** + * 提供的URL是否为文件
+ * 文件协议包括"file". + * + * @param url {@link URL} + * @return 是否为文件 + * @since 6.0.0 + */ + public static boolean isFileURL(final URL url) { + Assert.notNull(url, "URL must be not null"); + final String protocol = url.getProtocol(); + return URL_PROTOCOL_FILE.equals(protocol); + } + + /** + * 提供的URL是否为文件
+ * 文件协议包括"vfsfile" 或 "vfs". + * + * @param url {@link URL} + * @return 是否为文件 + * @since 6.0.0 + */ + public static boolean isVfsURL(final URL url) { + Assert.notNull(url, "URL must be not null"); + final String protocol = url.getProtocol(); + return (URL_PROTOCOL_VFSFILE.equals(protocol) || // + URL_PROTOCOL_VFS.equals(protocol)); + } + + /** + * 提供的URL是否为jar包URL 协议包括: "jar", "zip", "vfszip" 或 "wsjar". + * + * @param url {@link URL} + * @return 是否为jar包URL + */ + public static boolean isJarURL(final URL url) { + Assert.notNull(url, "URL must be not null"); + final String protocol = url.getProtocol(); + return (URL_PROTOCOL_JAR.equals(protocol) || // + URL_PROTOCOL_ZIP.equals(protocol) || // + URL_PROTOCOL_VFSZIP.equals(protocol) || // + URL_PROTOCOL_WSJAR.equals(protocol)); + } + + /** + * 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar + * + * @param url the URL to check + * @return whether the URL has been identified as a JAR file URL + * @since 4.1 + */ + public static boolean isJarFileURL(final URL url) { + Assert.notNull(url, "URL must be not null"); + return (URL_PROTOCOL_FILE.equals(url.getProtocol()) && // + url.getPath().toLowerCase().endsWith(FileNameUtil.EXT_JAR)); + } +} diff --git a/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java b/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java index b26a55b5b..97b0709de 100644 --- a/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java +++ b/hutool-setting/src/main/java/org/dromara/hutool/setting/props/Props.java @@ -190,7 +190,7 @@ public final class Props extends Properties implements TypeGetter * @since 5.5.2 */ public void load(final URL url) { - load(new UrlResource(url)); + load(ResourceUtil.getResource(url)); } /**