From f37edfd84fe1847a2c8ccaf3cbca926abe99b705 Mon Sep 17 00:00:00 2001 From: LuisStruggle <18300767078@163.com> Date: Fri, 10 Feb 2023 11:28:46 +0800 Subject: [PATCH 001/125] =?UTF-8?q?fix=EF=BC=9AListUtil.reverse()=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=BD=93=E8=AF=A5=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E5=8F=82=E6=95=B0list=E4=B8=BAnull=E5=AF=B9=E8=B1=A1=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E5=87=BA=E7=8E=B0=E7=A9=BA=E6=8C=87=E9=92=88=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/collection/ListUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index be30e38d3..c59a9dae7 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -386,6 +386,9 @@ public class ListUtil { * @since 4.0.6 */ public static List reverse(final List list) { + if (CollUtil.isEmpty(list)) { + return list; + } Collections.reverse(list); return list; } From fdffcbfe7cef93a9095cbf9fd59c030d70341e20 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Sat, 11 Feb 2023 15:30:33 +0800 Subject: [PATCH 002/125] =?UTF-8?q?=E8=BF=94=E5=9B=9EemptyMap=E4=BB=A3?= =?UTF-8?q?=E6=9B=BFnull=EF=BC=8C=E4=BD=BF=E7=94=A8=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E7=94=A8=E9=A2=9D=E5=A4=96=E5=88=A4=E6=96=ADnull=E7=9A=84?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/util/EnumUtil.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java index 6e85d2095..57a3e437b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java @@ -8,11 +8,7 @@ import cn.hutool.core.reflect.FieldUtil; import cn.hutool.core.text.StrUtil; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; import java.util.function.Predicate; @@ -315,7 +311,7 @@ public class EnumUtil { public static Map getNameFieldMap(final Class> clazz, final String fieldName) { final Enum[] enums = clazz.getEnumConstants(); if (null == enums) { - return null; + return Collections.emptyMap(); } final Map map = MapUtil.newHashMap(enums.length, true); for (final Enum e : enums) { From b1e9f263bcc2f9c8ba3861c6c1b84e3d5caf49ef Mon Sep 17 00:00:00 2001 From: huahua Date: Tue, 26 Jul 2022 10:07:15 +0800 Subject: [PATCH 003/125] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=92=88=E5=AF=B9=20?= =?UTF-8?q?int=20long=20double=E7=B1=BB=E5=9E=8B=E7=9A=84sum=E5=92=8Cavg?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 69 +++++++++++++++++++ .../cn/hutool/core/stream/EasyStreamTest.java | 9 +++ 2 files changed, 78 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index e3659496c..b84fefc03 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; import java.util.Objects; +import java.util.OptionalDouble; import java.util.Spliterator; import java.util.function.*; import java.util.stream.Stream; @@ -264,6 +265,74 @@ public class EasyStream extends AbstractEnhancedWrappedStream(stream); } + + + + /** + * 计算int类型总和 + * + * @param mapper 映射 + * @return int + */ + public int sum(ToIntFunction mapper) { + return stream.mapToInt(mapper).sum(); + } + + /** + * 计算long类型总和 + * + * @param mapper 映射 + * @return long + */ + public long sum(ToLongFunction mapper) { + return stream.mapToLong(mapper).sum(); + } + + + /** + * 计算double总和 + * + * @param mapper 映射器 + * @return double + */ + public double sum(ToDoubleFunction mapper) { + return stream.mapToDouble(mapper).sum(); + } + + + + /** + * 计算int平均值 + * + * @param mapper 映射器 + * @return {@link Integer} + */ + public OptionalDouble avg(ToIntFunction mapper) { + return stream.mapToInt(mapper).average(); + } + + /** + * 计算double平均值 + * + * @param mapper 映射 + * @return {@link OptionalDouble} + */ + public OptionalDouble avg(ToDoubleFunction mapper) { + return stream.mapToDouble(mapper).average(); + } + + + /** + * 计算double平均值 + * + * @param mapper 映射 + * @return {@link OptionalDouble} + */ + public OptionalDouble avg(ToLongFunction mapper) { + return stream.mapToLong(mapper).average(); + } + + /** * 建造者 * diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index 0f50b8337..1818f061f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -433,4 +433,13 @@ public class EasyStreamTest { Assert.assertTrue(EasyStream.of(1).isNotEmpty()); } + + @Test + public void testIntSum() { + int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue); + Assert.assertEquals(sum,55); + double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue); + Assert.assertEquals(doubleSum,59.6); + } + } From 74ca8eb1d08d1cfdffb870ea1f3cf861dc359cf7 Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 12 Feb 2023 14:54:24 +0800 Subject: [PATCH 004/125] fix doc; --- .../java/cn/hutool/core/net/Ipv4Util.java | 210 ++++++++++-------- .../java/cn/hutool/core/net/Ipv4UtilTest.java | 57 ++++- 2 files changed, 169 insertions(+), 98 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index 6c8c89689..2745aa5e5 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -17,7 +17,19 @@ import java.util.regex.Matcher; * *

pr自:https://gitee.com/loolly/hutool/pulls/161

* + *

名词解释: + *

    + *
  • ip字符串:点分十进制,形如:xxx.xxx.xxx.xxx
  • + *
  • ip的Long类型:有效位32位,每8位可以转为一个十进制数,例如:0xC0A802FA, 转为点分十进制是:192.168.2.250
  • + *
  • 掩码地址:点分十进制,例如:255.255.255.0
  • + *
  • 掩码位:int类型,例如 24, 它代表的掩码地址为:255.255.255.0;掩码位和掩码地址的相互转换,请使用 {@link MaskBit}
  • + *
  • CIDR:无类域间路由,形如:xxx.xxx.xxx.xxx/掩码位
  • + *
  • 全量地址:区间内所有ip地址,包含区间两端
  • + *
  • 可用地址:区间内所有ip地址,但是不包含区间两端
  • + *
+ * * @author ZhuKun + * @author emptypoint * @since 5.4.1 */ public class Ipv4Util { @@ -43,22 +55,57 @@ public class Ipv4Util { public static final int IP_MASK_MAX = 32; /** - * 格式化IP段 + * 最小掩码位 + */ + public static final int IP_MASK_MIN = 1; + + /** + * A类私有地址的最小值 + */ + public static final long A_INNER_IP_LONG_BEGIN = ipv4ToLong("10.0.0.0"); + + /** + * A类私有地址的最大值 + */ + public static final long A_INNER_IP_LONG_END = ipv4ToLong("10.255.255.255"); + + /** + * B类私有地址的最小值 + */ + public static final long B_INNER_IP_LONG_BEGIN = ipv4ToLong("172.16.0.0"); + + /** + * B类私有地址的最大值 + */ + public static final long B_INNER_IP_LONG_END = ipv4ToLong("172.31.255.255"); + + /** + * C类私有地址的最小值 + */ + public static final long C_INNER_IP_LONG_BEGIN = ipv4ToLong("192.168.0.0"); + + /** + * C类私有地址的最大值 + */ + public static final long C_INNER_IP_LONG_END = ipv4ToLong("192.168.255.255"); + + /** + * 根据 ip地址 和 掩码地址 获得 CIDR格式字符串 * - * @param ip IP地址 - * @param mask 掩码 - * @return 返回xxx.xxx.xxx.xxx/mask的格式 + * @param ip IP地址,点分十进制,如:xxx.xxx.xxx.xxx + * @param mask 掩码地址,点分十进制,如:255.255.255.0 + * @return 返回 {@literal xxx.xxx.xxx.xxx/掩码位} 的格式 */ public static String formatIpBlock(final String ip, final String mask) { return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask); } /** - * 智能转换IP地址集合 + * 智能获取指定区间内的所有IP地址 * - * @param ipRange IP段,支持X.X.X.X-X.X.X.X或X.X.X.X/X - * @param isAll true:全量地址,false:可用地址;仅在ipRange为X.X.X.X/X时才生效 - * @return IP集 + * @param ipRange IP区间,支持 {@literal X.X.X.X-X.X.X.X} 或 {@literal X.X.X.X/X} + * @param isAll true:全量地址,false:可用地址;该参数仅在ipRange为X.X.X.X/X时才生效 + * @return 区间内的所有IP地址,点分十进制格式 */ public static List list(final String ipRange, final boolean isAll) { if (ipRange.contains(IP_SPLIT_MARK)) { @@ -75,12 +122,12 @@ public class Ipv4Util { } /** - * 根据IP地址、子网掩码获取IP地址区间 + * 根据 IP地址 和 掩码位数 获取 子网所有ip地址 * - * @param ip IP地址 + * @param ip IP地址,点分十进制 * @param maskBit 掩码位,例如24、32 * @param isAll true:全量地址,false:可用地址 - * @return 区间地址 + * @return 子网所有ip地址 */ public static List list(final String ip, final int maskBit, final boolean isAll) { if (maskBit == IP_MASK_MAX) { @@ -107,11 +154,11 @@ public class Ipv4Util { } /** - * 得到IP地址区间 + * 获得 指定区间内 所有ip地址 * - * @param ipFrom 开始IP - * @param ipTo 结束IP - * @return 区间地址 + * @param ipFrom 开始IP,包含,点分十进制 + * @param ipTo 结束IP,包含,点分十进制 + * @return 区间内所有ip地址 */ public static List list(final String ipFrom, final String ipTo) { // 确定ip数量 @@ -154,34 +201,34 @@ public class Ipv4Util { } /** - * 根据long值获取ip v4地址:xx.xx.xx.xx + * 根据 ip的long值 获取 ip字符串,即:xxx.xxx.xxx.xxx * - * @param longIP IP的long表示形式 - * @return IP V4 地址 + * @param longIp IP的long表示形式 + * @return 点分十进制ip地址 */ - public static String longToIpv4(final long longIP) { + public static String longToIpv4(final long longIp) { final StringBuilder sb = StrUtil.builder(); // 直接右移24位 - sb.append(longIP >> 24 & 0xFF); + sb.append(longIp >> 24 & 0xFF); sb.append(CharUtil.DOT); // 将高8位置0,然后右移16位 - sb.append(longIP >> 16 & 0xFF); + sb.append(longIp >> 16 & 0xFF); sb.append(CharUtil.DOT); - sb.append(longIP >> 8 & 0xFF); + sb.append(longIp >> 8 & 0xFF); sb.append(CharUtil.DOT); - sb.append(longIP & 0xFF); + sb.append(longIp & 0xFF); return sb.toString(); } /** - * 根据ip地址(xxx.xxx.xxx.xxx)计算出long型的数据 - * 方法别名:inet_aton + * 将 ip字符串 转换为 long值 + *

方法别名:inet_aton

* - * @param strIP IP V4 地址 - * @return long值 + * @param strIp ip地址,点分十进制,xxx.xxx.xxx.xxx + * @return ip的long值 */ - public static long ipv4ToLong(final String strIP) { - final Matcher matcher = PatternPool.IPV4.matcher(strIP); + public static long ipv4ToLong(final String strIp) { + final Matcher matcher = PatternPool.IPV4.matcher(strIp); if (matcher.matches()) { return matchAddress(matcher); } @@ -189,11 +236,11 @@ public class Ipv4Util { } /** - * 根据 ip/掩码位 计算IP段的起始IP(字符串型) - * 方法别名:inet_ntoa + * 根据 ip 和 掩码位 获取 子网的起始IP(字符串型) + *

方法别名:inet_ntoa

* - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 + * @param ip 给定的IP,点分十进制,如:xxx.xxx.xxx.xxx + * @param maskBit 给定的掩码位,如:30 * @return 起始IP的字符串表示 */ public static String getBeginIpStr(final String ip, final int maskBit) { @@ -201,10 +248,10 @@ public class Ipv4Util { } /** - * 根据 ip/掩码位 计算IP段的起始IP(Long型) + * 根据 ip 和 掩码位 获取 子网的起始IP(Long型) * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 + * @param ip 给定的IP,点分十进制,如:xxx.xxx.xxx.xxx + * @param maskBit 给定的掩码位,如:30 * @return 起始IP的长整型表示 */ public static Long getBeginIpLong(final String ip, final int maskBit) { @@ -212,10 +259,10 @@ public class Ipv4Util { } /** - * 根据 ip/掩码位 计算IP段的终止IP(字符串型) + * 根据 ip 和 掩码位 获取 子网的终止IP(字符串型) * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 + * @param ip 给定的IP,点分十进制,如:xxx.xxx.xxx.xxx + * @param maskBit 给定的掩码位,如:30 * @return 终止IP的字符串表示 */ public static String getEndIpStr(final String ip, final int maskBit) { @@ -223,7 +270,18 @@ public class Ipv4Util { } /** - * 根据子网掩码转换为掩码位 + * 根据 ip 和 掩码位 获取 子网的终止IP(Long型) + * + * @param ip 给定的IP,点分十进制,如:xxx.xxx.xxx.xxx + * @param maskBit 给定的掩码位,如:30 + * @return 终止IP的长整型表示 + */ + public static Long getEndIpLong(final String ip, final int maskBit) { + return getBeginIpLong(ip, maskBit) + ~ipv4ToLong(getMaskByMaskBit(maskBit)); + } + + /** + * 将 子网掩码 转换为 掩码位 * * @param mask 掩码的点分十进制表示,例如 255.255.255.0 * @return 掩码位,例如 24 @@ -238,11 +296,11 @@ public class Ipv4Util { } /** - * 计算子网大小 + * 获取 子网内的 地址总数 * - * @param maskBit 掩码位 + * @param maskBit 掩码位,取值范围:[2, {@link #IP_MASK_MAX}] * @param isAll true:全量地址,false:可用地址 - * @return 地址总数 + * @return 子网内地址总数 */ public static int countByMaskBit(final int maskBit, final boolean isAll) { //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0 @@ -255,21 +313,21 @@ public class Ipv4Util { } /** - * 根据掩码位获取掩码 + * 根据 掩码位 获取 掩码地址 * - * @param maskBit 掩码位 - * @return 掩码 + * @param maskBit 掩码位,如:24,取值范围:[{@link #IP_MASK_MIN}, {@link #IP_MASK_MAX}] + * @return 掩码地址,点分十进制,如:255.255.255.0 */ public static String getMaskByMaskBit(final int maskBit) { return MaskBit.get(maskBit); } /** - * 根据开始IP与结束IP计算掩码 + * 根据 开始IP 与 结束IP 获取 掩码地址 * - * @param fromIp 开始IP - * @param toIp 结束IP - * @return 掩码x.x.x.x + * @param fromIp 开始IP,包含,点分十进制 + * @param toIp 结束IP,包含,点分十进制 + * @return 掩码地址,点分十进制 */ public static String getMaskByIpRange(final String fromIp, final String toIp) { final long toIpLong = ipv4ToLong(toIp); @@ -286,10 +344,10 @@ public class Ipv4Util { } /** - * 计算IP区间有多少个IP + * 获得 指定区间内的 ip数量 * - * @param fromIp 开始IP - * @param toIp 结束IP + * @param fromIp 开始IP,包含,点分十进制 + * @param toIp 结束IP,包含,点分十进制 * @return IP数量 */ public static int countByIpRange(final String fromIp, final String toIp) { @@ -320,7 +378,7 @@ public class Ipv4Util { /** * 判断掩码位是否合法 * - * @param maskBit 掩码位,例如 24 + * @param maskBit 掩码位,有效范围:[{@link #IP_MASK_MIN}, {@link #IP_MASK_MAX}] * @return true:掩码位合法;false:掩码位不合法 */ public static boolean isMaskBitValid(final int maskBit) { @@ -337,47 +395,25 @@ public class Ipv4Util { * * 当然,还有127这个网段是环回地址 * - * @param ipAddress IP地址 + * @param ipAddress IP地址,点分十进制 * @return 是否为内网IP * @since 5.7.18 */ public static boolean isInnerIP(final String ipAddress) { - final boolean isInnerIp; final long ipNum = ipv4ToLong(ipAddress); - - final long aBegin = ipv4ToLong("10.0.0.0"); - final long aEnd = ipv4ToLong("10.255.255.255"); - - final long bBegin = ipv4ToLong("172.16.0.0"); - final long bEnd = ipv4ToLong("172.31.255.255"); - - final long cBegin = ipv4ToLong("192.168.0.0"); - final long cEnd = ipv4ToLong("192.168.255.255"); - - isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || LOCAL_IP.equals(ipAddress); - return isInnerIp; + return isBetween(ipNum, A_INNER_IP_LONG_BEGIN, A_INNER_IP_LONG_END) + || isBetween(ipNum, B_INNER_IP_LONG_BEGIN, B_INNER_IP_LONG_END) + || isBetween(ipNum, C_INNER_IP_LONG_BEGIN, C_INNER_IP_LONG_END) + || LOCAL_IP.equals(ipAddress); } //-------------------------------------------------------------------------------- Private method start /** - * 根据 ip/掩码位 计算IP段的终止IP(Long型) - * 注:此接口返回负数,请使用转成字符串后再转Long型 - * - * @param ip 给定的IP,如218.240.38.69 - * @param maskBit 给定的掩码位,如30 - * @return 终止IP的长整型表示 - */ - public static Long getEndIpLong(final String ip, final int maskBit) { - return getBeginIpLong(ip, maskBit) - + ~ipv4ToLong(getMaskByMaskBit(maskBit)); - } - - /** - * 将匹配到的Ipv4地址的4个分组分别处理 + * 将匹配到的Ipv4地址转为Long类型 * * @param matcher 匹配到的Ipv4正则 - * @return ipv4对应long + * @return ip的long值 */ private static long matchAddress(final Matcher matcher) { long addr = 0; @@ -388,14 +424,14 @@ public class Ipv4Util { } /** - * 指定IP的long是否在指定范围内 + * 指定IP是否在指定范围内 * * @param userIp 用户IP - * @param begin 开始IP - * @param end 结束IP + * @param begin 开始IP,包含 + * @param end 结束IP,包含 * @return 是否在范围内 */ - private static boolean isInner(final long userIp, final long begin, final long end) { + private static boolean isBetween(final long userIp, final long begin, final long end) { return (userIp >= begin) && (userIp <= end); } //-------------------------------------------------------------------------------- Private method end diff --git a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java index e98f646fa..97497d5b4 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java @@ -4,8 +4,6 @@ import org.junit.Assert; import org.junit.Test; import org.junit.function.ThrowingRunnable; -import java.util.List; - public class Ipv4UtilTest { @Test @@ -28,10 +26,16 @@ public class Ipv4UtilTest { @Test public void longToIpTest() { - final String ip = "192.168.1.255"; - final long ipLong = Ipv4Util.ipv4ToLong(ip); - final String ipv4 = Ipv4Util.longToIpv4(ipLong); - Assert.assertEquals(ip, ipv4); + testLongToIp("192.168.1.255"); + testLongToIp("0.0.0.0"); + testLongToIp("0.0.0.255"); + testLongToIp("0.0.255.255"); + testLongToIp("0.255.255.255"); + testLongToIp("255.255.255.255"); + testLongToIp("255.255.255.0"); + testLongToIp("255.255.0.0"); + testLongToIp("255.0.0.0"); + testLongToIp("0.255.255.0"); } @Test @@ -44,9 +48,24 @@ public class Ipv4UtilTest { @Test public void listTest(){ - final int maskBit = Ipv4Util.getMaskBitByMask("255.255.255.0"); - final List list = Ipv4Util.list("192.168.100.2", maskBit, false); - Assert.assertEquals(254, list.size()); + final String ip = "192.168.100.2"; + testGenerateIpList(ip, 22, false); + testGenerateIpList(ip, 22, true); + + testGenerateIpList(ip, 24, false); + testGenerateIpList(ip, 24, true); + + testGenerateIpList(ip, 26, false); + testGenerateIpList(ip, 26, true); + + testGenerateIpList(ip, 30, false); + testGenerateIpList(ip, 30, true); + + testGenerateIpList(ip, 31, false); + testGenerateIpList(ip, 31, true); + + testGenerateIpList(ip, 32, false); + testGenerateIpList(ip, 32, true); testGenerateIpList("10.1.0.1", "10.2.1.2"); @@ -90,8 +109,9 @@ public class Ipv4UtilTest { @Test public void isMaskBitValidTest() { - final boolean maskBitValid = Ipv4Util.isMaskBitValid(32); - Assert.assertTrue("掩码位合法检验", maskBitValid); + for (int i = 1; i < 32; i++) { + Assert.assertTrue("掩码位非法:" + i, Ipv4Util.isMaskBitValid(i)); + } } @Test @@ -119,4 +139,19 @@ public class Ipv4UtilTest { Ipv4Util.list(fromIp, toIp).size() ); } + + @SuppressWarnings("SameParameterValue") + private void testGenerateIpList(final String ip, final int maskBit, final boolean isAll) { + Assert.assertEquals( + Ipv4Util.countByMaskBit(maskBit, isAll), + Ipv4Util.list(ip, maskBit, isAll).size() + ); + } + + private static void testLongToIp(final String ip){ + final long ipLong = Ipv4Util.ipv4ToLong(ip); + final String ipv4 = Ipv4Util.longToIpv4(ipLong); + Assert.assertEquals(ip, ipv4); + } + } From c9fdb17e8e1b42271f43e798fba31b1fa73078e3 Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 12 Feb 2023 15:12:02 +0800 Subject: [PATCH 005/125] update code; --- .../java/cn/hutool/core/net/Ipv4Util.java | 122 ++++++++++++------ 1 file changed, 82 insertions(+), 40 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index 2745aa5e5..23eebfff0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -130,6 +130,12 @@ public class Ipv4Util { * @return 子网所有ip地址 */ public static List list(final String ip, final int maskBit, final boolean isAll) { + assertMaskBitValid(maskBit); + // 避免后续的计算异常 + if (countByMaskBit(maskBit, isAll) == 0) { + return new ArrayList<>(0); + } + if (maskBit == IP_MASK_MAX) { final List list = new ArrayList<>(); if (isAll) { @@ -144,6 +150,7 @@ public class Ipv4Util { return list(startIp, endIp); } + // 可用地址,排除开始和结束的地址 int lastDotIndex = startIp.lastIndexOf(CharUtil.DOT) + 1; startIp = StrUtil.subPre(startIp, lastDotIndex) + (Integer.parseInt(Objects.requireNonNull(StrUtil.subSuf(startIp, lastDotIndex))) + 1); @@ -207,17 +214,12 @@ public class Ipv4Util { * @return 点分十进制ip地址 */ public static String longToIpv4(final long longIp) { - final StringBuilder sb = StrUtil.builder(); - // 直接右移24位 - sb.append(longIp >> 24 & 0xFF); - sb.append(CharUtil.DOT); - // 将高8位置0,然后右移16位 - sb.append(longIp >> 16 & 0xFF); - sb.append(CharUtil.DOT); - sb.append(longIp >> 8 & 0xFF); - sb.append(CharUtil.DOT); - sb.append(longIp & 0xFF); - return sb.toString(); + return StrUtil.builder(15) + .append(getPartOfIpLong(longIp, 1)).append(CharUtil.DOT) + .append(getPartOfIpLong(longIp, 2)).append(CharUtil.DOT) + .append(getPartOfIpLong(longIp, 3)).append(CharUtil.DOT) + .append(getPartOfIpLong(longIp, 4)) + .toString(); } /** @@ -229,10 +231,8 @@ public class Ipv4Util { */ public static long ipv4ToLong(final String strIp) { final Matcher matcher = PatternPool.IPV4.matcher(strIp); - if (matcher.matches()) { - return matchAddress(matcher); - } - throw new IllegalArgumentException("Invalid IPv4 address!"); + Assert.isTrue(matcher.matches(), "Invalid IPv4 address: {}", strIp); + return matchAddress(matcher); } /** @@ -255,6 +255,7 @@ public class Ipv4Util { * @return 起始IP的长整型表示 */ public static Long getBeginIpLong(final String ip, final int maskBit) { + assertMaskBitValid(maskBit); return ipv4ToLong(ip) & ipv4ToLong(getMaskByMaskBit(maskBit)); } @@ -289,9 +290,7 @@ public class Ipv4Util { */ public static int getMaskBitByMask(final String mask) { final Integer maskBit = MaskBit.getMaskBit(mask); - if (maskBit == null) { - throw new IllegalArgumentException("Invalid netmask " + mask); - } + Assert.notNull(maskBit, "Invalid netmask:{}", mask); return maskBit; } @@ -303,12 +302,13 @@ public class Ipv4Util { * @return 子网内地址总数 */ public static int countByMaskBit(final int maskBit, final boolean isAll) { - //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0 - if ((false == isAll) && (maskBit <= 0 || maskBit >= 32)) { + assertMaskBitValid(maskBit); + //如果掩码位等于32,则可用地址为0 + if (maskBit == 32 && false == isAll) { return 0; } - final int count = (int) Math.pow(2, 32 - maskBit); + final int count = 1 << (32 - maskBit); return isAll ? count : count - 2; } @@ -332,15 +332,14 @@ public class Ipv4Util { public static String getMaskByIpRange(final String fromIp, final String toIp) { final long toIpLong = ipv4ToLong(toIp); final long fromIpLong = ipv4ToLong(fromIp); - Assert.isTrue(fromIpLong < toIpLong, "to IP must be greater than from IP!"); + Assert.isTrue(fromIpLong <= toIpLong, "Start IP must be less than or equal to end IP!"); - final String[] fromIpSplit = StrUtil.splitToArray(fromIp, CharUtil.DOT); - final String[] toIpSplit = StrUtil.splitToArray(toIp, CharUtil.DOT); - final StringBuilder mask = new StringBuilder(); - for (int i = 0; i < toIpSplit.length; i++) { - mask.append(255 - Integer.parseInt(toIpSplit[i]) + Integer.parseInt(fromIpSplit[i])).append(CharUtil.DOT); - } - return mask.substring(0, mask.length() - 1); + return StrUtil.builder(15) + .append(255 - getPartOfIpLong(toIpLong, 1) + getPartOfIpLong(fromIpLong, 1)).append(CharUtil.DOT) + .append(255 - getPartOfIpLong(toIpLong, 2) + getPartOfIpLong(fromIpLong, 2)).append(CharUtil.DOT) + .append(255 - getPartOfIpLong(toIpLong, 3) + getPartOfIpLong(fromIpLong, 3)).append(CharUtil.DOT) + .append(255 - getPartOfIpLong(toIpLong, 4) + getPartOfIpLong(fromIpLong, 4)) + .toString(); } /** @@ -353,15 +352,13 @@ public class Ipv4Util { public static int countByIpRange(final String fromIp, final String toIp) { final long toIpLong = ipv4ToLong(toIp); final long fromIpLong = ipv4ToLong(fromIp); - if (fromIpLong > toIpLong) { - throw new IllegalArgumentException("to IP must be greater than from IP!"); - } + Assert.isTrue(fromIpLong <= toIpLong, "Start IP must be less than or equal to end IP!"); + int count = 1; - final int[] fromIpSplit = StrUtil.split(fromIp, CharUtil.DOT).stream().mapToInt(Integer::parseInt).toArray(); - final int[] toIpSplit = StrUtil.split(toIp, CharUtil.DOT).stream().mapToInt(Integer::parseInt).toArray(); - for (int i = fromIpSplit.length - 1; i >= 0; i--) { - count += (toIpSplit[i] - fromIpSplit[i]) * Math.pow(256, fromIpSplit.length - i - 1); - } + count += (getPartOfIpLong(toIpLong, 4) - getPartOfIpLong(fromIpLong, 4)); + count += (getPartOfIpLong(toIpLong, 3) - getPartOfIpLong(fromIpLong, 3)) << 8; + count += (getPartOfIpLong(toIpLong, 2) - getPartOfIpLong(fromIpLong, 2)) << 16; + count += (getPartOfIpLong(toIpLong, 1) - getPartOfIpLong(fromIpLong, 1)) << 24; return count; } @@ -382,7 +379,7 @@ public class Ipv4Util { * @return true:掩码位合法;false:掩码位不合法 */ public static boolean isMaskBitValid(final int maskBit) { - return MaskBit.get(maskBit) != null; + return maskBit >= IP_MASK_MIN && maskBit <= IP_MASK_MAX; } /** @@ -416,9 +413,15 @@ public class Ipv4Util { * @return ip的long值 */ private static long matchAddress(final Matcher matcher) { - long addr = 0; + int addr = 0; + // 每个点分十进制数字 转为 8位二进制 for (int i = 1; i <= 4; ++i) { - addr |= Long.parseLong(matcher.group(i)) << 8 * (4 - i); + addr <<= 8; + addr |= Integer.parseInt(matcher.group(i)); + } + // int的最高位无法直接使用,转为Long + if (addr < 0) { + return 0xffffffffL & addr; } return addr; } @@ -434,5 +437,44 @@ public class Ipv4Util { private static boolean isBetween(final long userIp, final long begin, final long end) { return (userIp >= begin) && (userIp <= end); } + + /** + * 校验 掩码位数,合法范围为:[1,32],不合法则抛出异常 + * + * @param maskBit 掩码位数 + */ + private static void assertMaskBitValid(final int maskBit) { + Assert.isTrue(isMaskBitValid(maskBit), "Invalid maskBit:{}", maskBit); + } + + /** + * 获取ip(Long类型)指定部分的十进制值,即,{@literal X.X.X.X }形式中每个部分的值 + *

例如,ip为{@literal 0xC0A802FA},第1部分的值为: + *

    + *
  • 第1部分的值为:@literal 0xC0},十进制值为:192
  • + *
  • 第2部分的值为:@literal 0xA8},十进制值为:168
  • + *
  • 第3部分的值为:@literal 0x02},十进制值为:2
  • + *
  • 第4部分的值为:@literal 0xFA},十进制值为:250
  • + *
+ *

+ * + * @param ip ip地址,Long类型 + * @param position 指定位置,取值范围:[1,4] + * @return ip地址指定部分的十进制值 + */ + private static int getPartOfIpLong(final long ip, final int position) { + switch (position) { + case 1: + return ((int) ip >> 24) & 0xFF; + case 2: + return ((int) ip >> 16) & 0xFF; + case 3: + return ((int) ip >> 8) & 0xFF; + case 4: + return ((int) ip) & 0xFF; + default: + throw new IllegalArgumentException("Illegal position of ip Long: " + position); + } + } //-------------------------------------------------------------------------------- Private method end } From 4bed6c554a223423b479a51739c4a4a9df39d002 Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 12 Feb 2023 15:28:43 +0800 Subject: [PATCH 006/125] add method for ip Long; --- .../java/cn/hutool/core/net/Ipv4Util.java | 56 +++++++++++++------ .../main/java/cn/hutool/core/net/MaskBit.java | 12 ++++ 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index 23eebfff0..aad5addfc 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -137,7 +137,7 @@ public class Ipv4Util { } if (maskBit == IP_MASK_MAX) { - final List list = new ArrayList<>(); + final List list = new ArrayList<>(isAll ? 1 : 0); if (isAll) { list.add(ip); } @@ -168,10 +168,19 @@ public class Ipv4Util { * @return 区间内所有ip地址 */ public static List list(final String ipFrom, final String ipTo) { + return list(ipv4ToLong(ipFrom), ipv4ToLong(ipTo)); + } + + /** + * 得到指定区间内的所有IP地址 + * + * @param ipFrom 开始IP, 包含 + * @param ipTo 结束IP, 包含 + * @return 区间内所有ip地址,点分十进制表示 + */ + public static List list(final long ipFrom, final long ipTo) { // 确定ip数量 final int count = countByIpRange(ipFrom, ipTo); - final int[] from = Convert.convert(int[].class, StrUtil.splitToArray(ipFrom, CharUtil.DOT)); - final int[] to = Convert.convert(int[].class, StrUtil.splitToArray(ipTo, CharUtil.DOT)); final List ips = new ArrayList<>(count); // 是否是循环的第一个值 @@ -179,23 +188,23 @@ public class Ipv4Util { // 是否是循环的最后一个值 boolean aIsEnd, bIsEnd, cIsEnd; // 循环的结束值 - final int aEnd = to[0]; + final int aEnd = getPartOfIpLong(ipTo, 1); int bEnd; int cEnd; int dEnd; - for (int a = from[0]; a <= aEnd; a++) { + for (int a = getPartOfIpLong(ipFrom, 1); a <= aEnd; a++) { aIsEnd = (a == aEnd); // 本次循环的结束结束值 - bEnd = aIsEnd ? to[1] : 255; - for (int b = (aIsStart ? from[1] : 0); b <= bEnd; b++) { + bEnd = aIsEnd ? getPartOfIpLong(ipTo, 2) : 255; + for (int b = (aIsStart ? getPartOfIpLong(ipFrom, 2) : 0); b <= bEnd; b++) { // 在上一个循环是最后值的基础上进行判断 bIsEnd = aIsEnd && (b == bEnd); - cEnd = bIsEnd ? to[2] : 255; - for (int c = (bIsStart ? from[2] : 0); c <= cEnd; c++) { + cEnd = bIsEnd ? getPartOfIpLong(ipTo, 3) : 255; + for (int c = (bIsStart ? getPartOfIpLong(ipFrom, 3) : 0); c <= cEnd; c++) { // 在之前循环是最后值的基础上进行判断 cIsEnd = bIsEnd && (c == cEnd); - dEnd = cIsEnd ? to[3] : 255; - for (int d = (cIsStart ? from[3] : 0); d <= dEnd; d++) { + dEnd = cIsEnd ? getPartOfIpLong(ipTo, 4) : 255; + for (int d = (cIsStart ? getPartOfIpLong(ipFrom, 4) : 0); d <= dEnd; d++) { ips.add(a + "." + b + "." + c + "." + d); } cIsStart = false; @@ -256,7 +265,7 @@ public class Ipv4Util { */ public static Long getBeginIpLong(final String ip, final int maskBit) { assertMaskBitValid(maskBit); - return ipv4ToLong(ip) & ipv4ToLong(getMaskByMaskBit(maskBit)); + return ipv4ToLong(ip) & MaskBit.getMaskIpLong(maskBit); } /** @@ -278,7 +287,7 @@ public class Ipv4Util { * @return 终止IP的长整型表示 */ public static Long getEndIpLong(final String ip, final int maskBit) { - return getBeginIpLong(ip, maskBit) + ~ipv4ToLong(getMaskByMaskBit(maskBit)); + return getBeginIpLong(ip, maskBit) + ~MaskBit.getMaskIpLong(maskBit); } /** @@ -352,13 +361,24 @@ public class Ipv4Util { public static int countByIpRange(final String fromIp, final String toIp) { final long toIpLong = ipv4ToLong(toIp); final long fromIpLong = ipv4ToLong(fromIp); - Assert.isTrue(fromIpLong <= toIpLong, "Start IP must be less than or equal to end IP!"); + return countByIpRange(fromIpLong, toIpLong); + } + + /** + * 获得 指定区间内的 ip数量 + * + * @param fromIp 开始IP,包含 + * @param toIp 结束IP,包含 + * @return IP数量 + */ + public static int countByIpRange(final long fromIp, final long toIp) { + Assert.isTrue(fromIp <= toIp, "Start IP must be less than or equal to end IP!"); int count = 1; - count += (getPartOfIpLong(toIpLong, 4) - getPartOfIpLong(fromIpLong, 4)); - count += (getPartOfIpLong(toIpLong, 3) - getPartOfIpLong(fromIpLong, 3)) << 8; - count += (getPartOfIpLong(toIpLong, 2) - getPartOfIpLong(fromIpLong, 2)) << 16; - count += (getPartOfIpLong(toIpLong, 1) - getPartOfIpLong(fromIpLong, 1)) << 24; + count += (getPartOfIpLong(toIp, 4) - getPartOfIpLong(fromIp, 4)); + count += (getPartOfIpLong(toIp, 3) - getPartOfIpLong(fromIp, 3)) << 8; + count += (getPartOfIpLong(toIp, 2) - getPartOfIpLong(fromIp, 2)) << 16; + count += (getPartOfIpLong(toIp, 1) - getPartOfIpLong(fromIp, 1)) << 24; return count; } diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java index 8e2cccc22..5b51c0c10 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java @@ -1,5 +1,6 @@ package cn.hutool.core.net; +import cn.hutool.core.lang.Assert; import cn.hutool.core.map.BiMap; import java.util.HashMap; @@ -73,4 +74,15 @@ public class MaskBit { return MASK_BIT_MAP.getKey(mask); } + /** + * 根据掩码位获取掩码IP(Long型) + * + * @param maskBit 掩码位 + * @return 掩码IP(Long型) + * @since 6.0.0 + */ + public static long getMaskIpLong(final int maskBit) { + Assert.isTrue(MASK_BIT_MAP.containsKey(maskBit), "非法的掩码位数:{}", maskBit); + return -1L << (32 - maskBit); + } } From c79ab01fed176af04a5fea1329bac4bbe662a024 Mon Sep 17 00:00:00 2001 From: ZZemptypoint Date: Sun, 12 Feb 2023 21:55:46 +0800 Subject: [PATCH 007/125] update code; --- .../src/main/java/cn/hutool/core/net/Ipv4Util.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index aad5addfc..617a3b0ed 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -1,11 +1,10 @@ package cn.hutool.core.net; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; import cn.hutool.core.regex.PatternPool; -import cn.hutool.core.util.CharUtil; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.CharUtil; import java.util.ArrayList; import java.util.List; @@ -192,6 +191,7 @@ public class Ipv4Util { int bEnd; int cEnd; int dEnd; + final StringBuilder sb = StrUtil.builder(15); for (int a = getPartOfIpLong(ipFrom, 1); a <= aEnd; a++) { aIsEnd = (a == aEnd); // 本次循环的结束结束值 @@ -205,7 +205,12 @@ public class Ipv4Util { cIsEnd = bIsEnd && (c == cEnd); dEnd = cIsEnd ? getPartOfIpLong(ipTo, 4) : 255; for (int d = (cIsStart ? getPartOfIpLong(ipFrom, 4) : 0); d <= dEnd; d++) { - ips.add(a + "." + b + "." + c + "." + d); + sb.setLength(0); + ips.add(sb.append(a).append(CharUtil.DOT) + .append(b).append(CharUtil.DOT) + .append(c).append(CharUtil.DOT) + .append(d) + .toString()); } cIsStart = false; } From 835e7bf66d61ba33426ad32db48e014cd96353b9 Mon Sep 17 00:00:00 2001 From: huahua Date: Mon, 13 Feb 2023 21:09:53 +0800 Subject: [PATCH 008/125] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=92=88=E5=AF=B9=20?= =?UTF-8?q?bigDecimal=E7=B1=BB=E5=9E=8B=E7=9A=84avg=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 35 ++++ .../cn/hutool/core/stream/EasyStreamTest.java | 161 +++++++++++------- 2 files changed, 135 insertions(+), 61 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index b84fefc03..9001d19cf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -1,13 +1,19 @@ package cn.hutool.core.stream; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Opt; +import cn.hutool.core.math.NumberUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; import java.util.Objects; import java.util.OptionalDouble; import java.util.Spliterator; import java.util.function.*; +import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -299,6 +305,34 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { + return stream.map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + /** + * 计算bigDecimal平均值 + * @param mapper 映射 + * @param scale 精度 + * @param roundingMode 舍入模式 + * @return 如果元素的长度为0 那么会返回为空的opt + */ + public Opt avg(final Function mapper,int scale,RoundingMode roundingMode){ + //元素列表 + List bigDecimalList = stream.map(mapper).collect(Collectors.toList()); + if (CollUtil.isEmpty(bigDecimalList)){ + return Opt.ofNullable(null); + } + + return Opt.of(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add).divide(NumberUtil.toBigDecimal(bigDecimalList.size()),scale, roundingMode)); + } + + /** @@ -333,6 +367,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream orders = Arrays.asList(1, 2, 3, 2); final List list = Arrays.asList("dromara", "guava", "sweet", "hutool"); final Map map = MapUtil.builder() - .put(1, "dromara") - .put(2, "hutool") - .put(3, "sweet") - .build(); + .put(1, "dromara") + .put(2, "hutool") + .put(3, "sweet") + .build(); final Map toZip = EasyStream.of(orders).toZip(list); Assert.assertEquals(map, toZip); @@ -122,15 +126,15 @@ public class EasyStreamTest { final List list = Arrays.asList(1, 2, 3); final Map> group = EasyStream.of(list).group(String::valueOf); Assert.assertEquals( - new HashMap>() { - private static final long serialVersionUID = 1L; + new HashMap>() { + private static final long serialVersionUID = 1L; - { - put("1", singletonList(1)); - put("2", singletonList(2)); - put("3", singletonList(3)); - } - }, group); + { + put("1", singletonList(1)); + put("2", singletonList(2)); + put("3", singletonList(3)); + } + }, group); } @Test @@ -140,7 +144,7 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), mapIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), - EasyStream.of("dromara", "hutool", "sweet").parallel().mapIdx((e, i) -> i + 1 + "." + e).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel().mapIdx((e, i) -> i + 1 + "." + e).toList()); } @Test @@ -181,7 +185,7 @@ public class EasyStreamTest { Assert.assertEquals(ListUtil.sort(collect2), ListUtil.sort(distinctBy2)); Assert.assertEquals( - 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() + 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() ); } @@ -217,28 +221,28 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), mapIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), - EasyStream.of("dromara", "hutool", "sweet").parallel() - .flatMapIdx((e, i) -> EasyStream.of(i + 1 + "." + e)).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel() + .flatMapIdx((e, i) -> EasyStream.of(i + 1 + "." + e)).toList()); } @Test public void testPeek() { EasyStream.of("one", "two", "three", "four") - .filter(e -> e.length() == 4) - .peek(e -> Assert.assertEquals("four", e)) - .map(String::toUpperCase) - .peek(e -> Assert.assertEquals("FOUR", e)) - .collect(Collectors.toList()); + .filter(e -> e.length() == 4) + .peek(e -> Assert.assertEquals("four", e)) + .map(String::toUpperCase) + .peek(e -> Assert.assertEquals("FOUR", e)) + .collect(Collectors.toList()); } @Test public void testPeekIdx() { EasyStream.of("one", "two", "three", "four") - .filter(e -> e.length() == 4) - .peekIdx((e, i) -> Assert.assertEquals("four:0", e + ":" + i)) - .map(String::toUpperCase) - .peekIdx((e, i) -> Assert.assertEquals("FOUR:0", e + ":" + i)) - .collect(Collectors.toList()); + .filter(e -> e.length() == 4) + .peekIdx((e, i) -> Assert.assertEquals("four:0", e + ":" + i)) + .map(String::toUpperCase) + .peekIdx((e, i) -> Assert.assertEquals("FOUR:0", e + ":" + i)) + .collect(Collectors.toList()); } @Test @@ -274,7 +278,7 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("dromara", "hutool"), filterIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("dromara", "hutool"), - EasyStream.of("dromara", "hutool", "sweet").parallel().filterIdx((e, i) -> i < 2).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel().filterIdx((e, i) -> i < 2).toList()); } @Test @@ -380,23 +384,23 @@ public class EasyStreamTest { final List list = EasyStream.iterate(1, i -> i <= 10, i -> i + 1).toList(); final List res1 = EasyStream.of(list) - // 舍弃 5 - .takeWhile(e -> e < 5) - // 过滤奇数 - .filter(e -> (e & 1) == 0) - // 反序 - .sorted(Comparator.reverseOrder()) - .map(String::valueOf) - .toList(); + // 舍弃 5 + .takeWhile(e -> e < 5) + // 过滤奇数 + .filter(e -> (e & 1) == 0) + // 反序 + .sorted(Comparator.reverseOrder()) + .map(String::valueOf) + .toList(); Assert.assertEquals(Arrays.asList("4", "2"), res1); final List res2 = EasyStream.iterate(1, i -> i + 1) - .parallel() - .takeWhile(e -> e < 5) - .map(String::valueOf) - .map(Integer::valueOf) - .sorted(Comparator.naturalOrder()) - .toList(); + .parallel() + .takeWhile(e -> e < 5) + .map(String::valueOf) + .map(Integer::valueOf) + .sorted(Comparator.naturalOrder()) + .toList(); Assert.assertEquals(Arrays.asList(1, 2, 3, 4), res2); } @@ -406,25 +410,25 @@ public class EasyStreamTest { final List list = EasyStream.iterate(1, i -> i <= 10, i -> i + 1).toList(); final List res1 = EasyStream.of(list) - // 舍弃 5之前的数字 - .dropWhile(e -> e < 5) - // 过滤偶数 - .filter(e -> (e & 1) == 1) - // 反序 - .sorted(Comparator.reverseOrder()) - .map(String::valueOf) - .toList(); + // 舍弃 5之前的数字 + .dropWhile(e -> e < 5) + // 过滤偶数 + .filter(e -> (e & 1) == 1) + // 反序 + .sorted(Comparator.reverseOrder()) + .map(String::valueOf) + .toList(); Assert.assertEquals(Arrays.asList("9", "7", "5"), res1); final List res2 = EasyStream.of(list) - .parallel() - .dropWhile(e -> e < 5) - // 过滤偶数 - .filter(e -> (e & 1) == 1) - .map(String::valueOf) - .map(Integer::valueOf) - .sorted(Comparator.naturalOrder()) - .toList(); + .parallel() + .dropWhile(e -> e < 5) + // 过滤偶数 + .filter(e -> (e & 1) == 1) + .map(String::valueOf) + .map(Integer::valueOf) + .sorted(Comparator.naturalOrder()) + .toList(); Assert.assertEquals(Arrays.asList(5, 7, 9), res2); } @@ -435,11 +439,46 @@ public class EasyStreamTest { @Test - public void testIntSum() { + public void testIntSumAndAvg() { int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue); - Assert.assertEquals(sum,55); - double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue); - Assert.assertEquals(doubleSum,59.6); + Assert.assertEquals(sum, 55); + + //测试为空 + List integerList = new ArrayList<>(); + int emptySum = EasyStream.of(integerList).sum(Integer::intValue); + Assert.assertEquals(emptySum, 0); } + @Test + public void testDoubleSumAndAvg() { + double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue); + Assert.assertEquals(doubleSum, 59.6,2); + + List doubleList = new ArrayList<>(); + double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue); + Assert.assertEquals(emptySum, 0.0,2); + + } + + @Test + public void testLongSumAndAvg() { + long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue); + Assert.assertEquals(sum, 55); + + List longList = new ArrayList<>(); + double emptySum = EasyStream.of(longList).sum(Long::longValue); + Assert.assertEquals(emptySum, 0L); + + } + + @Test + public void testBigDecimalSumAndAvg() { + BigDecimal sum = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)).sum(Function.identity()); + Assert.assertEquals(sum, 59.6); + + List bigDecimalList = new ArrayList<>(); + BigDecimal emptySum = EasyStream.of(bigDecimalList).sum(Function.identity()); + Assert.assertEquals(emptySum, BigDecimal.ZERO); + + } } From 2becd707b669bf34bdf7797419b3cadcf23f3eff Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Mon, 13 Feb 2023 21:37:54 +0800 Subject: [PATCH 009/125] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=8A=9B=E5=87=BA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=96=B9=E5=BC=8F=E4=BB=A3=E6=9B=BFnull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java index 57a3e437b..cc03082b3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java @@ -311,7 +311,7 @@ public class EnumUtil { public static Map getNameFieldMap(final Class> clazz, final String fieldName) { final Enum[] enums = clazz.getEnumConstants(); if (null == enums) { - return Collections.emptyMap(); + throw new IllegalArgumentException(StrUtil.format("Class [{}] is not an Enum type!", clazz.getName())); } final Map map = MapUtil.newHashMap(enums.length, true); for (final Enum e : enums) { From a079a809082e1e5cdd23502e7b377f0aaa65b032 Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Mon, 13 Feb 2023 21:48:23 +0800 Subject: [PATCH 010/125] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 86 +++++--- .../cn/hutool/core/stream/EasyStreamTest.java | 196 ++++++++++++------ 2 files changed, 186 insertions(+), 96 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 9001d19cf..1e2f4a919 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -104,7 +104,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 * @return 包含单个元素的串行流 */ @@ -116,9 +116,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 + * @param 元素类型 * @return 包含指定元素的串行流 - * 从一个安全数组中创建流 + * 从一个安全数组中创建流 */ @SafeVarargs @SuppressWarnings("varargs") @@ -130,7 +130,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 + * @param 元素类型 * @return 流 */ public static EasyStream of(final Iterable iterable) { @@ -142,7 +142,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 + * @param 元素类型 * @return 流 */ public static EasyStream of(final Iterable iterable, final boolean parallel) { @@ -157,7 +157,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 + * @param 元素类型 * @return 流 */ public static EasyStream of(final Stream stream) { @@ -173,9 +173,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream * - * @param 元素类型 + * @param 元素类型 * @param seed 初始值 - * @param f 用上一个元素作为参数执行并返回一个新的元素 + * @param f 用上一个元素作为参数执行并返回一个新的元素 * @return 无限有序流 */ public static EasyStream iterate(final T seed, final UnaryOperator f) { @@ -191,13 +191,14 @@ public class EasyStream extends AbstractEnhancedWrappedStream * - * @param 元素类型 - * @param seed 初始值 + * @param 元素类型 + * @param seed 初始值 * @param hasNext 条件值 - * @param next 用上一个元素作为参数执行并返回一个新的元素 + * @param next 用上一个元素作为参数执行并返回一个新的元素 * @return 无限有序流 */ - public static EasyStream iterate(final T seed, final Predicate hasNext, final UnaryOperator next) { + public static EasyStream iterate(final T seed, final Predicate hasNext, + final UnaryOperator next) { Objects.requireNonNull(next); Objects.requireNonNull(hasNext); return new EasyStream<>(StreamUtil.iterate(seed, hasNext, next)); @@ -209,7 +210,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 - * @param s 用来生成元素的 {@code Supplier} + * @param s 用来生成元素的 {@code Supplier} * @return 无限串行无序流 */ public static EasyStream generate(final Supplier s) { @@ -224,8 +225,8 @@ public class EasyStream extends AbstractEnhancedWrappedStream从重复串行流进行拼接时可能会导致深度调用链甚至抛出 {@code StackOverflowException}

* * @param 元素类型 - * @param a 第一个流 - * @param b 第二个流 + * @param a 第一个流 + * @param b 第二个流 * @return 拼接两个流之后的流 */ public static EasyStream concat(final Stream a, final Stream b) { @@ -235,12 +236,13 @@ public class EasyStream extends AbstractEnhancedWrappedStream split(final CharSequence str, final String regex) { - return Opt.ofBlankAble(str).map(CharSequence::toString).map(s -> s.split(regex)).map(EasyStream::of).orElseGet(EasyStream::empty); + return Opt.ofBlankAble(str).map(CharSequence::toString).map(s -> s.split(regex)).map(EasyStream::of) + .orElseGet(EasyStream::empty); } // --------------------------------------------------------------- Static method end @@ -251,7 +253,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 函数执行后返回的类型 + * @param 函数执行后返回的类型 * @return 返回叠加操作后的流 */ @Override @@ -272,8 +274,6 @@ public class EasyStream extends AbstractEnhancedWrappedStream extends AbstractEnhancedWrappedStream mapper) { - return stream.map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add); + return stream.map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + + /** + * 计算bigDecimal平均值 并以四舍五入的方式保留2位精度 + * + * @param mapper 映射 + * @return 如果元素的长度为0 那么会返回为空的opt + */ + public Opt avg(final Function mapper) { + return avg(mapper, 2); + } + + + /** + * 计算bigDecimal平均值 并以四舍五入的方式保留scale的进度 + * + * @param mapper 映射 + * @param scale 精度 + * @return 如果元素的长度为0 那么会返回为空的opt + */ + public Opt avg(final Function mapper, int scale) { + return avg(mapper, scale, RoundingMode.HALF_UP); } /** * 计算bigDecimal平均值 + * * @param mapper 映射 * @param scale 精度 * @param roundingMode 舍入模式 * @return 如果元素的长度为0 那么会返回为空的opt */ - public Opt avg(final Function mapper,int scale,RoundingMode roundingMode){ + public Opt avg(final Function mapper, int scale, RoundingMode roundingMode) { //元素列表 List bigDecimalList = stream.map(mapper).collect(Collectors.toList()); - if (CollUtil.isEmpty(bigDecimalList)){ + if (CollUtil.isEmpty(bigDecimalList)) { return Opt.ofNullable(null); } - return Opt.of(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add).divide(NumberUtil.toBigDecimal(bigDecimalList.size()),scale, roundingMode)); + return Opt.of(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add) + .divide(NumberUtil.toBigDecimal(bigDecimalList.size()), scale, roundingMode)); } - - /** * 计算int平均值 * @@ -367,7 +390,6 @@ public class EasyStream extends AbstractEnhancedWrappedStream extends AbstractEnhancedWrappedStream{@code - * accept(t) - * return this; - * } + *
{@code
+		 * 						    accept(t)
+		 * 						    return this;
+		 *                      }
*/ default Builder add(final T t) { accept(t); diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index 5b83598a9..f44a0570a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -2,8 +2,10 @@ package cn.hutool.core.stream; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.lang.Opt; import cn.hutool.core.map.MapUtil; import cn.hutool.core.math.NumberUtil; +import java.math.RoundingMode; import org.junit.Assert; import org.junit.Test; @@ -85,10 +87,10 @@ public class EasyStreamTest { final List orders = Arrays.asList(1, 2, 3, 2); final List list = Arrays.asList("dromara", "guava", "sweet", "hutool"); final Map map = MapUtil.builder() - .put(1, "dromara") - .put(2, "hutool") - .put(3, "sweet") - .build(); + .put(1, "dromara") + .put(2, "hutool") + .put(3, "sweet") + .build(); final Map toZip = EasyStream.of(orders).toZip(list); Assert.assertEquals(map, toZip); @@ -126,15 +128,15 @@ public class EasyStreamTest { final List list = Arrays.asList(1, 2, 3); final Map> group = EasyStream.of(list).group(String::valueOf); Assert.assertEquals( - new HashMap>() { - private static final long serialVersionUID = 1L; + new HashMap>() { + private static final long serialVersionUID = 1L; - { - put("1", singletonList(1)); - put("2", singletonList(2)); - put("3", singletonList(3)); - } - }, group); + { + put("1", singletonList(1)); + put("2", singletonList(2)); + put("3", singletonList(3)); + } + }, group); } @Test @@ -144,7 +146,7 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), mapIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), - EasyStream.of("dromara", "hutool", "sweet").parallel().mapIdx((e, i) -> i + 1 + "." + e).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel().mapIdx((e, i) -> i + 1 + "." + e).toList()); } @Test @@ -185,7 +187,8 @@ public class EasyStreamTest { Assert.assertEquals(ListUtil.sort(collect2), ListUtil.sort(distinctBy2)); Assert.assertEquals( - 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() + 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true) + .distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count() ); } @@ -221,28 +224,28 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), mapIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("1.dromara", "2.hutool", "3.sweet"), - EasyStream.of("dromara", "hutool", "sweet").parallel() - .flatMapIdx((e, i) -> EasyStream.of(i + 1 + "." + e)).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel() + .flatMapIdx((e, i) -> EasyStream.of(i + 1 + "." + e)).toList()); } @Test public void testPeek() { EasyStream.of("one", "two", "three", "four") - .filter(e -> e.length() == 4) - .peek(e -> Assert.assertEquals("four", e)) - .map(String::toUpperCase) - .peek(e -> Assert.assertEquals("FOUR", e)) - .collect(Collectors.toList()); + .filter(e -> e.length() == 4) + .peek(e -> Assert.assertEquals("four", e)) + .map(String::toUpperCase) + .peek(e -> Assert.assertEquals("FOUR", e)) + .collect(Collectors.toList()); } @Test public void testPeekIdx() { EasyStream.of("one", "two", "three", "four") - .filter(e -> e.length() == 4) - .peekIdx((e, i) -> Assert.assertEquals("four:0", e + ":" + i)) - .map(String::toUpperCase) - .peekIdx((e, i) -> Assert.assertEquals("FOUR:0", e + ":" + i)) - .collect(Collectors.toList()); + .filter(e -> e.length() == 4) + .peekIdx((e, i) -> Assert.assertEquals("four:0", e + ":" + i)) + .map(String::toUpperCase) + .peekIdx((e, i) -> Assert.assertEquals("FOUR:0", e + ":" + i)) + .collect(Collectors.toList()); } @Test @@ -278,7 +281,7 @@ public class EasyStreamTest { Assert.assertEquals(Arrays.asList("dromara", "hutool"), filterIndex); // 并行流时正常 Assert.assertEquals(Arrays.asList("dromara", "hutool"), - EasyStream.of("dromara", "hutool", "sweet").parallel().filterIdx((e, i) -> i < 2).toList()); + EasyStream.of("dromara", "hutool", "sweet").parallel().filterIdx((e, i) -> i < 2).toList()); } @Test @@ -384,23 +387,23 @@ public class EasyStreamTest { final List list = EasyStream.iterate(1, i -> i <= 10, i -> i + 1).toList(); final List res1 = EasyStream.of(list) - // 舍弃 5 - .takeWhile(e -> e < 5) - // 过滤奇数 - .filter(e -> (e & 1) == 0) - // 反序 - .sorted(Comparator.reverseOrder()) - .map(String::valueOf) - .toList(); + // 舍弃 5 + .takeWhile(e -> e < 5) + // 过滤奇数 + .filter(e -> (e & 1) == 0) + // 反序 + .sorted(Comparator.reverseOrder()) + .map(String::valueOf) + .toList(); Assert.assertEquals(Arrays.asList("4", "2"), res1); final List res2 = EasyStream.iterate(1, i -> i + 1) - .parallel() - .takeWhile(e -> e < 5) - .map(String::valueOf) - .map(Integer::valueOf) - .sorted(Comparator.naturalOrder()) - .toList(); + .parallel() + .takeWhile(e -> e < 5) + .map(String::valueOf) + .map(Integer::valueOf) + .sorted(Comparator.naturalOrder()) + .toList(); Assert.assertEquals(Arrays.asList(1, 2, 3, 4), res2); } @@ -410,25 +413,25 @@ public class EasyStreamTest { final List list = EasyStream.iterate(1, i -> i <= 10, i -> i + 1).toList(); final List res1 = EasyStream.of(list) - // 舍弃 5之前的数字 - .dropWhile(e -> e < 5) - // 过滤偶数 - .filter(e -> (e & 1) == 1) - // 反序 - .sorted(Comparator.reverseOrder()) - .map(String::valueOf) - .toList(); + // 舍弃 5之前的数字 + .dropWhile(e -> e < 5) + // 过滤偶数 + .filter(e -> (e & 1) == 1) + // 反序 + .sorted(Comparator.reverseOrder()) + .map(String::valueOf) + .toList(); Assert.assertEquals(Arrays.asList("9", "7", "5"), res1); final List res2 = EasyStream.of(list) - .parallel() - .dropWhile(e -> e < 5) - // 过滤偶数 - .filter(e -> (e & 1) == 1) - .map(String::valueOf) - .map(Integer::valueOf) - .sorted(Comparator.naturalOrder()) - .toList(); + .parallel() + .dropWhile(e -> e < 5) + // 过滤偶数 + .filter(e -> (e & 1) == 1) + .map(String::valueOf) + .map(Integer::valueOf) + .sorted(Comparator.naturalOrder()) + .toList(); Assert.assertEquals(Arrays.asList(5, 7, 9), res2); } @@ -440,6 +443,7 @@ public class EasyStreamTest { @Test public void testIntSumAndAvg() { + //测试int类型的总和 int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue); Assert.assertEquals(sum, 55); @@ -447,38 +451,102 @@ public class EasyStreamTest { List integerList = new ArrayList<>(); int emptySum = EasyStream.of(integerList).sum(Integer::intValue); Assert.assertEquals(emptySum, 0); + + //测试平均值 + OptionalDouble avg = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).avg(Integer::intValue); + Assert.assertEquals(avg.getAsDouble(), 5.5, 2); + + //测试元素为空 + OptionalDouble emptyAvg = EasyStream.of(integerList).avg(Integer::intValue); + Assert.assertFalse(emptyAvg.isPresent()); + } @Test public void testDoubleSumAndAvg() { + //测试double类型的sum double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue); - Assert.assertEquals(doubleSum, 59.6,2); + Assert.assertEquals(doubleSum, 59.6, 2); + //测试double类型的sum 无元素double List doubleList = new ArrayList<>(); double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue); - Assert.assertEquals(emptySum, 0.0,2); + Assert.assertEquals(emptySum, 0.0, 2); + + //测试double类型的avg + OptionalDouble doubleAvg = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10) + .avg(Double::doubleValue); + Assert.assertEquals(doubleAvg.getAsDouble(), 5.96, 2); + + //测试double类型的 空元素的avg + OptionalDouble emptyDoubleAvg = EasyStream.of(doubleList).avg(Double::doubleValue); + Assert.assertFalse(emptyDoubleAvg.isPresent()); } @Test public void testLongSumAndAvg() { + //测试long类型的sum long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue); Assert.assertEquals(sum, 55); + //测试long类型的空元素 sum List longList = new ArrayList<>(); - double emptySum = EasyStream.of(longList).sum(Long::longValue); + long emptySum = EasyStream.of(longList).sum(Long::longValue); Assert.assertEquals(emptySum, 0L); + //测试long类型的avg + OptionalDouble doubleAvg = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).avg(Long::longValue); + Assert.assertEquals(doubleAvg.getAsDouble(), 5.5, 2); + + //测试long类型的avg 空元素 + OptionalDouble emptyDoubleAvg = EasyStream.of(longList).avg(Long::longValue); + Assert.assertFalse(emptyDoubleAvg.isPresent()); + + } @Test public void testBigDecimalSumAndAvg() { - BigDecimal sum = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)).sum(Function.identity()); - Assert.assertEquals(sum, 59.6); + //测试bigDecimal的sum + BigDecimal sum = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), + NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), + NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), + NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)).sum(Function.identity()); + Assert.assertEquals(sum, NumberUtil.toBigDecimal(59.6)); - List bigDecimalList = new ArrayList<>(); - BigDecimal emptySum = EasyStream.of(bigDecimalList).sum(Function.identity()); + //测试bigDecimal的sum 空元素 + List bigDecimalEmptyList = new ArrayList<>(); + BigDecimal emptySum = EasyStream.of(bigDecimalEmptyList).sum(Function.identity()); Assert.assertEquals(emptySum, BigDecimal.ZERO); + //测试bigDecimal的avg + Opt bigDecimalAvgFullParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), + NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), + NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), + NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + .avg(Function.identity(), 2, RoundingMode.HALF_UP); + Assert.assertEquals(bigDecimalAvgFullParam.get(), NumberUtil.toBigDecimal(5.96)); + + Opt bigDecimalAvgOneParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), + NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), + NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), + NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + .avg(Function.identity()); + Assert.assertEquals(bigDecimalAvgOneParam.get(), NumberUtil.toBigDecimal(5.96)); + + Opt bigDecimalAvgTwoParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), + NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), + NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), + NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + .avg(Function.identity(), 2); + Assert.assertEquals(bigDecimalAvgTwoParam.get(), NumberUtil.toBigDecimal(5.96)); + + //测试bigDecimal的avg 空元素 + Opt emptyBigDecimalAvg = EasyStream.of(bigDecimalEmptyList) + .avg(Function.identity(), 2, RoundingMode.HALF_UP); + Assert.assertFalse(emptyBigDecimalAvg.isPresent()); + + } } From ef61893d59386f96b6ff2894a828eb6b15eda258 Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Mon, 13 Feb 2023 22:04:34 +0800 Subject: [PATCH 011/125] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 14 ++++---- .../cn/hutool/core/stream/EasyStreamTest.java | 35 +++++++++++-------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 1e2f4a919..549911bc5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -320,7 +320,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 如果元素的长度为0 那么会返回为空的opt */ public Opt avg(final Function mapper) { return avg(mapper, 2); @@ -332,7 +332,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream */ public Opt avg(final Function mapper, int scale) { return avg(mapper, scale, RoundingMode.HALF_UP); @@ -344,7 +344,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 如果元素的长度为0 那么会返回为空的opt */ public Opt avg(final Function mapper, int scale, RoundingMode roundingMode) { //元素列表 @@ -362,7 +362,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { return stream.mapToInt(mapper).average(); @@ -406,9 +406,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream{@code - * accept(t) - * return this; - * } + * accept(t) + * return this; + * } */ default Builder add(final T t) { accept(t); diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index f44a0570a..5646d772f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -445,16 +445,17 @@ public class EasyStreamTest { public void testIntSumAndAvg() { //测试int类型的总和 int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue); - Assert.assertEquals(sum, 55); + Assert.assertEquals(55, sum); //测试为空 List integerList = new ArrayList<>(); int emptySum = EasyStream.of(integerList).sum(Integer::intValue); - Assert.assertEquals(emptySum, 0); + Assert.assertEquals(0, emptySum); //测试平均值 OptionalDouble avg = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).avg(Integer::intValue); - Assert.assertEquals(avg.getAsDouble(), 5.5, 2); + Assert.assertTrue(avg.isPresent()); + Assert.assertEquals(5.5, avg.getAsDouble(), 2); //测试元素为空 OptionalDouble emptyAvg = EasyStream.of(integerList).avg(Integer::intValue); @@ -466,17 +467,18 @@ public class EasyStreamTest { public void testDoubleSumAndAvg() { //测试double类型的sum double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue); - Assert.assertEquals(doubleSum, 59.6, 2); + Assert.assertEquals(59.6, doubleSum, 2); //测试double类型的sum 无元素double List doubleList = new ArrayList<>(); double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue); - Assert.assertEquals(emptySum, 0.0, 2); + Assert.assertEquals(0.0, emptySum, 2); //测试double类型的avg OptionalDouble doubleAvg = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10) .avg(Double::doubleValue); - Assert.assertEquals(doubleAvg.getAsDouble(), 5.96, 2); + Assert.assertTrue(doubleAvg.isPresent()); + Assert.assertEquals(5.96, doubleAvg.getAsDouble(), 2); //测试double类型的 空元素的avg OptionalDouble emptyDoubleAvg = EasyStream.of(doubleList).avg(Double::doubleValue); @@ -488,16 +490,17 @@ public class EasyStreamTest { public void testLongSumAndAvg() { //测试long类型的sum long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue); - Assert.assertEquals(sum, 55); + Assert.assertEquals(55, sum); //测试long类型的空元素 sum List longList = new ArrayList<>(); long emptySum = EasyStream.of(longList).sum(Long::longValue); - Assert.assertEquals(emptySum, 0L); + Assert.assertEquals(0L, emptySum); //测试long类型的avg OptionalDouble doubleAvg = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).avg(Long::longValue); - Assert.assertEquals(doubleAvg.getAsDouble(), 5.5, 2); + Assert.assertTrue(doubleAvg.isPresent()); + Assert.assertEquals(5.5, doubleAvg.getAsDouble(), 2); //测试long类型的avg 空元素 OptionalDouble emptyDoubleAvg = EasyStream.of(longList).avg(Long::longValue); @@ -513,34 +516,36 @@ public class EasyStreamTest { NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)).sum(Function.identity()); - Assert.assertEquals(sum, NumberUtil.toBigDecimal(59.6)); + Assert.assertEquals(NumberUtil.toBigDecimal(59.6), sum); //测试bigDecimal的sum 空元素 List bigDecimalEmptyList = new ArrayList<>(); BigDecimal emptySum = EasyStream.of(bigDecimalEmptyList).sum(Function.identity()); - Assert.assertEquals(emptySum, BigDecimal.ZERO); + Assert.assertEquals(BigDecimal.ZERO, emptySum); - //测试bigDecimal的avg + //测试bigDecimal的avg全参 Opt bigDecimalAvgFullParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) .avg(Function.identity(), 2, RoundingMode.HALF_UP); - Assert.assertEquals(bigDecimalAvgFullParam.get(), NumberUtil.toBigDecimal(5.96)); + Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgFullParam.get()); + //测试bigDecimal的avg双参 Opt bigDecimalAvgOneParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) .avg(Function.identity()); - Assert.assertEquals(bigDecimalAvgOneParam.get(), NumberUtil.toBigDecimal(5.96)); + Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgOneParam.get()); + //测试bigDecimal的avg单参 Opt bigDecimalAvgTwoParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) .avg(Function.identity(), 2); - Assert.assertEquals(bigDecimalAvgTwoParam.get(), NumberUtil.toBigDecimal(5.96)); + Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgTwoParam.get()); //测试bigDecimal的avg 空元素 Opt emptyBigDecimalAvg = EasyStream.of(bigDecimalEmptyList) From c6d6333cbcd3fc00f6620ef486ab5593cadc59a7 Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Mon, 13 Feb 2023 22:09:06 +0800 Subject: [PATCH 012/125] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 549911bc5..d5642c9cc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -309,7 +309,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { return stream.map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add); From 0a8e8d289306e938aee50f0a2bc799ced090e372 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Feb 2023 15:43:27 +0800 Subject: [PATCH 013/125] add test --- .../cn/hutool/db/dialect/DialectFactory.java | 5 +- .../hutool/db/dialect/DialectFactoryTest.java | 70 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100755 hutool-db/src/test/java/cn/hutool/db/dialect/DialectFactoryTest.java diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java index 390714b4c..44930824a 100755 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java @@ -106,6 +106,7 @@ public class DialectFactory implements DriverNamePool { if (nameContainsProductInfo.contains("mysql") || nameContainsProductInfo.contains("cobar")) { driver = ClassLoaderUtil.isPresent(DRIVER_MYSQL_V6, classLoader) ? DRIVER_MYSQL_V6 : DRIVER_MYSQL; } else if (nameContainsProductInfo.contains("mariadb")) { + // Mariadb driver = DRIVER_MARIADB; } else if (nameContainsProductInfo.contains("oracle")) { driver = ClassLoaderUtil.isPresent(DRIVER_ORACLE, classLoader) ? DRIVER_ORACLE : DRIVER_ORACLE_OLD; @@ -155,13 +156,13 @@ public class DialectFactory implements DriverNamePool { // 华为高斯 driver = DRIVER_GAUSS; } else if (nameContainsProductInfo.contains("gbase")) { - // 华为高斯 + // 南大通用数据库 driver = DRIVER_GBASE; } else if (nameContainsProductInfo.contains("oscar")) { // 神州数据库 driver = DRIVER_OSCAR; } else if (nameContainsProductInfo.contains("sybase")) { - // 神州数据库 + // Sybase driver = DRIVER_SYBASE; } else if (nameContainsProductInfo.contains("xugu")) { // 虚谷数据库 diff --git a/hutool-db/src/test/java/cn/hutool/db/dialect/DialectFactoryTest.java b/hutool-db/src/test/java/cn/hutool/db/dialect/DialectFactoryTest.java new file mode 100755 index 000000000..e2e4d4204 --- /dev/null +++ b/hutool-db/src/test/java/cn/hutool/db/dialect/DialectFactoryTest.java @@ -0,0 +1,70 @@ +package cn.hutool.db.dialect; + +import cn.hutool.core.util.RandomUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_CLICK_HOUSE; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_DB2; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_DERBY; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_DM7; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_GAUSS; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_GBASE; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_H2; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_HIGHGO; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_HIVE; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_HIVE2; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_HSQLDB; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_IGNITE_THIN; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_KINGBASE8; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_MARIADB; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_MYSQL_V6; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_ORACLE; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_OSCAR; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_PHOENIX; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_POSTGRESQL; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_SQLLITE3; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_SQLSERVER; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_SYBASE; +import static cn.hutool.db.dialect.DriverNamePool.DRIVER_XUGU; + +public class DialectFactoryTest { + + @Test + public void identifyDriverTest(){ + final Map map = new HashMap<>(25); + map.put("mysql",DRIVER_MYSQL_V6); + map.put("cobar",DRIVER_MYSQL_V6); + map.put("oracle",DRIVER_ORACLE); + map.put("postgresql",DRIVER_POSTGRESQL); + map.put("sqlite",DRIVER_SQLLITE3); + map.put("sqlserver",DRIVER_SQLSERVER); + map.put("microsoft",DRIVER_SQLSERVER); + map.put("hive2",DRIVER_HIVE2); + map.put("hive",DRIVER_HIVE); + map.put("h2",DRIVER_H2); + map.put("derby",DRIVER_DERBY); + map.put("hsqldb",DRIVER_HSQLDB); + map.put("dm",DRIVER_DM7); + map.put("kingbase8",DRIVER_KINGBASE8); + map.put("ignite",DRIVER_IGNITE_THIN); + map.put("clickhouse",DRIVER_CLICK_HOUSE); + map.put("highgo",DRIVER_HIGHGO); + map.put("db2",DRIVER_DB2); + map.put("xugu",DRIVER_XUGU); + map.put("phoenix",DRIVER_PHOENIX); + map.put("zenith",DRIVER_GAUSS); + map.put("gbase",DRIVER_GBASE); + map.put("oscar",DRIVER_OSCAR); + map.put("sybase",DRIVER_SYBASE); + map.put("mariadb",DRIVER_MARIADB); + + + map.forEach((k,v) -> Assert.assertEquals(v, + DialectFactory.identifyDriver(k+ RandomUtil.randomString(2),null) )); + + } +} From fca001acc8990b42ee428c34e0265691d2f5589a Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Feb 2023 15:49:38 +0800 Subject: [PATCH 014/125] fix code --- .../src/main/java/cn/hutool/db/dialect/DialectFactory.java | 3 --- .../src/main/java/cn/hutool/db/dialect/DriverNamePool.java | 4 ---- 2 files changed, 7 deletions(-) diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java index 44930824a..3bce8520a 100755 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectFactory.java @@ -164,9 +164,6 @@ public class DialectFactory implements DriverNamePool { } else if (nameContainsProductInfo.contains("sybase")) { // Sybase driver = DRIVER_SYBASE; - } else if (nameContainsProductInfo.contains("xugu")) { - // 虚谷数据库 - driver = DRIVER_XUGO; } return driver; diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/DriverNamePool.java b/hutool-db/src/main/java/cn/hutool/db/dialect/DriverNamePool.java index 56392945a..6da118859 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/DriverNamePool.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/DriverNamePool.java @@ -108,9 +108,5 @@ public interface DriverNamePool { * JDBC 驱动 Sybase */ String DRIVER_SYBASE = "com.sybase.jdbc4.jdbc.SybDriver"; - /** - * JDBC 驱动 虚谷 - */ - String DRIVER_XUGO = "com.xugu.cloudjdbc.Driver"; } From ec3a1b2519b6fcab60e69d285e6714d324048e74 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Feb 2023 16:28:03 +0800 Subject: [PATCH 015/125] fix code --- hutool-http/src/main/java/cn/hutool/http/GlobalHeaders.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hutool-http/src/main/java/cn/hutool/http/GlobalHeaders.java b/hutool-http/src/main/java/cn/hutool/http/GlobalHeaders.java index 2d3fcd114..2a5e4edb2 100644 --- a/hutool-http/src/main/java/cn/hutool/http/GlobalHeaders.java +++ b/hutool-http/src/main/java/cn/hutool/http/GlobalHeaders.java @@ -55,7 +55,9 @@ public enum GlobalHeaders { this.headers.clear(); } - header(Header.ACCEPT, "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", true); + //header(Header.ACCEPT, "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", true); + // 某些请求中这个自定义头会导致请求失败,此处采用与PostMan一致的默认头 + header(Header.ACCEPT, "*/*", true); header(Header.ACCEPT_ENCODING, "gzip, deflate", true); header(Header.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.8", true); // 此Header只有在post请求中有用,因此在HttpRequest的method方法中设置此头信息,此处去掉 From e2266f593f991e3dabaea7077d11e518988d086a Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Feb 2023 17:39:08 +0800 Subject: [PATCH 016/125] fix bug --- .../src/main/java/cn/hutool/core/io/file/PathUtil.java | 3 ++- .../test/java/cn/hutool/core/io/file/PathUtilTest.java | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 76888bffe..84eb66659 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -511,7 +511,8 @@ public class PathUtil { Assert.notNull(src, "Src path must be not null !"); Assert.notNull(target, "Target path must be not null !"); - if(equals(src, target)){ + // issue#2893 target 不存在导致NoSuchFileException + if(Files.exists(target) && equals(src, target)){ // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 return target; } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java index 215ce5f46..1f960aa92 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java @@ -78,4 +78,13 @@ public class PathUtilTest { final String contentType = FileUtil.getMimeType("a001.7z"); Assert.assertEquals("application/x-7z-compressed", contentType); } + + /** + * issue#2893 target不存在空导致异常 + */ + @Test + @Ignore + public void moveTest2(){ + PathUtil.move(Paths.get("D:\\project\\test1.txt"), Paths.get("D:\\project\\test2.txt"), false); + } } From 3b3871ba1e5a6e68a7c6975a1683caebdf2fd939 Mon Sep 17 00:00:00 2001 From: Zjp <1215582715@qq.com> Date: Wed, 15 Feb 2023 21:12:21 +0800 Subject: [PATCH 017/125] fix bug; --- .../src/main/java/cn/hutool/core/net/MaskBit.java | 3 ++- .../src/test/java/cn/hutool/core/net/Ipv4UtilTest.java | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java index 5b51c0c10..934a93180 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java @@ -2,6 +2,7 @@ package cn.hutool.core.net; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.BiMap; + import java.util.HashMap; /** @@ -83,6 +84,6 @@ public class MaskBit { */ public static long getMaskIpLong(final int maskBit) { Assert.isTrue(MASK_BIT_MAP.containsKey(maskBit), "非法的掩码位数:{}", maskBit); - return -1L << (32 - maskBit); + return (0xffffffffL << (32 - maskBit)) & 0xffffffffL; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java index 97497d5b4..9ccf674f8 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java @@ -121,7 +121,7 @@ public class Ipv4UtilTest { } @Test - public void ipv4ToLongTest(){ + public void ipv4ToLongTest() { long l = Ipv4Util.ipv4ToLong("127.0.0.1"); Assert.assertEquals(2130706433L, l); l = Ipv4Util.ipv4ToLong("114.114.114.114"); @@ -132,6 +132,13 @@ public class Ipv4UtilTest { Assert.assertEquals(4294967295L, l); } + @Test + public void getMaskIpLongTest() { + for (int i = 1; i <= 32; i++) { + Assert.assertEquals(Ipv4Util.ipv4ToLong(MaskBit.get(i)), MaskBit.getMaskIpLong(i)); + } + } + @SuppressWarnings("SameParameterValue") private void testGenerateIpList(final String fromIp, final String toIp) { Assert.assertEquals( From bfebc8bc0fdeaf7a830424c0c482709acd371328 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Thu, 16 Feb 2023 09:57:36 +0800 Subject: [PATCH 018/125] =?UTF-8?q?if=E6=94=B9=E6=88=90Assert.notNull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java index cc03082b3..7990cad8d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java @@ -310,9 +310,7 @@ public class EnumUtil { */ public static Map getNameFieldMap(final Class> clazz, final String fieldName) { final Enum[] enums = clazz.getEnumConstants(); - if (null == enums) { - throw new IllegalArgumentException(StrUtil.format("Class [{}] is not an Enum type!", clazz.getName())); - } + Assert.notNull(enums, "Enum clazz must be not null !"); final Map map = MapUtil.newHashMap(enums.length, true); for (final Enum e : enums) { map.put(e.name(), FieldUtil.getFieldValue(e, fieldName)); From 65239df0e499bf428cb8afa8752518d958606a64 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Thu, 16 Feb 2023 09:58:38 +0800 Subject: [PATCH 019/125] =?UTF-8?q?if=E6=94=B9=E6=88=90Assert.notNull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java index 7990cad8d..3f9e3fe51 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/EnumUtil.java @@ -310,7 +310,7 @@ public class EnumUtil { */ public static Map getNameFieldMap(final Class> clazz, final String fieldName) { final Enum[] enums = clazz.getEnumConstants(); - Assert.notNull(enums, "Enum clazz must be not null !"); + Assert.notNull(enums, "Class [{}] is not an Enum type!", clazz); final Map map = MapUtil.newHashMap(enums.length, true); for (final Enum e : enums) { map.put(e.name(), FieldUtil.getFieldValue(e, fieldName)); From f1f80c4258190a17765d5d2b45b0f29a2409a81e Mon Sep 17 00:00:00 2001 From: huangchengxing <841396397@qq.com> Date: Fri, 17 Feb 2023 18:17:04 +0800 Subject: [PATCH 020/125] =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E7=B1=BB=E6=94=AF=E6=8C=81=E4=BF=AE=E6=94=B9Hutool=E5=92=8CSpr?= =?UTF-8?q?ing=E5=90=88=E6=88=90=E6=B3=A8=E8=A7=A3=E7=9A=84=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/annotation/AnnotationUtil.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java index 2e5b13e51..e41272700 100755 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java @@ -9,6 +9,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.WeakConcurrentMap; import cn.hutool.core.reflect.FieldUtil; import cn.hutool.core.reflect.MethodUtil; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; @@ -21,6 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; @@ -38,6 +40,11 @@ import java.util.stream.Stream; */ public class AnnotationUtil { + private static final String JDK_MEMBER_ATTRIBUTE = "memberValues"; + private static final String SPRING_MEMBER_ATTRIBUTE = "valueCache"; + private static final String HUTOOL_MEMBER_ATTRIBUTE = "valueCache"; + private static final String SPRING_INVOCATION_HANDLER = "SynthesizedMergedAnnotationInvocationHandler"; + /** * 直接声明的注解缓存 */ @@ -323,9 +330,20 @@ public class AnnotationUtil { * @param value 要更新的属性值 * @since 5.5.2 */ - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void setValue(final Annotation annotation, final String annotationField, final Object value) { - final Map memberValues = (Map) FieldUtil.getFieldValue(Proxy.getInvocationHandler(annotation), "memberValues"); + @SuppressWarnings("unchecked") + public static void setValue( + final Annotation annotation, final String annotationField, final Object value) { + InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation); + String memberAttributeName = JDK_MEMBER_ATTRIBUTE; + // Spring合成注解 + if (CharSequenceUtil.contains(invocationHandler.getClass().getName(), SPRING_INVOCATION_HANDLER)) { + memberAttributeName = SPRING_MEMBER_ATTRIBUTE; + } + // Hutool合成注解 + else if (invocationHandler instanceof AnnotationMappingProxy) { + memberAttributeName = HUTOOL_MEMBER_ATTRIBUTE; + } + Map memberValues = (Map) FieldUtil.getFieldValue(invocationHandler, memberAttributeName); memberValues.put(annotationField, value); } From 30922016349034dfa419032171dcfa14165d7d2d Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Sun, 19 Feb 2023 15:14:06 +0800 Subject: [PATCH 021/125] =?UTF-8?q?=E6=8C=89=E7=85=A7=E8=B6=85=E5=93=A5?= =?UTF-8?q?=E6=95=99=E7=9A=84=20=E4=BD=BF=E7=94=A8number=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?decimal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/stream/EasyStream.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index d5642c9cc..fdd2d390c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -306,13 +306,13 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { - return stream.map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add); + public BigDecimal sum(final Function mapper) { + return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add,NumberUtil::add); } From faa1e1149469b263b639f03728aa378214f1f22c Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 19 Feb 2023 14:58:38 +0800 Subject: [PATCH 022/125] add ip constants; --- .../java/cn/hutool/core/net/Ipv4Pool.java | 440 ++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java new file mode 100644 index 000000000..409f01452 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java @@ -0,0 +1,440 @@ +package cn.hutool.core.net; + +/** + * Ip相关常量 + *

+ *

+ * 为了方便处理作出以下特别说明,若后续因此收到影响或有更好处理方式需要及时调整:
+ * 1、此处定义的`最小值`、`最大值`并非实际ip可分配的最小值、最大值。而是正常地址格式所能表示的最小值、最大值。
+ * 2、比如:1.0.0.0这种保留地址,我们仍然认为属于A类网。
+ * 3、类似于127.0.0.1这种本地回环地址,我们仍然认为数据C类网。
+ * 
+ * + * @author aoshiguchen + * @author emptypoint + * @since 6.0.0 + */ +public interface Ipv4Pool { + + /** + * IP段的分割符 + */ + String IP_SPLIT_MARK = "-"; + + /** + * IP与掩码的分割符 + */ + String IP_MASK_SPLIT_MARK = "/"; + + /** + * localhost默认解析的ip地址 + */ + String LOCAL_IP = "127.0.0.1"; + /** + * localhost默认解析的ip地址的数值形式 + */ + long LOCAL_IP_NUM = Ipv4Util.ipv4ToLong(LOCAL_IP); + + /** + * Ipv4地址最小值字符串形式 + */ + String IPV4_STR_MIN = "0.0.0.0"; + /** + * Ipv4最小值数值形式 + */ + long IPV4_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_STR_MIN); + + /** + * Ipv4地址最大值字符串形式 + */ + String IPV4_STR_MAX = "255.255.255.255"; + /** + * Ipv4最大值数值形式 + */ + long IPV4_NUM_MAX = 0xffffffffL; + + /** + * Ipv4未使用地址最小值字符串形式 + */ + String IPV4_UNUSED_STR_MIN = "0.0.0.0"; + /** + * Ipv4未使用地址最小值数值形式 + */ + long IPV4_UNUSED_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_UNUSED_STR_MIN); + + /** + * Ipv4未使用地址最大值字符串形式 + */ + String IPV4_UNUSED_STR_MAX = "0.255.255.255"; + /** + * Ipv4未使用地址最大值数值形式 + */ + long IPV4_UNUSED_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_UNUSED_STR_MAX); + + // region 子网掩码常量 + // ================================================== 子网掩码常量 ================================================== + /** + * Ipv4最小掩码位 + */ + int IPV4_MASK_BIT_MIN = 0; + + /** + * Ipv4有意义的最小掩码位 + */ + int IPV4_MASK_BIT_VALID_MIN = 1; + /** + * Ipv4有意义的最小掩码字符串 + */ + String IPV4_MASK_VALID_MIN = MaskBit.get(IPV4_MASK_BIT_VALID_MIN); + + /** + * Ipv4最大掩码位 + */ + int IPV4_MASK_BIT_MAX = 32; + /** + * Ipv4最大掩码字符串 + */ + String IPV4_MASK_MAX = MaskBit.get(IPV4_MASK_BIT_MAX); + // endregion + + // region 本地回环地址常量 + // ================================================== 本地回环地址常量 ================================================ + /** + * Ipv4 本地回环地址最小值字符串形式 + */ + String IPV4_LOOPBACK_STR_MIN = "127.0.0.0"; + /** + * Ipv4 本地回环地址最小值数值形式 + */ + long IPV4_LOOPBACK_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_LOOPBACK_STR_MIN); + /** + * Ipv4 本地回环地址最大值字符串形式 + */ + String IPV4_LOOPBACK_STR_MAX = "127.255.255.255"; + /** + * Ipv4 本地回环地址最大值数值形式 + */ + long IPV4_LOOPBACK_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_LOOPBACK_STR_MAX); + // endregion + + // region A类地址常量 + // ================================================== A类地址常量 ================================================== + /** + * Ipv4 A类地址最小值字符串形式 + */ + String IPV4_A_STR_MIN = "0.0.0.0"; + /** + * Ipv4 A类地址最小值数值形式 + */ + long IPV4_A_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_A_STR_MIN); + + /** + * Ipv4 A类地址最大值字符串形式 + */ + String IPV4_A_STR_MAX = "127.255.255.255"; + /** + * Ipv4 A类地址最大值数值形式 + */ + long IPV4_A_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_A_STR_MAX); + + /** + * Ipv4 A类地址第一个公网网段最小值字符串形式 + */ + String IPV4_A_PUBLIC_1_STR_MIN = "1.0.0.0"; + /** + * Ipv4 A类地址第一个公网网段最小值数值形式 + */ + long IPV4_A_PUBLIC_1_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_A_PUBLIC_1_STR_MIN); + + /** + * Ipv4 A类地址第一个公网网段最大值字符串形式 + */ + String IPV4_A_PUBLIC_1_STR_MAX = "9.255.255.255"; + /** + * Ipv4 A类地址第一个公网网段最大值数值形式 + */ + long IPV4_A_PUBLIC_1_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_A_PUBLIC_1_STR_MAX); + + /** + * Ipv4 A类地址私网网段最小值字符串形式 + */ + String IPV4_A_PRIVATE_STR_MIN = "10.0.0.0"; + /** + * Ipv4 A类地址私网网段最小值数值形式 + */ + long IPV4_A_PRIVATE_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_A_PRIVATE_STR_MIN); + + /** + * Ipv4 A类地址私网网段最大值字符串形式 + */ + String IPV4_A_PRIVATE_STR_MAX = "10.255.255.255"; + /** + * Ipv4 A类地址私网网段最大值数值形式 + */ + long IPV4_A_PRIVATE_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_A_PRIVATE_STR_MAX); + + /** + * Ipv4 A类地址第二个公网网段最小值字符串形式 + */ + String IPV4_A_PUBLIC_2_STR_MIN = "11.0.0.0"; + /** + * Ipv4 A类地址第二个公网网段最小值数值形式 + */ + long IPV4_A_PUBLIC_2_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_A_PUBLIC_2_STR_MIN); + + /** + * Ipv4 A类地址第二个公网网段最大值字符串形式 + */ + String IPV4_A_PUBLIC_2_STR_MAX = "126.255.255.255"; + /** + * Ipv4 A类地址第二个公网网段最大值数值形式 + */ + long IPV4_A_PUBLIC_2_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_A_PUBLIC_2_STR_MAX); + // endregion + + // region B类地址常量 + // ================================================== B类地址常量 ================================================== + /** + * Ipv4 B类地址最小值字符串形式 + */ + String IPV4_B_STR_MIN = "128.0.0.0"; + /** + * Ipv4 B类地址最小值数值形式 + */ + long IPV4_B_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_B_STR_MIN); + + /** + * Ipv4 B类地址最大值字符串形式 + */ + String IPV4_B_STR_MAX = "191.255.255.255"; + /** + * Ipv4 B类地址最大值数值形式 + */ + long IPV4_B_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_B_STR_MAX); + + /** + * Ipv4 B类地址第一个公网网段最小值字符串形式 + */ + String IPV4_B_PUBLIC_1_STR_MIN = "128.0.0.0"; + /** + * Ipv4 B类地址第一个公网网段最小值数值形式 + */ + long IPV4_B_PUBLIC_1_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_B_PUBLIC_1_STR_MIN); + + /** + * Ipv4 B类地址第一个公网网段最大值字符串形式 + */ + String IPV4_B_PUBLIC_1_STR_MAX = "172.15.255.255"; + /** + * Ipv4 B类地址第一个公网网段最大值数值形式 + */ + long IPV4_B_PUBLIC_1_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_B_PUBLIC_1_STR_MAX); + + /** + * Ipv4 B类地址私网网段最小值字符串形式 + */ + String IPV4_B_PRIVATE_STR_MIN = "172.16.0.0"; + /** + * Ipv4 B类地址私网网段最小值数值形式 + */ + long IPV4_B_PRIVATE_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_B_PRIVATE_STR_MIN); + + /** + * Ipv4 B类地址私网网段最大值字符串形式 + */ + String IPV4_B_PRIVATE_STR_MAX = "172.31.255.255"; + /** + * Ipv4 B类地址私网网段最大值数值形式 + */ + long IPV4_B_PRIVATE_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_B_PRIVATE_STR_MAX); + + /** + * Ipv4 B类地址第二个公网网段最小值字符串形式 + */ + String IPV4_B_PUBLIC_2_STR_MIN = "172.32.0.0"; + /** + * Ipv4 B类地址第二个公网网段最小值数值形式 + */ + long IPV4_B_PUBLIC_2_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_B_PUBLIC_2_STR_MIN); + + /** + * Ipv4 B类地址第二个公网网段最大值字符串形式 + */ + String IPV4_B_PUBLIC_2_STR_MAX = "191.255.255.255"; + /** + * Ipv4 B类地址第二个公网网段最大值数值形式 + */ + long IPV4_B_PUBLIC_2_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_B_PUBLIC_2_STR_MAX); + // endregion + + // region C类地址常量 + // ================================================== C类地址常量 ================================================== + /** + * Ipv4 C类地址最小值字符串形式 + */ + String IPV4_C_STR_MIN = "192.0.0.0"; + /** + * Ipv4 C类地址最小值数值形式 + */ + long IPV4_C_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_C_STR_MIN); + + /** + * Ipv4 C类地址最大值字符串形式 + */ + String IPV4_C_STR_MAX = "223.255.255.255"; + /** + * Ipv4 C类地址最大值数值形式 + */ + long IPV4_C_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_C_STR_MAX); + + /** + * Ipv4 C类地址第一个公网网段最小值字符串形式 + */ + String IPV4_C_PUBLIC_1_STR_MIN = "192.0.0.0"; + /** + * Ipv4 C类地址第一个公网网段最小值数值形式 + */ + long IPV4_C_PUBLIC_1_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_C_PUBLIC_1_STR_MIN); + + /** + * Ipv4 C类地址第一个公网网段最大值字符串形式 + */ + String IPV4_C_PUBLIC_1_STR_MAX = "192.167.255.255"; + /** + * Ipv4 C类地址第一个公网网段最大值数值形式 + */ + long IPV4_C_PUBLIC_1_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_C_PUBLIC_1_STR_MAX); + + /** + * Ipv4 C类地址私网网段最小值字符串形式 + */ + String IPV4_C_PRIVATE_STR_MIN = "192.168.0.0"; + /** + * Ipv4 C类地址私网网段最小值数值形式 + */ + long IPV4_C_PRIVATE_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_C_PRIVATE_STR_MIN); + + /** + * Ipv4 C类地址私网网段最大值字符串形式 + */ + String IPV4_C_PRIVATE_STR_MAX = "192.168.255.255"; + /** + * Ipv4 C类地址私网网段最大值数值形式 + */ + long IPV4_C_PRIVATE_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_C_PRIVATE_STR_MAX); + + /** + * Ipv4 C类地址第二个公网网段最小值字符串形式 + */ + String IPV4_C_PUBLIC_2_STR_MIN = "192.169.0.0"; + /** + * Ipv4 C类地址第二个公网网段最小值数值形式 + */ + long IPV4_C_PUBLIC_2_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_C_PUBLIC_2_STR_MIN); + + /** + * Ipv4 C类地址第二个公网网段最大值字符串形式 + */ + String IPV4_C_PUBLIC_2_STR_MAX = "223.255.255.255"; + /** + * Ipv4 C类地址第二个公网网段最大值数值形式 + */ + long IPV4_C_PUBLIC_2_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_C_PUBLIC_2_STR_MAX); + // endregion + + // region D类地址常量 + // ================================================== D类地址常量 ================================================== + /** + * Ipv4 D类地址最小值字符串形式 + */ + String IPV4_D_STR_MIN = "224.0.0.0"; + /** + * Ipv4 D类地址最小值数值形式 + */ + long IPV4_D_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_D_STR_MIN); + + /** + * Ipv4 D类地址最大值字符串形式 + */ + String IPV4_D_STR_MAX = "239.255.255.255"; + /** + * Ipv4 D类地址最大值数值形式 + */ + long IPV4_D_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_D_STR_MAX); + + /** + * Ipv4 D类地址专用网段(用于广播)最小值字符串形式 + */ + String IPV4_D_DEDICATED_STR_MIN = "224.0.0.0"; + /** + * Ipv4 D类地址专用网段(用于广播)最小值数值形式 + */ + long IPV4_D_DEDICATED_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_D_DEDICATED_STR_MIN); + + /** + * Ipv4 D类地址专用网段(用于广播)最大值字符串形式 + */ + String IPV4_D_DEDICATED_STR_MAX = "224.0.0.255"; + /** + * Ipv4 D类地址专用网段(用于广播)最大值数值形式 + */ + long IPV4_D_DEDICATED_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_D_DEDICATED_STR_MAX); + + /** + * Ipv4 D类地址公用网段(用于组播)最小值字符串形式 + */ + String IPV4_D_PUBLIC_STR_MIN = "224.0.1.0"; + /** + * Ipv4 D类地址公用网段(用于组播)最小值数值形式 + */ + long IPV4_D_PUBLIC_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_D_PUBLIC_STR_MIN); + + /** + * Ipv4 D类地址公用网段(用于组播)最大值字符串形式 + */ + String IPV4_D_PUBLIC_STR_MAX = "238.255.255.255"; + /** + * Ipv4 D类地址公用网段(用于组播)最大值数值形式 + */ + long IPV4_D_PUBLIC_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_D_PUBLIC_STR_MAX); + + /** + * Ipv4 D类地址私用网段(用于测试)最小值字符串形式 + */ + String IPV4_D_PRIVATE_STR_MIN = "239.0.0.0"; + /** + * Ipv4 D类地址私用网段(用于测试)最小值数值形式 + */ + long IPV4_D_PRIVATE_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_D_PRIVATE_STR_MIN); + + /** + * Ipv4 D类地址私用网段(用于测试)最大值字符串形式 + */ + String IPV4_D_PRIVATE_STR_MAX = "239.255.255.255"; + /** + * Ipv4 D类地址私用网段(用于测试)最大值数值形式 + */ + long IPV4_D_PRIVATE_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_D_PRIVATE_STR_MAX); + // endregion + + // region E类地址常量 + // ================================================== E类地址常量 ================================================== + /** + * Ipv4 E类地址最小值字符串形式 + */ + String IPV4_E_STR_MIN = "240.0.0.0"; + /** + * Ipv4 E类地址最小值数值形式 + */ + long IPV4_E_NUM_MIN = Ipv4Util.ipv4ToLong(IPV4_E_STR_MIN); + + /** + * Ipv4 E类地址最大值字符串形式 + */ + String IPV4_E_STR_MAX = "255.255.255.255"; + /** + * Ipv4 E类地址最大值数值形式 + */ + long IPV4_E_NUM_MAX = Ipv4Util.ipv4ToLong(IPV4_E_STR_MAX); + // endregion +} From ba944f854ac799ac0f903cc72a13101a528f6ab2 Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 19 Feb 2023 15:08:15 +0800 Subject: [PATCH 023/125] add method; --- .../java/cn/hutool/core/net/Ipv4Util.java | 194 +++++++++--------- .../java/cn/hutool/core/net/Ipv4UtilTest.java | 23 ++- 2 files changed, 115 insertions(+), 102 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index 617a3b0ed..ac992a443 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -29,64 +29,10 @@ import java.util.regex.Matcher; * * @author ZhuKun * @author emptypoint + * @author aoshiguchen * @since 5.4.1 */ -public class Ipv4Util { - - /** - * 本地IP:127.0.0.1 - */ - public static final String LOCAL_IP = "127.0.0.1"; - - /** - * IP段的分割符 - */ - public static final String IP_SPLIT_MARK = "-"; - - /** - * IP与掩码的分割符 - */ - public static final String IP_MASK_SPLIT_MARK = StrUtil.SLASH; - - /** - * 最大掩码位 - */ - public static final int IP_MASK_MAX = 32; - - /** - * 最小掩码位 - */ - public static final int IP_MASK_MIN = 1; - - /** - * A类私有地址的最小值 - */ - public static final long A_INNER_IP_LONG_BEGIN = ipv4ToLong("10.0.0.0"); - - /** - * A类私有地址的最大值 - */ - public static final long A_INNER_IP_LONG_END = ipv4ToLong("10.255.255.255"); - - /** - * B类私有地址的最小值 - */ - public static final long B_INNER_IP_LONG_BEGIN = ipv4ToLong("172.16.0.0"); - - /** - * B类私有地址的最大值 - */ - public static final long B_INNER_IP_LONG_END = ipv4ToLong("172.31.255.255"); - - /** - * C类私有地址的最小值 - */ - public static final long C_INNER_IP_LONG_BEGIN = ipv4ToLong("192.168.0.0"); - - /** - * C类私有地址的最大值 - */ - public static final long C_INNER_IP_LONG_END = ipv4ToLong("192.168.255.255"); +public class Ipv4Util implements Ipv4Pool { /** * 根据 ip地址 和 掩码地址 获得 CIDR格式字符串 @@ -135,7 +81,7 @@ public class Ipv4Util { return new ArrayList<>(0); } - if (maskBit == IP_MASK_MAX) { + if (maskBit == IPV4_MASK_BIT_MAX) { final List list = new ArrayList<>(isAll ? 1 : 0); if (isAll) { list.add(ip); @@ -311,25 +257,26 @@ public class Ipv4Util { /** * 获取 子网内的 地址总数 * - * @param maskBit 掩码位,取值范围:[2, {@link #IP_MASK_MAX}] + * @param maskBit 掩码位,取值范围:({@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] * @param isAll true:全量地址,false:可用地址 * @return 子网内地址总数 */ public static int countByMaskBit(final int maskBit, final boolean isAll) { - assertMaskBitValid(maskBit); + Assert.isTrue(maskBit > IPV4_MASK_BIT_VALID_MIN && maskBit <= IPV4_MASK_BIT_MAX, + "Not support mask bit: {}", maskBit); //如果掩码位等于32,则可用地址为0 - if (maskBit == 32 && false == isAll) { + if (maskBit == IPV4_MASK_BIT_MAX && false == isAll) { return 0; } - final int count = 1 << (32 - maskBit); + final int count = 1 << (IPV4_MASK_BIT_MAX - maskBit); return isAll ? count : count - 2; } /** * 根据 掩码位 获取 掩码地址 * - * @param maskBit 掩码位,如:24,取值范围:[{@link #IP_MASK_MIN}, {@link #IP_MASK_MAX}] + * @param maskBit 掩码位,如:24,取值范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] * @return 掩码地址,点分十进制,如:255.255.255.0 */ public static String getMaskByMaskBit(final int maskBit) { @@ -400,11 +347,11 @@ public class Ipv4Util { /** * 判断掩码位是否合法 * - * @param maskBit 掩码位,有效范围:[{@link #IP_MASK_MIN}, {@link #IP_MASK_MAX}] + * @param maskBit 掩码位,有效范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] * @return true:掩码位合法;false:掩码位不合法 */ public static boolean isMaskBitValid(final int maskBit) { - return maskBit >= IP_MASK_MIN && maskBit <= IP_MASK_MAX; + return maskBit >= IPV4_MASK_BIT_VALID_MIN && maskBit <= IPV4_MASK_BIT_MAX; } /** @@ -422,13 +369,88 @@ public class Ipv4Util { * @since 5.7.18 */ public static boolean isInnerIP(final String ipAddress) { - final long ipNum = ipv4ToLong(ipAddress); - return isBetween(ipNum, A_INNER_IP_LONG_BEGIN, A_INNER_IP_LONG_END) - || isBetween(ipNum, B_INNER_IP_LONG_BEGIN, B_INNER_IP_LONG_END) - || isBetween(ipNum, C_INNER_IP_LONG_BEGIN, C_INNER_IP_LONG_END) - || LOCAL_IP.equals(ipAddress); + return isInnerIP(ipv4ToLong(ipAddress)); } + /** + * 是否为内网地址 + * + * @param ipNum IP地址数值形式 + * @return 是否为内网IP + * @see #isInnerIP(String) + * @since 6.0.0 + */ + public static boolean isInnerIP(final long ipNum) { + return isBetween(ipNum, IPV4_A_PRIVATE_NUM_MIN, IPV4_A_PRIVATE_NUM_MAX) + || isBetween(ipNum, IPV4_B_PRIVATE_NUM_MIN, IPV4_B_PRIVATE_NUM_MAX) + || isBetween(ipNum, IPV4_C_PRIVATE_NUM_MIN, IPV4_C_PRIVATE_NUM_MAX) + || LOCAL_IP_NUM == ipNum; + } + + /** + * 是否为公网地址 + *

+ * 公网IP: + *

+	 * A类 1.0.0.0-9.255.255.255,11.0.0.0-126.255.255.255
+	 * B类 128.0.0.0-172.15.255.255,172.32.0.0-191.255.255.255
+	 * C类 192.0.0.0-192.167.255.255,192.169.0.0-223.255.255.255
+	 * 
+ * + * @param ipAddress IP地址,点分十进制 + * @return 是否为公网IP + * @since 6.0.0 + */ + public static boolean isPublicIP(final String ipAddress) { + return isPublicIP(ipv4ToLong(ipAddress)); + } + + /** + * 是否为公网地址 + * + * @param ipNum IP地址数值形式 + * @return 是否为公网IP + * @see #isPublicIP(String) + * @since 6.0.0 + */ + public static boolean isPublicIP(final long ipNum) { + return isBetween(ipNum, IPV4_A_PUBLIC_1_NUM_MIN, IPV4_A_PUBLIC_1_NUM_MAX) + || isBetween(ipNum, IPV4_A_PUBLIC_2_NUM_MIN, IPV4_A_PUBLIC_2_NUM_MAX) + || isBetween(ipNum, IPV4_B_PUBLIC_1_NUM_MIN, IPV4_B_PUBLIC_1_NUM_MAX) + || isBetween(ipNum, IPV4_B_PUBLIC_2_NUM_MIN, IPV4_B_PUBLIC_2_NUM_MAX) + || isBetween(ipNum, IPV4_C_PUBLIC_1_NUM_MIN, IPV4_C_PUBLIC_1_NUM_MAX) + || isBetween(ipNum, IPV4_C_PUBLIC_2_NUM_MIN, IPV4_C_PUBLIC_2_NUM_MAX); + } + + /** + * 获取ip(Long类型)指定部分的十进制值,即,{@literal X.X.X.X }形式中每个部分的值 + *

例如,ip为{@literal 0xC0A802FA},第1部分的值为: + *

    + *
  • 第1部分的值为:{@literal 0xC0},十进制值为:192
  • + *
  • 第2部分的值为:{@literal 0xA8},十进制值为:168
  • + *
  • 第3部分的值为:{@literal 0x02},十进制值为:2
  • + *
  • 第4部分的值为:{@literal 0xFA},十进制值为:250
  • + *
+ * + * @param ip ip地址,Long类型 + * @param position 指定位置,取值范围:[1,4] + * @return ip地址指定部分的十进制值 + * @since 6.0.0 + */ + public static int getPartOfIpLong(final long ip, final int position) { + switch (position) { + case 1: + return ((int) ip >> 24) & 0xFF; + case 2: + return ((int) ip >> 16) & 0xFF; + case 3: + return ((int) ip >> 8) & 0xFF; + case 4: + return ((int) ip) & 0xFF; + default: + throw new IllegalArgumentException("Illegal position of ip Long: " + position); + } + } //-------------------------------------------------------------------------------- Private method start /** @@ -446,7 +468,7 @@ public class Ipv4Util { } // int的最高位无法直接使用,转为Long if (addr < 0) { - return 0xffffffffL & addr; + return IPV4_NUM_MAX & addr; } return addr; } @@ -464,42 +486,12 @@ public class Ipv4Util { } /** - * 校验 掩码位数,合法范围为:[1,32],不合法则抛出异常 + * 校验 掩码位数,合法范围为:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}],不合法则抛出异常 * * @param maskBit 掩码位数 */ private static void assertMaskBitValid(final int maskBit) { Assert.isTrue(isMaskBitValid(maskBit), "Invalid maskBit:{}", maskBit); } - - /** - * 获取ip(Long类型)指定部分的十进制值,即,{@literal X.X.X.X }形式中每个部分的值 - *

例如,ip为{@literal 0xC0A802FA},第1部分的值为: - *

    - *
  • 第1部分的值为:@literal 0xC0},十进制值为:192
  • - *
  • 第2部分的值为:@literal 0xA8},十进制值为:168
  • - *
  • 第3部分的值为:@literal 0x02},十进制值为:2
  • - *
  • 第4部分的值为:@literal 0xFA},十进制值为:250
  • - *
- *

- * - * @param ip ip地址,Long类型 - * @param position 指定位置,取值范围:[1,4] - * @return ip地址指定部分的十进制值 - */ - private static int getPartOfIpLong(final long ip, final int position) { - switch (position) { - case 1: - return ((int) ip >> 24) & 0xFF; - case 2: - return ((int) ip >> 16) & 0xFF; - case 3: - return ((int) ip >> 8) & 0xFF; - case 4: - return ((int) ip) & 0xFF; - default: - throw new IllegalArgumentException("Illegal position of ip Long: " + position); - } - } //-------------------------------------------------------------------------------- Private method end } diff --git a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java index 97497d5b4..f866bd13a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java @@ -148,10 +148,31 @@ public class Ipv4UtilTest { ); } - private static void testLongToIp(final String ip){ + private static void testLongToIp(final String ip) { final long ipLong = Ipv4Util.ipv4ToLong(ip); final String ipv4 = Ipv4Util.longToIpv4(ipLong); Assert.assertEquals(ip, ipv4); } + @Test + public void isInnerTest() { + Assert.assertTrue(Ipv4Util.isInnerIP(Ipv4Util.LOCAL_IP)); + Assert.assertTrue(Ipv4Util.isInnerIP("192.168.5.12")); + Assert.assertTrue(Ipv4Util.isInnerIP("172.20.10.1")); + + Assert.assertFalse(Ipv4Util.isInnerIP("180.10.2.5")); + Assert.assertFalse(Ipv4Util.isInnerIP("192.160.10.3")); + } + + @Test + public void isPublicTest() { + Assert.assertTrue(Ipv4Util.isPublicIP("180.10.2.5")); + Assert.assertTrue(Ipv4Util.isPublicIP("192.160.10.3")); + + Assert.assertFalse(Ipv4Util.isPublicIP(Ipv4Util.LOCAL_IP)); + Assert.assertFalse(Ipv4Util.isPublicIP("192.168.5.12")); + Assert.assertFalse(Ipv4Util.isPublicIP("127.0.0.1")); + Assert.assertFalse(Ipv4Util.isPublicIP("172.20.10.1")); + } + } From ec86b8ed443c4a6077d969b98beec6a4a77b99c1 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Sun, 19 Feb 2023 20:03:42 +0800 Subject: [PATCH 024/125] =?UTF-8?q?=E4=BF=AE=E5=A4=8Djavadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/stream/EasyStream.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index fdd2d390c..032c4fd3b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -309,6 +309,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 映射后的类型 * @return {@link BigDecimal} */ public BigDecimal sum(final Function mapper) { @@ -320,7 +321,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 如果元素的长度为0 那么会返回为空的opt + * @return 计算结果 如果元素的长度为0 那么会返回为空的opt */ public Opt avg(final Function mapper) { return avg(mapper, 2); @@ -332,7 +333,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream + * @return 计算结果 如果元素的长度为0 那么会返回为空的opt */ public Opt avg(final Function mapper, int scale) { return avg(mapper, scale, RoundingMode.HALF_UP); @@ -344,7 +345,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 如果元素的长度为0 那么会返回为空的opt + * @return 计算结果 如果元素的长度为0 那么会返回为空的opt */ public Opt avg(final Function mapper, int scale, RoundingMode roundingMode) { //元素列表 From 76e742ec0c506709e6804660f44568ae95184a3e Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 20 Feb 2023 09:49:29 +0800 Subject: [PATCH 025/125] add test --- .../hutool/core/reflect/MethodUtilTest.java | 30 +++++++++++++++++++ hutool-extra/pom.xml | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/reflect/MethodUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/reflect/MethodUtilTest.java index 1198aa049..cdd713d2f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/reflect/MethodUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/reflect/MethodUtilTest.java @@ -6,6 +6,7 @@ import cn.hutool.core.lang.test.bean.ExamInfoDict; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.SystemUtil; +import lombok.Data; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -216,4 +217,33 @@ public class MethodUtilTest { } } } + + @Data + static class TestClass { + private int a; + } + + @Test + public void invokeMethodTest() { + final TestClass testClass = new TestClass(); + final Method method = MethodUtil.getMethod(TestClass.class, "setA", int.class); + MethodUtil.invoke(testClass, method, 10); + Assert.assertEquals(10, testClass.getA()); + } + + @Test + public void invokeMethodWithParamConvertTest() { + final TestClass testClass = new TestClass(); + final Method method = MethodUtil.getMethod(TestClass.class, "setA", int.class); + MethodUtil.invoke(testClass, method, "10"); + Assert.assertEquals(10, testClass.getA()); + } + + @Test + public void invokeMethodWithParamConvertFailedTest() { + final TestClass testClass = new TestClass(); + final Method method = MethodUtil.getMethod(TestClass.class, "setA", int.class); + Assert.assertThrows(IllegalArgumentException.class, + () -> MethodUtil.invoke(testClass, method, "NaN")); + } } diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index b3fe50e70..d03fe8fe1 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -479,7 +479,7 @@ com.alibaba QLExpress - 3.3.0 + 3.3.1 compile true From d6355bb241a76137ff4a7dd5be261cddeb654c7d Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 20 Feb 2023 10:22:01 +0800 Subject: [PATCH 026/125] add test --- .../cn/hutool/core/text/finder/LengthFinder.java | 1 + .../java/cn/hutool/core/text/SplitUtilTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100755 hutool-core/src/test/java/cn/hutool/core/text/SplitUtilTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java b/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java index e8646f27c..be20641b1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java @@ -19,6 +19,7 @@ public class LengthFinder extends TextFinder { * @param length 长度 */ public LengthFinder(final int length) { + Assert.isTrue(length > 0, "Length must be great than 0"); this.length = length; } diff --git a/hutool-core/src/test/java/cn/hutool/core/text/SplitUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/SplitUtilTest.java new file mode 100755 index 000000000..096f26bd3 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/text/SplitUtilTest.java @@ -0,0 +1,15 @@ +package cn.hutool.core.text; + +import cn.hutool.core.text.split.SplitUtil; +import org.junit.Assert; +import org.junit.Test; + +public class SplitUtilTest { + + @Test + public void issueI6FKSITest(){ + // issue:I6FKSI + Assert.assertThrows(IllegalArgumentException.class, () -> SplitUtil.splitByLength("test length 0", 0)); + } + +} From a7598322597b7e2699e7882c0dc02c3e27f5c39d Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 21 Feb 2023 11:50:06 +0800 Subject: [PATCH 027/125] fix bugf --- .../main/java/cn/hutool/core/lang/Validator.java | 3 ++- .../src/main/java/cn/hutool/core/regex/ReUtil.java | 13 ++----------- .../test/java/cn/hutool/core/util/ReUtilTest.java | 9 +++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java b/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java index fa01f02c9..e1aa07a59 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java @@ -3,6 +3,7 @@ package cn.hutool.core.lang; import cn.hutool.core.date.DateUtil; import cn.hutool.core.exceptions.ValidateException; import cn.hutool.core.regex.PatternPool; +import cn.hutool.core.regex.RegexPool; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CreditCodeUtil; import cn.hutool.core.math.NumberUtil; @@ -915,7 +916,7 @@ public class Validator { * @since 5.2.1 */ public static boolean hasChinese(final CharSequence value) { - return ReUtil.contains(ReUtil.RE_CHINESES, value); + return ReUtil.contains(RegexPool.CHINESES, value); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java index 065804671..87ec9b9f0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java @@ -33,15 +33,6 @@ import java.util.regex.Pattern; */ public class ReUtil { - /** - * 正则表达式匹配中文汉字 - */ - public final static String RE_CHINESE = RegexPool.CHINESE; - /** - * 正则表达式匹配中文字符串 - */ - public final static String RE_CHINESES = RegexPool.CHINESES; - /** * 正则中需要被转义的关键字 */ @@ -459,7 +450,7 @@ public class ReUtil { * @return 删除后剩余的内容 */ public static String delAll(final String regex, final CharSequence content) { - if (StrUtil.hasBlank(regex, content)) { + if (StrUtil.hasEmpty(regex, content)) { return StrUtil.str(content); } @@ -475,7 +466,7 @@ public class ReUtil { * @return 删除后剩余的内容 */ public static String delAll(final Pattern pattern, final CharSequence content) { - if (null == pattern || StrUtil.isBlank(content)) { + if (null == pattern || StrUtil.isEmpty(content)) { return StrUtil.str(content); } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java index 41c9c0db3..1635d2ad2 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java @@ -14,6 +14,7 @@ import java.util.Map; import java.util.regex.Pattern; public class ReUtilTest { + static final String content = "ZZZaaabbbccc中文1234"; @Test @@ -56,6 +57,7 @@ public class ReUtilTest { Assert.assertEquals("公斤",ReUtil.delLast("\\d+", word)); Assert.assertEquals("公斤",ReUtil.delLast(PatternPool.NUMBERS, word)); //去除汉字 + //noinspection UnnecessaryUnicodeEscape Assert.assertEquals("180",ReUtil.delLast("[\u4E00-\u9FFF]+", word)); Assert.assertEquals("180",ReUtil.delLast(PatternPool.CHINESES, word)); @@ -66,6 +68,7 @@ public class ReUtilTest { Assert.assertEquals("10.商品KLS100021型号xxl适合身高180体重斤的用户", s); //多个匹配删除最后一个 判断是否不在包含最后的数字 + //noinspection UnnecessaryUnicodeEscape Assert.assertFalse(ReUtil.delLast("[\u4E00-\u9FFF]+", sentence).contains("斤的用户")); Assert.assertFalse(ReUtil.delLast(PatternPool.CHINESES, sentence).contains("斤的用户")); } @@ -96,6 +99,7 @@ public class ReUtilTest { @Test public void isMatchTest() { // 给定字符串是否匹配给定正则 + //noinspection UnnecessaryUnicodeEscape final boolean isMatch = ReUtil.isMatch("\\w+[\u4E00-\u9FFF]+\\d+", content); Assert.assertTrue(isMatch); } @@ -227,4 +231,9 @@ public class ReUtilTest { final String s = ReUtil.replaceAll("1.2.3.4", patternIp, "$1.**.**.$10"); Assert.assertEquals("1.**.**.4", s); } + + @Test + public void issueI6GIMTTest(){ + Assert.assertEquals(StrUtil.EMPTY, ReUtil.delAll("[\\s]*", " ")); + } } From dbb79f2edfb2e7e1aa09e3430faf4de0f8743e36 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 21 Feb 2023 11:52:22 +0800 Subject: [PATCH 028/125] fix bug --- .../src/main/java/cn/hutool/core/io/file/Tailer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java b/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java index 3bd690fce..4b9410388 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java @@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUnit; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.lang.func.SerConsumer; import cn.hutool.core.util.CharUtil; @@ -140,7 +141,11 @@ public class Tailer implements Serializable { * 结束,此方法需在异步模式或 */ public void stop(){ - this.executorService.shutdown(); + try{ + this.executorService.shutdown(); + } finally { + IoUtil.close(this.randomAccessFile); + } } // ---------------------------------------------------------------------------------------- Private method start From dde6b356ef2bc89100449ad506869ff392099670 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 21 Feb 2023 16:02:11 +0800 Subject: [PATCH 029/125] add test --- .../cn/hutool/core/convert/ConvertTest.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java index 3c6b9ff74..96db50c8e 100755 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java @@ -90,21 +90,21 @@ public class ConvertTest { @Test public void toStrTest5() { // 被转化的对象有值,正常转换 - String a = "aaaa"; - String aDefaultValue = "aDefault"; - String aResult = Convert.toStr(a, aDefaultValue); + final String a = "aaaa"; + final String aDefaultValue = "aDefault"; + final String aResult = Convert.toStr(a, aDefaultValue); Assert.assertEquals(aResult, a); // 被转化的对象为null,返回默认值 - String b = null; - String bDefaultValue = "bDefault"; - String bResult = Convert.toStr(b, bDefaultValue); + final String b = null; + final String bDefaultValue = "bDefault"; + final String bResult = Convert.toStr(b, bDefaultValue); Assert.assertEquals(bResult, bDefaultValue); // 转换失败,返回默认值 - TestExceptionClass c = new TestExceptionClass(); - String cDefaultValue = "cDefault"; - String cResult = Convert.toStr(c, cDefaultValue); + final TestExceptionClass c = new TestExceptionClass(); + final String cDefaultValue = "cDefault"; + final String cResult = Convert.toStr(c, cDefaultValue); Assert.assertEquals(cResult, cDefaultValue); } @@ -444,4 +444,11 @@ public class ConvertTest { final String s = Convert.toDBC(null); Assert.assertNull(s); } + + @Test + public void convertQuietlyTest(){ + final String a = "12"; + final Object s = Convert.convertQuietly(int.class, a, a); + Assert.assertEquals(12, s); + } } From d3f29fad02c6c39bf6a341a2ff1bb715e9db8944 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 22 Feb 2023 19:20:03 +0800 Subject: [PATCH 030/125] fix bug --- .../core/bean/copier/MapToBeanCopier.java | 13 +----------- .../cn/hutool/core/bean/BeanUtilTest.java | 7 +++++-- .../java/cn/hutool/json/IssueI6H0XFTest.java | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 hutool-json/src/test/java/cn/hutool/json/IssueI6H0XFTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java index 7547671a3..f1e978675 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/MapToBeanCopier.java @@ -115,17 +115,6 @@ public class MapToBeanCopier extends AbsCopier, T> { // 转驼峰尝试查找 sKeyStr = StrUtil.toCamelCase(sKeyStr); propDesc = targetPropDescMap.get(sKeyStr); - if(null != propDesc){ - return propDesc; - } - - // boolean类型参数名转换尝试查找 - if(sKeyStr.startsWith("is")){ - sKeyStr = StrUtil.removePreAndLowerFirst(sKeyStr, 2); - propDesc = targetPropDescMap.get(sKeyStr); - return propDesc; - } - - return null; + return propDesc; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index b942451d0..aef2b879d 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -261,8 +261,11 @@ public class BeanUtilTest { final SubPersonWithAlias subPersonWithAlias = BeanUtil.toBean(map, SubPersonWithAlias.class); Assert.assertEquals("sub名字", subPersonWithAlias.getSubName()); - Assert.assertTrue(subPersonWithAlias.isBooleana()); - Assert.assertEquals(true, subPersonWithAlias.getBooleanb()); + + // https://gitee.com/dromara/hutool/issues/I6H0XF + // is_booleana并不匹配booleana字段 + Assert.assertFalse(subPersonWithAlias.isBooleana()); + Assert.assertNull(subPersonWithAlias.getBooleanb()); } @Test diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI6H0XFTest.java b/hutool-json/src/test/java/cn/hutool/json/IssueI6H0XFTest.java new file mode 100644 index 000000000..a77e680b6 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI6H0XFTest.java @@ -0,0 +1,20 @@ +package cn.hutool.json; + +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +public class IssueI6H0XFTest { + + @Test + public void toBeanTest(){ + final Demo demo = JSONUtil.toBean("{\"biz\":\"A\",\"isBiz\":true}", Demo.class); + Assert.assertEquals("A", demo.getBiz()); + Assert.assertEquals("{\"biz\":\"A\"}", JSONUtil.toJsonStr(demo)); + } + + @Data + static class Demo { + String biz; + } +} From c105ebf740025b51e2930852962e7dbd8e9e24fd Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 10:09:28 +0800 Subject: [PATCH 031/125] fix code --- .../java/cn/hutool/core/lang/func/LambdaUtil.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java index 15f942687..43bb2733b 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java @@ -140,7 +140,8 @@ public class LambdaUtil { * @param getter方法返回值类型 * @return Obj::getXxx */ - public static Function buildGetter(Method getMethod) { + @SuppressWarnings("unchecked") + public static Function buildGetter(final Method getMethod) { return LambdaFactory.build(Function.class, getMethod); } @@ -153,7 +154,8 @@ public class LambdaUtil { * @param getter方法返回值类型 * @return Obj::getXxx */ - public static Function buildGetter(Class clazz, String fieldName) { + @SuppressWarnings("unchecked") + public static Function buildGetter(final Class clazz, final String fieldName) { return LambdaFactory.build(Function.class, BeanUtil.getBeanDesc(clazz).getGetter(fieldName)); } @@ -165,7 +167,8 @@ public class LambdaUtil { * @param

setter方法返回的值类型 * @return Obj::setXxx */ - public static BiConsumer buildSetter(Method setMethod) { + @SuppressWarnings("unchecked") + public static BiConsumer buildSetter(final Method setMethod) { return LambdaFactory.build(BiConsumer.class, setMethod); } @@ -178,7 +181,8 @@ public class LambdaUtil { * @param

setter方法返回的值类型 * @return Obj::setXxx */ - public static BiConsumer buildSetter(Class clazz, String fieldName) { + @SuppressWarnings("unchecked") + public static BiConsumer buildSetter(final Class clazz, final String fieldName) { return LambdaFactory.build(BiConsumer.class, BeanUtil.getBeanDesc(clazz).getSetter(fieldName)); } @@ -192,7 +196,7 @@ public class LambdaUtil { * @param 函数式接口类型 * @return Obj::method */ - public static F build(Class lambdaType, Class clazz, String methodName, Class... paramsTypes) { + public static F build(final Class lambdaType, final Class clazz, final String methodName, final Class... paramsTypes) { return LambdaFactory.build(lambdaType, clazz, methodName, paramsTypes); } From 56aed3ba3ac2975f78c38410c51fa8c63a1162dc Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 10:20:31 +0800 Subject: [PATCH 032/125] fix code --- .../src/main/java/cn/hutool/core/reflect/LookupFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java index eae5f1bdb..a40b47137 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java @@ -11,7 +11,8 @@ import java.lang.reflect.Method; * {@link MethodHandles.Lookup}工厂,用于创建{@link MethodHandles.Lookup}对象
* jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 - * + * + *

* 参考: *

https://blog.csdn.net/u013202238/article/details/108687086

* From 4842974b0dc972f41cc401f94e5bd9b671b14c75 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 11:05:31 +0800 Subject: [PATCH 033/125] add test --- .../main/java/cn/hutool/core/lang/Assert.java | 43 ++---- .../cn/hutool/core/reflect/LookupFactory.java | 2 +- .../java/cn/hutool/core/lang/AssertTest.java | 142 +++++++++++++++++- 3 files changed, 152 insertions(+), 35 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java b/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java index 350b9bb65..e51a04738 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java @@ -144,7 +144,6 @@ public class Assert { /** * 断言对象是否为{@code null} ,如果不为{@code null} 抛出{@link IllegalArgumentException} 异常 - * *
 	 * Assert.isNull(value, "The value must be null");
 	 * 
@@ -160,7 +159,6 @@ public class Assert { /** * 断言对象是否为{@code null} ,如果不为{@code null} 抛出{@link IllegalArgumentException} 异常 - * *
 	 * Assert.isNull(value);
 	 * 
@@ -201,7 +199,6 @@ public class Assert { /** * 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常 Assert that an object is not {@code null} . - * *
 	 * Assert.notNull(clazz, "The class must not be null");
 	 * 
@@ -219,7 +216,6 @@ public class Assert { /** * 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常 - * *
 	 * Assert.notNull(clazz);
 	 * 
@@ -358,8 +354,8 @@ public class Assert { } /** - * 断言给定字符串是否不被另一个字符串包含(即是否为子串) - * 并使用指定的函数获取错误信息返回 + * 断言给定字符串是否不被另一个字符串包含(即是否为子串),并使用指定的函数获取错误信息返回
+ * 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。 *
 	 * Assert.notContain(name, "rod", ()->{
 	 *      // to query relation message
@@ -385,43 +381,42 @@ public class Assert {
 	}
 
 	/**
-	 * 断言给定字符串是否不被另一个字符串包含(即是否为子串)
-	 *
+	 * 断言给定字符串是否不被另一个字符串包含(即是否为子串)
+ * 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。 *
 	 * Assert.notContain(name, "rod", "Name must not contain 'rod'");
 	 * 
* * @param textToSearch 被搜索的字符串 - * @param substring 被检查的子串 + * @param subString 被检查的子串 * @param errorMsgTemplate 异常时的消息模板 * @param params 参数列表 * @return 被检查的子串 * @throws IllegalArgumentException 非子串抛出异常 */ - public static String notContain(final String textToSearch, final String substring, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException { - return notContain(textToSearch, substring, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params))); + public static String notContain(final String textToSearch, final String subString, final String errorMsgTemplate, final Object... params) throws IllegalArgumentException { + return notContain(textToSearch, subString, () -> new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params))); } /** - * 断言给定字符串是否不被另一个字符串包含(即是否为子串) - * + * 断言给定字符串是否不被另一个字符串包含(即是否为子串),即subString是否不是textToSearch的子串。
+ * 如果非子串,返回子串,如果是子串,则抛出{@link IllegalArgumentException}异常。 *
 	 * Assert.notContain(name, "rod");
 	 * 
* * @param textToSearch 被搜索的字符串 - * @param substring 被检查的子串 + * @param subString 被检查的子串 * @return 被检查的子串 * @throws IllegalArgumentException 非子串抛出异常 */ - public static String notContain(final String textToSearch, final String substring) throws IllegalArgumentException { - return notContain(textToSearch, substring, "[Assertion failed] - this String argument must not contain the substring [{}]", substring); + public static String notContain(final String textToSearch, final String subString) throws IllegalArgumentException { + return notContain(textToSearch, subString, "[Assertion failed] - this String argument must not contain the substring [{}]", subString); } /** * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素 * 并使用指定的函数获取错误信息返回 - * *
 	 * Assert.notEmpty(array, ()->{
 	 *      // to query relation message
@@ -447,7 +442,6 @@ public class Assert {
 
 	/**
 	 * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素
-	 *
 	 * 
 	 * Assert.notEmpty(array, "The array must have elements");
 	 * 
@@ -465,7 +459,6 @@ public class Assert { /** * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素 - * *
 	 * Assert.notEmpty(array, "The array must have elements");
 	 * 
@@ -507,7 +500,6 @@ public class Assert { /** * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含 - * *
 	 * Assert.noNullElements(array, "The array must not have null elements");
 	 * 
@@ -525,7 +517,6 @@ public class Assert { /** * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含 - * *
 	 * Assert.noNullElements(array);
 	 * 
@@ -568,7 +559,6 @@ public class Assert { /** * 断言给定集合非空 - * *
 	 * Assert.notEmpty(collection, "Collection must have elements");
 	 * 
@@ -587,7 +577,6 @@ public class Assert { /** * 断言给定集合非空 - * *
 	 * Assert.notEmpty(collection);
 	 * 
@@ -632,7 +621,6 @@ public class Assert { /** * 断言给定Map非空 - * *
 	 * Assert.notEmpty(map, "Map must have entries");
 	 * 
@@ -652,7 +640,6 @@ public class Assert { /** * 断言给定Map非空 - * *
 	 * Assert.notEmpty(map, "Map must have entries");
 	 * 
@@ -670,7 +657,6 @@ public class Assert { /** * 断言给定对象是否是给定类的实例 - * *
 	 * Assert.instanceOf(Foo.class, foo);
 	 * 
@@ -688,7 +674,6 @@ public class Assert { /** * 断言给定对象是否是给定类的实例 - * *
 	 * Assert.instanceOf(Foo.class, foo, "foo must be an instance of class Foo");
 	 * 
@@ -712,7 +697,6 @@ public class Assert { /** * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}. - * *
 	 * Assert.isAssignable(Number.class, myClass);
 	 * 
@@ -727,7 +711,6 @@ public class Assert { /** * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}. - * *
 	 * Assert.isAssignable(Number.class, myClass, "myClass must can be assignable to class Number");
 	 * 
@@ -767,7 +750,6 @@ public class Assert { /** * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 - * *
 	 * Assert.state(id == null, "The id property must not already be initialized");
 	 * 
@@ -785,7 +767,6 @@ public class Assert { /** * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 - * *
 	 * Assert.state(id == null);
 	 * 
diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java index a40b47137..5c284e18b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/LookupFactory.java @@ -11,7 +11,7 @@ import java.lang.reflect.Method; * {@link MethodHandles.Lookup}工厂,用于创建{@link MethodHandles.Lookup}对象
* jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial * 时会出现权限不够问题,抛出"no private access for invokespecial"异常,因此针对JDK8及JDK9+分别封装lookup方法。 - * + * *

* 参考: *

https://blog.csdn.net/u013202238/article/details/108687086

diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java index cdb4507d3..bba79a832 100755 --- a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java @@ -1,21 +1,97 @@ package cn.hutool.core.lang; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrUtil; import org.junit.Test; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class AssertTest { @Test - public void isNullTest(){ + public void isNullTest() { final String a = null; Assert.isNull(a); } + @Test - public void notNullTest(){ + public void notNullTest() { final String a = null; Assert.isNull(a); } + @Test + public void notEmptyTest() { + final String a = " "; + final String s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + } + + @Test + public void notEmptyForArrayTest() { + // 虽然包含空字符串或者null,但是这大概数组由于有元素,则认定为非empty + String[] a = new String[]{""}; + String[] s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + + a = new String[]{null}; + s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + } + + @Test + public void notEmptyForCollectionTest() { + // 虽然包含空字符串或者null,但是这大概数组由于有元素,则认定为非empty + List a = ListUtil.of(""); + List s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + + a = ListUtil.of((String)null); + s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + } + + @Test + public void notEmptyForMapTest() { + // 虽然包含空字符串或者null,但是这大概数组由于有元素,则认定为非empty + Map a = MapUtil.of("", ""); + Map s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + + a = MapUtil.of(null, null); + s = Assert.notEmpty(a); + org.junit.Assert.assertSame(a, s); + } + + @Test + public void noNullElementsTest() { + final String[] a = new String[]{""}; + final String[] s = Assert.noNullElements(a); + org.junit.Assert.assertSame(a, s); + } + + @Test(expected = IllegalArgumentException.class) + public void noNullElementsTest2() { + final String[] a = new String[]{null}; + Assert.noNullElements(a); + } + + @Test(expected = IllegalArgumentException.class) + public void noNullElementsTest3() { + final String[] a = new String[]{"a", null}; + Assert.noNullElements(a); + } + + @Test + public void notBlankTest() { + final String a = "a"; + final String s = Assert.notBlank(a); + org.junit.Assert.assertSame(a, s); + } + @Test(expected = IllegalArgumentException.class) public void isTrueTest() { final int i = 0; @@ -34,7 +110,7 @@ public class AssertTest { public void isTrueTest3() { final int i = -1; //noinspection ConstantConditions - Assert.isTrue(i > 0, ()-> new IndexOutOfBoundsException("relation message to return")); + Assert.isTrue(i > 0, () -> new IndexOutOfBoundsException("relation message to return")); } @Test @@ -59,4 +135,64 @@ public class AssertTest { Assert.notEquals(c, d, () -> new RuntimeException(StrUtil.format("{}和{}相等", c, d))); } + + @Test + public void notEqualsTest2() { + final Object c = null; + final Object d = "null"; + Assert.notEquals(c, d); + } + + @Test + public void checkBetweenTest() { + final int a = 12; + final int i = Assert.checkBetween(a, 1, 12); + org.junit.Assert.assertSame(a, i); + } + + @Test + public void checkBetweenTest2() { + final double a = 12; + final double i = Assert.checkBetween(a, 1, 12); + org.junit.Assert.assertSame(a, i); + } + + @Test + public void checkBetweenTest3() { + final Number a = 12; + final Number i = Assert.checkBetween(a, 1, 12); + org.junit.Assert.assertSame(a, i); + } + + @Test(expected = IllegalArgumentException.class) + public void notContainTest() { + final String sub = "a"; + final String a = Assert.notContain("abc", sub); + org.junit.Assert.assertSame(sub, a); + } + + @Test + public void notContainTest2() { + final String sub = "d"; + final String a = Assert.notContain("abc", sub); + org.junit.Assert.assertSame(sub, a); + } + + @Test + public void isInstanceOfTest() { + final String a = "a"; + final String s = Assert.isInstanceOf(String.class, a); + org.junit.Assert.assertSame(a, s); + } + + @Test + public void isAssignableTest() { + Assert.isAssignable(Map.class, HashMap.class); + } + + @Test + public void checkIndexTest() { + final int i = Assert.checkIndex(1, 10); + org.junit.Assert.assertEquals(1, i); + } } From ad8b6c3d2881a378419329ec0135ac9d70ddddb5 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 16:22:30 +0800 Subject: [PATCH 034/125] add test --- .../cn/hutool/core/lang/mutable/MutableObj.java | 4 +++- .../test/java/cn/hutool/json/Issue2924Test.java | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 hutool-json/src/test/java/cn/hutool/json/Issue2924Test.java diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java index d78828635..274d833c0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableObj.java @@ -1,5 +1,7 @@ package cn.hutool.core.lang.mutable; +import cn.hutool.core.util.ObjUtil; + import java.io.Serializable; /** @@ -61,7 +63,7 @@ public class MutableObj implements Mutable, Serializable{ } if (this.getClass() == obj.getClass()) { final MutableObj that = (MutableObj) obj; - return this.value.equals(that.value); + return ObjUtil.equals(this.value, that.value); } return false; } diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue2924Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue2924Test.java new file mode 100644 index 000000000..5f4523b85 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/Issue2924Test.java @@ -0,0 +1,16 @@ +package cn.hutool.json; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class Issue2924Test { + + @Test + public void toListTest(){ + final String idsJsonString = "[1174,137,1172,210,1173,627,628]"; + final List idList = JSONUtil.toList(idsJsonString,Integer.class); + Assert.assertEquals("[1174, 137, 1172, 210, 1173, 627, 628]", idList.toString()); + } +} From 76c42d49c775b41b788335572f626afae2e4ff7b Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 19:58:49 +0800 Subject: [PATCH 035/125] fix test --- hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java index bba79a832..7b070c707 100755 --- a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java @@ -154,7 +154,7 @@ public class AssertTest { public void checkBetweenTest2() { final double a = 12; final double i = Assert.checkBetween(a, 1, 12); - org.junit.Assert.assertSame(a, i); + org.junit.Assert.assertEquals(a, i, 0.00); } @Test From 8db58ceddee071faffe519d82c00cd561d5b1e52 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Feb 2023 20:56:14 +0800 Subject: [PATCH 036/125] fix test --- .../java/cn/hutool/core/lang/func/LambdaFactoryTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java index 505268020..233153b44 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java @@ -29,7 +29,6 @@ import java.util.function.Function; */ public class LambdaFactoryTest { - // @Test @Test public void testMethodNotMatch() { try { @@ -39,6 +38,7 @@ public class LambdaFactoryTest { } } + @SuppressWarnings("unchecked") @Test public void buildLambdaTest() { final Something something = new Something(); @@ -49,6 +49,7 @@ public class LambdaFactoryTest { final Function get12 = LambdaFactory.build(Function.class, Something.class, "getId"); Assert.assertEquals(get11, get12); + // 通过LambdaFactory模拟创建一个getId方法的Lambda句柄函数,通过调用这个函数,实现方法调用。 Assert.assertEquals(something.getId(), get11.apply(something)); final String name = "sname"; @@ -136,6 +137,7 @@ public class LambdaFactoryTest { *

proxy 运行100000000次耗时 1117192600 NANOSECONDS *

-------------------------------------------- */ + @SuppressWarnings({"rawtypes", "unchecked", "Convert2MethodRef"}) @Test @SneakyThrows public void lambdaGetPerformanceTest() { @@ -211,6 +213,7 @@ public class LambdaFactoryTest { *

proxy 运行100000000次耗时 1169452400 NANOSECONDS *

-------------------------------------------- */ + @SuppressWarnings({"rawtypes", "unchecked"}) @Test @SneakyThrows public void lambdaSetPerformanceTest() { @@ -246,6 +249,7 @@ public class LambdaFactoryTest { loop(count, tasks); } + @SuppressWarnings("rawtypes") @SneakyThrows private void loop(final int count, final Task... tasks) { Arrays.stream(tasks) @@ -265,6 +269,7 @@ public class LambdaFactoryTest { System.out.println("--------------------------------------------"); } + @SuppressWarnings({"InnerClassMayBeStatic", "FieldMayBeFinal"}) @Getter private class Task { private String name; From 5f97b3d47ca703b293fd5775e7cadbd3b2bfc196 Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Tue, 28 Feb 2023 02:19:49 +0000 Subject: [PATCH 037/125] Update hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java --- hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 032c4fd3b..27adf6b78 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -210,7 +210,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 - * @param s 用来生成元素的 {@code Supplier} + * @param s 用来生成元素的 {@link Supplier} * @return 无限串行无序流 */ public static EasyStream generate(final Supplier s) { From d89541364f3f8e6e915d2b6525dd34ed334dd0bd Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Tue, 28 Feb 2023 10:59:49 +0800 Subject: [PATCH 038/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9final=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 85 ++++++++++--------- .../cn/hutool/core/stream/EasyStreamTest.java | 55 ++++++------ 2 files changed, 71 insertions(+), 69 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index fdd2d390c..51a46c18c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -275,52 +275,52 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { + public int sum(final ToIntFunction mapper) { return stream.mapToInt(mapper).sum(); } /** - * 计算long类型总和 + * 计算long类型的总和 * - * @param mapper 映射 - * @return long + * @param mapper 将对象转换为long的 {@link Function} + * @return long 总和 */ - public long sum(ToLongFunction mapper) { + public long sum(final ToLongFunction mapper) { return stream.mapToLong(mapper).sum(); } /** - * 计算double总和 + * 计算double类型的总和 * - * @param mapper 映射器 - * @return double + * @param mapper 将对象转换为double的 {@link Function} + * @return double 总和 */ - public double sum(ToDoubleFunction mapper) { + public double sum(final ToDoubleFunction mapper) { return stream.mapToDouble(mapper).sum(); } /** - * 计算number的总和 + * 计算 {@link Number} 类型的总和 * - * @param mapper 映射 - * @return {@link BigDecimal} + * @param mapper 将对象转换为{@link Number} 的 {@link Function} + * @return {@link BigDecimal} , 如果流为空, 返回 {@link BigDecimal#ZERO} */ public BigDecimal sum(final Function mapper) { - return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add,NumberUtil::add); + return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add, NumberUtil::add); } /** - * 计算bigDecimal平均值 并以四舍五入的方式保留2位精度 + * 计算 {@link BigDecimal} 类型的平均值 并以四舍五入的方式保留2位精度 * - * @param mapper 映射 - * @return {@link Opt}<{@link BigDecimal}> 如果元素的长度为0 那么会返回为空的opt + * @param mapper 将对象转换为{@link BigDecimal}的 {@link Function} + * @return {@link Opt}<{@link BigDecimal}>; 如果流的长度为0, 返回 {@link Opt#empty()} */ public Opt avg(final Function mapper) { return avg(mapper, 2); @@ -328,53 +328,54 @@ public class EasyStream extends AbstractEnhancedWrappedStream + * @param mapper 将对象转换为{@link BigDecimal} 的 {@link Function} + * @param scale 保留精度 + * @return {@link Opt}<{@link BigDecimal}> 如果流的长度为0, 返回 {@link Opt#empty()} */ - public Opt avg(final Function mapper, int scale) { + public Opt avg(final Function mapper, final int scale) { return avg(mapper, scale, RoundingMode.HALF_UP); } /** - * 计算bigDecimal平均值 + * 计算 {@link BigDecimal} 类型的平均值 * - * @param mapper 映射 - * @param scale 精度 + * @param mapper 将对象转换为{@link BigDecimal} 的 {@link Function} + * @param scale 保留精度 * @param roundingMode 舍入模式 - * @return {@link Opt}<{@link BigDecimal}> 如果元素的长度为0 那么会返回为空的opt + * @return {@link Opt}<{@link BigDecimal}> 如果元素的长度为0 那么会返回 {@link Opt#empty()} */ - public Opt avg(final Function mapper, int scale, RoundingMode roundingMode) { + public Opt avg(final Function mapper, final int scale, + final RoundingMode roundingMode) { //元素列表 List bigDecimalList = stream.map(mapper).collect(Collectors.toList()); if (CollUtil.isEmpty(bigDecimalList)) { - return Opt.ofNullable(null); + return Opt.empty(); } - return Opt.of(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add) + return Opt.ofNullable(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add) .divide(NumberUtil.toBigDecimal(bigDecimalList.size()), scale, roundingMode)); } /** - * 计算int平均值 + * 计算int类型的平均值 * - * @param mapper 映射器 - * @return {@link OptionalDouble} + * @param mapper 将对象转换为int 的 {@link Function} + * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()} */ - public OptionalDouble avg(ToIntFunction mapper) { + public OptionalDouble avg(final ToIntFunction mapper) { return stream.mapToInt(mapper).average(); } /** - * 计算double平均值 + * 计算double类型的平均值 * - * @param mapper 映射 - * @return {@link OptionalDouble} + * @param mapper 将对象转换为double 的 {@link Function} + * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()} */ - public OptionalDouble avg(ToDoubleFunction mapper) { + public OptionalDouble avg(final ToDoubleFunction mapper) { return stream.mapToDouble(mapper).average(); } @@ -382,10 +383,10 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { + public OptionalDouble avg(final ToLongFunction mapper) { return stream.mapToLong(mapper).average(); } diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java index 5646d772f..2fa800d3a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java @@ -1,22 +1,31 @@ package cn.hutool.core.stream; -import cn.hutool.core.collection.CollUtil; +import static java.util.Collections.singletonList; + import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Opt; import cn.hutool.core.map.MapUtil; import cn.hutool.core.math.NumberUtil; -import java.math.RoundingMode; -import org.junit.Assert; -import org.junit.Test; - import java.math.BigDecimal; -import java.util.*; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalDouble; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; - -import static java.util.Collections.singletonList; +import org.junit.Assert; +import org.junit.Test; /** * @author VampireAchao @@ -490,7 +499,7 @@ public class EasyStreamTest { public void testLongSumAndAvg() { //测试long类型的sum long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue); - Assert.assertEquals(55, sum); + Assert.assertEquals(55L, sum); //测试long类型的空元素 sum List longList = new ArrayList<>(); @@ -512,10 +521,8 @@ public class EasyStreamTest { @Test public void testBigDecimalSumAndAvg() { //测试bigDecimal的sum - BigDecimal sum = EasyStream.of(NumberUtil.toBigDecimal(1.1), NumberUtil.toBigDecimal(2.2), - NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), NumberUtil.toBigDecimal(5.5), - NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), NumberUtil.toBigDecimal(8.8), - NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)).sum(Function.identity()); + BigDecimal sum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).map(NumberUtil::toBigDecimal) + .sum(Function.identity()); Assert.assertEquals(NumberUtil.toBigDecimal(59.6), sum); //测试bigDecimal的sum 空元素 @@ -524,26 +531,20 @@ public class EasyStreamTest { Assert.assertEquals(BigDecimal.ZERO, emptySum); //测试bigDecimal的avg全参 - Opt bigDecimalAvgFullParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), - NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), - NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), - NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + Opt bigDecimalAvgFullParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10) + .map(NumberUtil::toBigDecimal) .avg(Function.identity(), 2, RoundingMode.HALF_UP); Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgFullParam.get()); - //测试bigDecimal的avg双参 - Opt bigDecimalAvgOneParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), - NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), - NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), - NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + //测试bigDecimal的avg单参 + Opt bigDecimalAvgOneParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10) + .map(NumberUtil::toBigDecimal) .avg(Function.identity()); Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgOneParam.get()); - //测试bigDecimal的avg单参 - Opt bigDecimalAvgTwoParam = EasyStream.of(NumberUtil.toBigDecimal(1.1), - NumberUtil.toBigDecimal(2.2), NumberUtil.toBigDecimal(3.3), NumberUtil.toBigDecimal(4.4), - NumberUtil.toBigDecimal(5.5), NumberUtil.toBigDecimal(6.6), NumberUtil.toBigDecimal(7.7), - NumberUtil.toBigDecimal(8.8), NumberUtil.toBigDecimal(9.9), NumberUtil.toBigDecimal(10.10)) + //测试bigDecimal的avg双参 + Opt bigDecimalAvgTwoParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10) + .map(NumberUtil::toBigDecimal) .avg(Function.identity(), 2); Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgTwoParam.get()); From 0b72ada03f64184956ff9633a1f25c20c974bd44 Mon Sep 17 00:00:00 2001 From: LoveHuahua Date: Tue, 28 Feb 2023 14:08:12 +0800 Subject: [PATCH 039/125] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/stream/EasyStream.java | 109 ++++++++++-------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 84735a6a9..af022870d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -5,14 +5,20 @@ import cn.hutool.core.lang.Opt; import cn.hutool.core.math.NumberUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; - import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Objects; import java.util.OptionalDouble; import java.util.Spliterator; -import java.util.function.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -206,11 +212,11 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型 - * @param s 用来生成元素的 {@link Supplier} + * @param s 用来生成元素的 {@link Supplier} * @return 无限串行无序流 */ public static EasyStream generate(final Supplier s) { @@ -275,53 +281,54 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { + public int sum(final ToIntFunction mapper) { return stream.mapToInt(mapper).sum(); } /** - * 计算long类型总和 + * 计算long类型的总和 * - * @param mapper 映射 - * @return long + * @param mapper 将对象转换为long的 {@link Function} + * @return long 总和 */ - public long sum(ToLongFunction mapper) { + public long sum(final ToLongFunction mapper) { return stream.mapToLong(mapper).sum(); } /** - * 计算double总和 + * 计算double类型的总和 * - * @param mapper 映射器 - * @return double + * @param mapper 将对象转换为double的 {@link Function} + * @return double 总和 */ - public double sum(ToDoubleFunction mapper) { + public double sum(final ToDoubleFunction mapper) { return stream.mapToDouble(mapper).sum(); } + /** - * 计算number的总和 + * 计算 {@link Number} 类型的总和 * - * @param mapper 映射 - * @param 映射后的类型 - * @return {@link BigDecimal} + * @param 数字 + * @param mapper 将对象转换为{@link Number} 的 {@link Function} + * @return {@link BigDecimal} , 如果流为空, 返回 {@link BigDecimal#ZERO} */ public BigDecimal sum(final Function mapper) { - return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add,NumberUtil::add); + return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add, NumberUtil::add); } /** - * 计算bigDecimal平均值 并以四舍五入的方式保留2位精度 + * 计算 {@link BigDecimal} 类型的平均值 并以四舍五入的方式保留2位精度 * - * @param mapper 映射 - * @return 计算结果 如果元素的长度为0 那么会返回为空的opt + * @param mapper 将对象转换为{@link BigDecimal}的 {@link Function} + * @return 计算后的平均值 如果流的长度为0, 返回 {@link Opt#empty()} */ public Opt avg(final Function mapper) { return avg(mapper, 2); @@ -329,53 +336,53 @@ public class EasyStream extends AbstractEnhancedWrappedStream avg(final Function mapper, int scale) { + public Opt avg(final Function mapper, final int scale) { return avg(mapper, scale, RoundingMode.HALF_UP); } /** - * 计算bigDecimal平均值 + * 计算 {@link BigDecimal} 类型的平均值 * - * @param mapper 映射 - * @param scale 精度 + * @param mapper 将对象转换为{@link BigDecimal} 的 {@link Function} + * @param scale 保留精度 * @param roundingMode 舍入模式 - * @return 计算结果 如果元素的长度为0 那么会返回为空的opt + * @return 计算后的平均值 如果元素的长度为0 那么会返回 {@link Opt#empty()} */ - public Opt avg(final Function mapper, int scale, RoundingMode roundingMode) { + public Opt avg(final Function mapper, final int scale, + final RoundingMode roundingMode) { //元素列表 List bigDecimalList = stream.map(mapper).collect(Collectors.toList()); if (CollUtil.isEmpty(bigDecimalList)) { - return Opt.ofNullable(null); + return Opt.empty(); } - - return Opt.of(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add) + return Opt.ofNullable(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add) .divide(NumberUtil.toBigDecimal(bigDecimalList.size()), scale, roundingMode)); } /** - * 计算int平均值 + * 计算int类型的平均值 * - * @param mapper 映射器 - * @return {@link OptionalDouble} + * @param mapper 将对象转换为int 的 {@link Function} + * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()} */ - public OptionalDouble avg(ToIntFunction mapper) { + public OptionalDouble avg(final ToIntFunction mapper) { return stream.mapToInt(mapper).average(); } /** - * 计算double平均值 + * 计算double类型的平均值 * - * @param mapper 映射 - * @return {@link OptionalDouble} + * @param mapper 将对象转换为double 的 {@link Function} + * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()} */ - public OptionalDouble avg(ToDoubleFunction mapper) { + public OptionalDouble avg(final ToDoubleFunction mapper) { return stream.mapToDouble(mapper).average(); } @@ -383,10 +390,10 @@ public class EasyStream extends AbstractEnhancedWrappedStream mapper) { + public OptionalDouble avg(final ToLongFunction mapper) { return stream.mapToLong(mapper).average(); } @@ -407,9 +414,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream{@code - * accept(t) - * return this; - * }

+ * accept(t) + * return this; + * }
*/ default Builder add(final T t) { accept(t); From 57671e3231f1b1c057c72bc7da674005cd973148 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 28 Feb 2023 20:30:55 +0800 Subject: [PATCH 040/125] fix code --- .../src/main/java/cn/hutool/core/regex/RegexPool.java | 2 +- .../src/test/java/cn/hutool/core/util/PhoneUtilTest.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/regex/RegexPool.java b/hutool-core/src/main/java/cn/hutool/core/regex/RegexPool.java index 42604b5cb..a40b0375f 100755 --- a/hutool-core/src/main/java/cn/hutool/core/regex/RegexPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/regex/RegexPool.java @@ -82,7 +82,7 @@ public interface RegexPool { * * @see 800 */ - String TEL_400_800 = "0\\d{2,3}[\\- ]?[1-9]\\d{6,7}|[48]00[\\- ]?[1-9]\\d{6}"; + String TEL_400_800 = "0\\d{2,3}[\\- ]?[1-9]\\d{6,7}|[48]00[\\- ]?[1-9]\\d{2}[\\- ]?\\d{4}"; /** * 18位身份证号码 */ diff --git a/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java index cdb6ed44a..fde5a3ad3 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/PhoneUtilTest.java @@ -96,4 +96,13 @@ public class PhoneUtilTest { Assert.assertEquals("7654321", PhoneUtil.subTelAfter("0755-7654321")); Assert.assertEquals("7654321", PhoneUtil.subTelAfter("07557654321")); } + + @Test + public void isTel400800Test() { + boolean tel400800 = PhoneUtil.isTel400800("400-860-8608");//800-830-3811 + Assert.assertTrue(tel400800); + + tel400800 = PhoneUtil.isTel400800("400-8608608");//800-830-3811 + Assert.assertTrue(tel400800); + } } From eb02d5e759f0f8870fc1f788001935b78ac34072 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 28 Feb 2023 20:44:34 +0800 Subject: [PATCH 041/125] add Automatic-Module-Name --- pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pom.xml b/pom.xml index 408ceac61..800ebdb75 100755 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,25 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + true + + true + + + ${os.name} + ${user.name} + ${java.version} + ${maven.build.timestamp} + ${project.artifactId} + + + + org.codehaus.mojo versions-maven-plugin From bff6af81a16ed9e7223ae8acb64b099576653be7 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 28 Feb 2023 20:46:30 +0800 Subject: [PATCH 042/125] fix doc --- hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java index 409f01452..172dcd22f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Pool.java @@ -2,7 +2,6 @@ package cn.hutool.core.net; /** * Ip相关常量 - *

*

  * 为了方便处理作出以下特别说明,若后续因此收到影响或有更好处理方式需要及时调整:
  * 1、此处定义的`最小值`、`最大值`并非实际ip可分配的最小值、最大值。而是正常地址格式所能表示的最小值、最大值。

From cb772d3f92bb85ab9ccdbb1b2b2d96b3de4b2885 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 20:50:23 +0800
Subject: [PATCH 043/125] add  Automatic-Module-Name

---
 pom.xml | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/pom.xml b/pom.xml
index 800ebdb75..7d0650a66 100755
--- a/pom.xml
+++ b/pom.xml
@@ -93,6 +93,25 @@
 					-Xlint:unchecked
 				
 			
+			
+				org.apache.maven.plugins
+				maven-jar-plugin
+				
+					
+						true
+						
+							true
+						
+						
+							${os.name}
+							${user.name}
+							${java.version}
+							${maven.build.timestamp}
+							${project.artifactId}
+						
+					
+				
+			
 			
 			
 				org.apache.maven.plugins
@@ -166,25 +185,6 @@
 							
 						
 					
-					
-						org.apache.maven.plugins
-						maven-jar-plugin
-						
-							
-								true
-								
-									true
-								
-								
-									${os.name}
-									${user.name}
-									${java.version}
-									${maven.build.timestamp}
-									${project.artifactId}
-								
-							
-						
-					
 					
 						org.codehaus.mojo
 						versions-maven-plugin

From 1f9ee66a0c50d2a6dadbebb75c32dd02f632f34c Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:03:34 +0800
Subject: [PATCH 044/125] update dependency

---
 hutool-extra/pom.xml | 12 ++++++------
 hutool-http/pom.xml  |  4 ++--
 hutool-poi/pom.xml   |  4 ++--
 pom.xml              |  4 ++--
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index d03fe8fe1..11e9015a6 100755
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -19,14 +19,14 @@
 	
 		
 		2.3
-		3.13.0.RELEASE
+		3.14.1.RELEASE
 		1.4.2
-		2.3.31
+		2.3.32
 		4.9.21
 		3.0.15.RELEASE
 		1.6.2
 		0.1.55
-		0.34.0
+		0.35.0
 		3.5.1
 		3.9.0
 		5.1.1
@@ -143,7 +143,7 @@
 		
 			jakarta.mail
 			jakarta.mail-api
-			2.1.0
+			2.1.1
 			compile
 			true
 		
@@ -236,7 +236,7 @@
 		
 			org.lionsoul
 			jcseg-core
-			2.6.2
+			2.6.3
 			true
 		
 		
@@ -487,7 +487,7 @@
 		
 			org.apache.commons
 			commons-compress
-			1.21
+			1.22
 			compile
 			true
 		
diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml
index b3e67831f..850484b95 100755
--- a/hutool-http/pom.xml
+++ b/hutool-http/pom.xml
@@ -38,13 +38,13 @@
 		
 			org.apache.httpcomponents.client5
 			httpclient5
-			5.1.3
+			5.2.1
 			provided
 		
 		
 			org.apache.httpcomponents
 			httpclient
-			4.5.13
+			4.5.14
 			provided
 		
 		
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index c9f6bfe8f..546ca8597 100755
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -18,7 +18,7 @@
 
 	
 		
-		5.2.2
+		5.2.3
 	
 
 	
@@ -45,7 +45,7 @@
 		
 			org.ofdrw
 			ofdrw-full
-			1.18.2
+			1.20.2
 			compile
 			true
 		
diff --git a/pom.xml b/pom.xml
index 7d0650a66..bdcee2e36 100755
--- a/pom.xml
+++ b/pom.xml
@@ -36,8 +36,8 @@
 
 		
 		8
-		5.9.0
-		1.18.24
+		5.9.2
+		1.18.26
 	
 
 	

From 0a88978c585d0655bbbe83f7fe823f2217c03bab Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:08:38 +0800
Subject: [PATCH 045/125] add version

---
 pom.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pom.xml b/pom.xml
index bdcee2e36..12fc17bc1 100755
--- a/pom.xml
+++ b/pom.xml
@@ -96,6 +96,7 @@
 			
 				org.apache.maven.plugins
 				maven-jar-plugin
+				3.3.0
 				
 					
 						true

From c8707966be307fd58e64dd405b2c6d06c0fa690c Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:09:54 +0800
Subject: [PATCH 046/125] add version

---
 .../src/main/java/cn/hutool/core/lang/func/LambdaFactory.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java
index b5369995b..38401bc96 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaFactory.java
@@ -65,11 +65,11 @@ public class LambdaFactory {
 	 * @return 接受Lambda的函数式接口对象
 	 * @param  Function类型
 	 */
+	@SuppressWarnings("unchecked")
 	public static  F build(final Class functionInterfaceType, final Method method) {
 		Assert.notNull(functionInterfaceType);
 		Assert.notNull(method);
 		final MutableEntry, Method> cacheKey = new MutableEntry<>(functionInterfaceType, method);
-		//noinspection unchecked
 		return (F) CACHE.computeIfAbsent(cacheKey, key -> {
 			final List abstractMethods = Arrays.stream(functionInterfaceType.getMethods())
 					.filter(m -> Modifier.isAbstract(m.getModifiers()))

From 8573b84d025b3301aeedd18efc9b81c871b077e4 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:12:23 +0800
Subject: [PATCH 047/125] remove console

---
 hutool-core/src/test/java/cn/hutool/core/tree/TreeTest.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hutool-core/src/test/java/cn/hutool/core/tree/TreeTest.java b/hutool-core/src/test/java/cn/hutool/core/tree/TreeTest.java
index c14971119..3db1199d0 100755
--- a/hutool-core/src/test/java/cn/hutool/core/tree/TreeTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/tree/TreeTest.java
@@ -85,7 +85,6 @@ public class TreeTest {
 		Console.log(tree);
 		tree.walk((tr)-> ids.add(tr.getId()), true);
 
-		Console.log(ids);
 		Assert .assertEquals(7, ids.size());
 	}
 

From 28777b69b7e01e131d3a5309a7441c6b5448ab73 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:39:27 +0800
Subject: [PATCH 048/125] fix code

---
 .../test/java/cn/hutool/core/lang/func/LambdaUtilTest.java  | 5 +++++
 hutool-poi/pom.xml                                          | 6 ++++++
 pom.xml                                                     | 2 +-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java
index 169c08e11..c525fad3f 100644
--- a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java
@@ -179,6 +179,7 @@ public class LambdaUtilTest {
 		Assert.assertTrue(bean.isFlag());
 	}
 
+	@SuppressWarnings("unchecked")
 	@Test
 	public void lambdaTest() {
 		final Bean bean = new Bean();
@@ -203,6 +204,7 @@ public class LambdaUtilTest {
 		Long pid;
 		boolean flag;
 
+		@SuppressWarnings("SameParameterValue")
 		private Tuple uniqueKey(final String name) {
 			return new Tuple(id, pid, flag, name);
 		}
@@ -211,14 +213,17 @@ public class LambdaUtilTest {
 			return new Tuple(name, length, score);
 		}
 
+		@SuppressWarnings("unused")
 		public static Function idGetter() {
 			return Bean::getId;
 		}
 
+		@SuppressWarnings("unused")
 		public Function idGet() {
 			return bean -> bean.id;
 		}
 
+		@SuppressWarnings("unused")
 		public Function idGetting() {
 			return Bean::getId;
 		}
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index 546ca8597..8c035f51e 100755
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -39,6 +39,12 @@
 			poi-ooxml
 			${poi.version}
 			compile
+			
+				
+					log4j-api
+					org.apache.logging.log4j
+				
+			
 			true
 		
 		
diff --git a/pom.xml b/pom.xml
index 12fc17bc1..62a37416f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,7 @@
 							${user.name}
 							${java.version}
 							${maven.build.timestamp}
-							${project.artifactId}
+							${project.groupId}
 						
 					
 				

From daa618ef3d6925cfbdf6cfe2cffbab449c1468a3 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:55:52 +0800
Subject: [PATCH 049/125] fix code

---
 .../src/main/java/cn/hutool/core/io/FileUtil.java      |  8 ++------
 .../main/java/cn/hutool/core/io/file/FileWriter.java   | 10 ++++++----
 .../cn/hutool/swing/img/gif/AnimatedGifEncoder.java    |  6 +++---
 .../main/java/cn/hutool/swing/img/gif/GifDecoder.java  |  5 +++--
 4 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
index 219831fdf..15a1a4941 100755
--- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
@@ -32,9 +32,7 @@ import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileFilter;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.LineNumberReader;
@@ -1790,8 +1788,7 @@ public class FileUtil extends PathUtil {
 	 */
 	public static BOMInputStream getBOMInputStream(final File file) throws IORuntimeException {
 		try {
-			//noinspection IOStreamConstructor
-			return new BOMInputStream(new FileInputStream(file));
+			return new BOMInputStream(Files.newInputStream(file.toPath()));
 		} catch (final IOException e) {
 			throw new IORuntimeException(e);
 		}
@@ -2335,8 +2332,7 @@ public class FileUtil extends PathUtil {
 	public static BufferedOutputStream getOutputStream(final File file) throws IORuntimeException {
 		final OutputStream out;
 		try {
-			//noinspection IOStreamConstructor
-			out = new FileOutputStream(touch(file));
+			out = Files.newOutputStream(touch(file).toPath());
 		} catch (final IOException e) {
 			throw new IORuntimeException(e);
 		}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java
index 255421399..2e8c704b0 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java
@@ -4,8 +4,8 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.text.StrUtil;
+import cn.hutool.core.util.CharsetUtil;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
@@ -13,9 +13,11 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -336,9 +338,9 @@ public class FileWriter extends FileWrapper {
 	 * @since 5.5.2
 	 */
 	public File writeFromStream(final InputStream in, final boolean isCloseIn) throws IORuntimeException {
-		FileOutputStream out = null;
+		OutputStream out = null;
 		try {
-			out = new FileOutputStream(FileUtil.touch(file));
+			out = Files.newOutputStream(FileUtil.touch(file).toPath());
 			IoUtil.copy(in, out);
 		} catch (final IOException e) {
 			throw new IORuntimeException(e);
@@ -359,7 +361,7 @@ public class FileWriter extends FileWrapper {
 	 */
 	public BufferedOutputStream getOutputStream() throws IORuntimeException {
 		try {
-			return new BufferedOutputStream(new FileOutputStream(FileUtil.touch(file)));
+			return new BufferedOutputStream(Files.newOutputStream(FileUtil.touch(file).toPath()));
 		} catch (final IOException e) {
 			throw new IORuntimeException(e);
 		}
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java
index 52d6c2ca6..30f7f3b6b 100755
--- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java
@@ -5,9 +5,10 @@ import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.DataBufferByte;
 import java.io.BufferedOutputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 /**
  * 动态GIF动画生成器,可生成一个或多个帧的GIF。
@@ -296,8 +297,7 @@ public class AnimatedGifEncoder {
 	public boolean start(final String file) {
 		boolean ok;
 		try {
-			//noinspection IOStreamConstructor
-			out = new BufferedOutputStream(new FileOutputStream(file));
+			out = new BufferedOutputStream(Files.newOutputStream(Paths.get(file)));
 			ok = start(out);
 			closeStream = true;
 		} catch (final IOException e) {
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java
index 9b6b92ea0..676008a5a 100755
--- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java
@@ -10,10 +10,11 @@ import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
 import java.awt.image.DataBufferInt;
 import java.io.BufferedInputStream;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 
 /**
@@ -339,7 +340,7 @@ public class GifDecoder {
 				final URL url = new URL(name);
 				in = new BufferedInputStream(url.openStream());
 			} else {
-				in = new BufferedInputStream(new FileInputStream(name));
+				in = new BufferedInputStream(Files.newInputStream(Paths.get(name)));
 			}
 			status = read(in);
 		} catch (final IOException e) {

From 82be78e2fdca4191598d9fb67dbcb116c3fb10d3 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 21:57:46 +0800
Subject: [PATCH 050/125] EasyStreamTest

---
 .../cn/hutool/core/stream/EasyStreamTest.java | 53 ++++++++++---------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
index 2fa800d3a..ee92c4d17 100644
--- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
@@ -1,11 +1,12 @@
 package cn.hutool.core.stream;
 
-import static java.util.Collections.singletonList;
-
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.lang.Opt;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.math.NumberUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.ArrayList;
@@ -24,8 +25,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.junit.Assert;
-import org.junit.Test;
+
+import static java.util.Collections.singletonList;
 
 /**
  * @author VampireAchao
@@ -453,21 +454,21 @@ public class EasyStreamTest {
 	@Test
 	public void testIntSumAndAvg() {
 		//测试int类型的总和
-		int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue);
+		final int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue);
 		Assert.assertEquals(55, sum);
 
 		//测试为空
-		List integerList = new ArrayList<>();
-		int emptySum = EasyStream.of(integerList).sum(Integer::intValue);
+		final List integerList = new ArrayList<>();
+		final int emptySum = EasyStream.of(integerList).sum(Integer::intValue);
 		Assert.assertEquals(0, emptySum);
 
 		//测试平均值
-		OptionalDouble avg = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).avg(Integer::intValue);
+		final OptionalDouble avg = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).avg(Integer::intValue);
 		Assert.assertTrue(avg.isPresent());
 		Assert.assertEquals(5.5, avg.getAsDouble(), 2);
 
 		//测试元素为空
-		OptionalDouble emptyAvg = EasyStream.of(integerList).avg(Integer::intValue);
+		final OptionalDouble emptyAvg = EasyStream.of(integerList).avg(Integer::intValue);
 		Assert.assertFalse(emptyAvg.isPresent());
 
 	}
@@ -475,22 +476,22 @@ public class EasyStreamTest {
 	@Test
 	public void testDoubleSumAndAvg() {
 		//测试double类型的sum
-		double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue);
+		final double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue);
 		Assert.assertEquals(59.6, doubleSum, 2);
 
 		//测试double类型的sum 无元素double
-		List doubleList = new ArrayList<>();
-		double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue);
+		final List doubleList = new ArrayList<>();
+		final double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue);
 		Assert.assertEquals(0.0, emptySum, 2);
 
 		//测试double类型的avg
-		OptionalDouble doubleAvg = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+		final OptionalDouble doubleAvg = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
 				.avg(Double::doubleValue);
 		Assert.assertTrue(doubleAvg.isPresent());
 		Assert.assertEquals(5.96, doubleAvg.getAsDouble(), 2);
 
 		//测试double类型的 空元素的avg
-		OptionalDouble emptyDoubleAvg = EasyStream.of(doubleList).avg(Double::doubleValue);
+		final OptionalDouble emptyDoubleAvg = EasyStream.of(doubleList).avg(Double::doubleValue);
 		Assert.assertFalse(emptyDoubleAvg.isPresent());
 
 	}
@@ -498,21 +499,21 @@ public class EasyStreamTest {
 	@Test
 	public void testLongSumAndAvg() {
 		//测试long类型的sum
-		long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue);
+		final long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue);
 		Assert.assertEquals(55L, sum);
 
 		//测试long类型的空元素 sum
-		List longList = new ArrayList<>();
-		long emptySum = EasyStream.of(longList).sum(Long::longValue);
+		final List longList = new ArrayList<>();
+		final long emptySum = EasyStream.of(longList).sum(Long::longValue);
 		Assert.assertEquals(0L, emptySum);
 
 		//测试long类型的avg
-		OptionalDouble doubleAvg = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).avg(Long::longValue);
+		final OptionalDouble doubleAvg = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).avg(Long::longValue);
 		Assert.assertTrue(doubleAvg.isPresent());
 		Assert.assertEquals(5.5, doubleAvg.getAsDouble(), 2);
 
 		//测试long类型的avg 空元素
-		OptionalDouble emptyDoubleAvg = EasyStream.of(longList).avg(Long::longValue);
+		final OptionalDouble emptyDoubleAvg = EasyStream.of(longList).avg(Long::longValue);
 		Assert.assertFalse(emptyDoubleAvg.isPresent());
 
 
@@ -521,35 +522,35 @@ public class EasyStreamTest {
 	@Test
 	public void testBigDecimalSumAndAvg() {
 		//测试bigDecimal的sum
-		BigDecimal sum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).map(NumberUtil::toBigDecimal)
+		final BigDecimal sum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).map(NumberUtil::toBigDecimal)
 				.sum(Function.identity());
 		Assert.assertEquals(NumberUtil.toBigDecimal(59.6), sum);
 
 		//测试bigDecimal的sum 空元素
-		List bigDecimalEmptyList = new ArrayList<>();
-		BigDecimal emptySum = EasyStream.of(bigDecimalEmptyList).sum(Function.identity());
+		final List bigDecimalEmptyList = new ArrayList<>();
+		final BigDecimal emptySum = EasyStream.of(bigDecimalEmptyList).sum(Function.identity());
 		Assert.assertEquals(BigDecimal.ZERO, emptySum);
 
 		//测试bigDecimal的avg全参
-		Opt bigDecimalAvgFullParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+		final Opt bigDecimalAvgFullParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
 				.map(NumberUtil::toBigDecimal)
 				.avg(Function.identity(), 2, RoundingMode.HALF_UP);
 		Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgFullParam.get());
 
 		//测试bigDecimal的avg单参
-		Opt bigDecimalAvgOneParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+		final Opt bigDecimalAvgOneParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
 				.map(NumberUtil::toBigDecimal)
 				.avg(Function.identity());
 		Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgOneParam.get());
 
 		//测试bigDecimal的avg双参
-		Opt bigDecimalAvgTwoParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+		final Opt bigDecimalAvgTwoParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
 				.map(NumberUtil::toBigDecimal)
 				.avg(Function.identity(), 2);
 		Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgTwoParam.get());
 
 		//测试bigDecimal的avg 空元素
-		Opt emptyBigDecimalAvg = EasyStream.of(bigDecimalEmptyList)
+		final Opt emptyBigDecimalAvg = EasyStream.of(bigDecimalEmptyList)
 				.avg(Function.identity(), 2, RoundingMode.HALF_UP);
 		Assert.assertFalse(emptyBigDecimalAvg.isPresent());
 

From 1141d57cfd352001f281a2639881eccffd372842 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 22:48:00 +0800
Subject: [PATCH 051/125] fix code

---
 .../java/cn/hutool/core/io/checksum/ChecksumUtil.java     | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/ChecksumUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/ChecksumUtil.java
index a96bc8f66..dafb03ad0 100755
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/ChecksumUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/ChecksumUtil.java
@@ -6,9 +6,9 @@ import cn.hutool.core.io.stream.EmptyOutputStream;
 import cn.hutool.core.lang.Assert;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.Files;
 import java.util.zip.CRC32;
 import java.util.zip.CheckedInputStream;
 import java.util.zip.Checksum;
@@ -57,8 +57,8 @@ public class ChecksumUtil {
 			throw new IllegalArgumentException("Checksums can't be computed on directories");
 		}
 		try {
-			return checksum(new FileInputStream(file), checksum);
-		} catch (final FileNotFoundException e) {
+			return checksum(Files.newInputStream(file.toPath()), checksum);
+		} catch (final IOException e) {
 			throw new IORuntimeException(e);
 		}
 	}

From 73d25a2f8ba71d51fa0938ebc801fe0690b23a94 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 28 Feb 2023 23:15:29 +0800
Subject: [PATCH 052/125] fix code

---
 .../java/cn/hutool/core/date/StopWatch.java   | 17 ++++++++----
 .../cn/hutool/core/date/StopWatchTest.java    | 26 +++++++++++++++++++
 2 files changed, 38 insertions(+), 5 deletions(-)
 create mode 100644 hutool-core/src/test/java/cn/hutool/core/date/StopWatchTest.java

diff --git a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java
index 121d52dda..cb3377766 100755
--- a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java
@@ -382,20 +382,27 @@ public class StopWatch {
 			sb.append("No task info kept");
 		} else {
 			sb.append("---------------------------------------------").append(FileUtil.getLineSeparator());
-			sb.append(DateUtil.getShotName(unit)).append("         %     Task name").append(FileUtil.getLineSeparator());
+			sb.append(DateUtil.getShotName(unit)).append("          %     Task name").append(FileUtil.getLineSeparator());
 			sb.append("---------------------------------------------").append(FileUtil.getLineSeparator());
 
 			final NumberFormat nf = NumberFormat.getNumberInstance();
-			nf.setMinimumIntegerDigits(9);
 			nf.setGroupingUsed(false);
 
 			final NumberFormat pf = NumberFormat.getPercentInstance();
-			pf.setMinimumIntegerDigits(2);
 			pf.setGroupingUsed(false);
 
 			for (final TaskInfo task : getTaskInfo()) {
-				sb.append(nf.format(task.getTime(unit))).append("  ");
-				sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append("   ");
+				final String taskTimeStr = nf.format(task.getTime(unit));
+				sb.append(taskTimeStr);
+				if(taskTimeStr.length() < 11){
+					sb.append(StrUtil.repeat(' ', 11 - taskTimeStr.length()));
+				}
+
+				final String percentStr = pf.format((double) task.getTimeNanos() / getTotalTimeNanos());
+				if(percentStr.length() < 4){
+					sb.append(StrUtil.repeat(' ', 4 - percentStr.length()));
+				}
+				sb.append(percentStr).append("   ");
 				sb.append(task.getTaskName()).append(FileUtil.getLineSeparator());
 			}
 		}
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/StopWatchTest.java b/hutool-core/src/test/java/cn/hutool/core/date/StopWatchTest.java
new file mode 100644
index 000000000..93d945d1d
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/date/StopWatchTest.java
@@ -0,0 +1,26 @@
+package cn.hutool.core.date;
+
+import cn.hutool.core.lang.Console;
+import cn.hutool.core.thread.ThreadUtil;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+public class StopWatchTest {
+
+	/**
+	 * https://gitee.com/dromara/hutool/issues/I6HSBG
+	 */
+	@Test
+	public void prettyPrintTest() {
+		final StopWatch stopWatch = new StopWatch();
+		stopWatch.start("任务1");
+		ThreadUtil.sleep(1);
+		stopWatch.stop();
+		stopWatch.start("任务2");
+		ThreadUtil.sleep(200);
+		stopWatch.stop();
+
+		Console.log(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
+	}
+}

From be5a5c411ad18133b17cc900519390c985ac27f9 Mon Sep 17 00:00:00 2001
From: wangdz50 
Date: Wed, 1 Mar 2023 13:42:25 +0800
Subject: [PATCH 053/125] =?UTF-8?q?[fixbug]:=20=20=E4=BF=AE=E5=A4=8D?=
 =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=8E=8B=E7=BC=A9=E8=87=AA=E5=8A=A8=E6=97=8B?=
 =?UTF-8?q?=E8=BD=AC=E9=97=AE=E9=A2=98=20#2923?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 hutool-swing/pom.xml                          |  5 ++
 .../cn/hutool/swing/img/ImgRevolveUtil.java   | 88 +++++++++++++++++++
 .../java/cn/hutool/swing/img/ImgUtil.java     |  2 +-
 3 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java

diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml
index 604b363ee..c1b882fa0 100755
--- a/hutool-swing/pom.xml
+++ b/hutool-swing/pom.xml
@@ -22,5 +22,10 @@
 			hutool-core
 			${project.parent.version}
 		
+		
+			com.drewnoakes
+			metadata-extractor
+			2.18.0
+		
 	
 
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java
new file mode 100644
index 000000000..42e355471
--- /dev/null
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java
@@ -0,0 +1,88 @@
+package cn.hutool.swing.img;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IORuntimeException;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.imaging.ImageProcessingException;
+import com.drew.metadata.Directory;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.Tag;
+
+/**
+ * 图片避免旋转工具类
+ *
+ *@Date: 2023/2/28 19:21
+ * @author wdz + * @since 5.8.13 + */ +public class ImgRevolveUtil { + /** + * 纠正图片旋转 + * + * @param srcFile + */ + public static BufferedImage correctBufferImg(File srcFile) throws IOException, ImageProcessingException { + // 获取偏转角度 + int angle = getAngle(srcFile); + //如果不偏转,直接返回即可 + if (angle != 90 && angle != 270) { + return ImageIO.read(srcFile); + } + + // 原始图片缓存 + BufferedImage srcImg = ImageIO.read(srcFile); + + // 宽高互换 + // 原始宽度 + int imgWidth = srcImg.getHeight(); + // 原始高度 + int imgHeight = srcImg.getWidth(); + + // 中心点位置 + double centerWidth = ((double) imgWidth) / 2; + double centerHeight = ((double) imgHeight) / 2; + + // 图片缓存 + BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); + + // 旋转对应角度 + Graphics2D g = targetImg.createGraphics(); + g.rotate(Math.toRadians(angle), centerWidth, centerHeight); + g.drawImage(srcImg, (imgWidth - srcImg.getWidth()) / 2, (imgHeight - srcImg.getHeight()) / 2, null); + g.rotate(Math.toRadians(-angle), centerWidth, centerHeight); + g.dispose(); + return targetImg; + } + + + /** + * 获取图片旋转角度 + * + * @param file 上传图片 + * @return + */ + public static int getAngle(File file) throws ImageProcessingException, IOException { + Metadata metadata = ImageMetadataReader.readMetadata(file); + for (Directory directory : metadata.getDirectories()) { + for (Tag tag : directory.getTags()) { + if ("Orientation".equals(tag.getTagName())) { + String orientation = tag.getDescription(); + if (orientation.contains("90")) { + return 90; + } else if (orientation.contains("180")) { + return 180; + } else if (orientation.contains("270")) { + return 270; + } + } + } + } + return 0; + } +} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index 1ab5ab80b..08ee070a4 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -1631,7 +1631,7 @@ public class ImgUtil { public static BufferedImage read(final File imageFile) { final BufferedImage result; try { - result = ImageIO.read(imageFile); + result = ImgRevolveUtil.correctBufferImg(imageFile); } catch (final IOException e) { throw new IORuntimeException(e); } From 0767fcd17575d60c5d02d6f97a9e711bf5775c6e Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 1 Mar 2023 18:48:32 +0800 Subject: [PATCH 054/125] add Automatic-Module-Name --- hutool-all/pom.xml | 4 ++++ hutool-core/pom.xml | 4 ++++ hutool-cron/pom.xml | 4 ++++ hutool-crypto/pom.xml | 1 + hutool-db/pom.xml | 1 + hutool-extra/pom.xml | 1 + hutool-http/pom.xml | 4 ++++ hutool-json/pom.xml | 1 + hutool-log/pom.xml | 1 + hutool-poi/pom.xml | 1 + hutool-setting/pom.xml | 4 ++++ hutool-socket/pom.xml | 4 ++++ hutool-swing/pom.xml | 4 ++++ pom.xml | 2 +- 14 files changed, 35 insertions(+), 1 deletion(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 5f87a6a2a..bef6e4634 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -17,6 +17,10 @@ Hutool是一个优雅而小巧的Java工具类库 https://github.com/looly/hutool + + cn.hutool + + cn.hutool diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 87fd312f2..261ff8b03 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -16,4 +16,8 @@ ${project.artifactId} Hutool核心,包括集合、字符串、Bean等工具 + + cn.hutool.core + + diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 56c3c955b..3ddae39f7 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -16,6 +16,10 @@ ${project.artifactId} Hutool 定时任务 + + cn.hutool.cron + + cn.hutool diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 92f9d7344..8f6f1050e 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -17,6 +17,7 @@ Hutool 加密解密 + cn.hutool.crypto 1.72 diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 23fb8f403..02d148512 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -17,6 +17,7 @@ Hutool 数据库JDBC的ORM封装 + cn.hutool.db 0.9.5.5 2.9.0 diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 11e9015a6..1a3a53e81 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -17,6 +17,7 @@ Hutool 扩展工具类(提供其它类库的封装) + cn.hutool.extra 2.3 3.14.1.RELEASE diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 850484b95..b6470b069 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -16,6 +16,10 @@ ${project.artifactId} Hutool Http客户端 + + cn.hutool.http + + cn.hutool diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index aeaa4ed89..5c1d63446 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -17,6 +17,7 @@ Hutool JSON封装 + cn.hutool.json 1.72 diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index d361408e2..c3a2f0430 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -17,6 +17,7 @@ Hutool 日志封装 + cn.hutool.log 2.0.3 diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 8c035f51e..78911842d 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -17,6 +17,7 @@ Hutool POI工具类(对Office文档、OFD等操作) + cn.hutool.poi 5.2.3 diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index d8cff59a4..62c38a6de 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -16,6 +16,10 @@ ${project.artifactId} Hutool 配置文件增强 + + cn.hutool.setting + + cn.hutool diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 1f9c38ed4..9bb0b5b37 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -16,6 +16,10 @@ ${project.artifactId} Hutool套接字,包括BIO、NIO、AIO封装 + + cn.hutool.socket + + cn.hutool diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml index 604b363ee..da2463e67 100755 --- a/hutool-swing/pom.xml +++ b/hutool-swing/pom.xml @@ -16,6 +16,10 @@ ${project.artifactId} Hutool swing桌面相关封装 + + cn.hutool.swing + + cn.hutool diff --git a/pom.xml b/pom.xml index 62a37416f..a1da7ec72 100755 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ ${user.name} ${java.version} ${maven.build.timestamp} - ${project.groupId} + ${Automatic-Module-Name} From f3da2ed20ebd6b8275b52604dfc9d7199ff2253b Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 1 Mar 2023 18:49:44 +0800 Subject: [PATCH 055/125] add Automatic-Module-Name --- hutool-all/pom.xml | 4 ---- pom.xml | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index bef6e4634..5f87a6a2a 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -17,10 +17,6 @@ Hutool是一个优雅而小巧的Java工具类库 https://github.com/looly/hutool - - cn.hutool - - cn.hutool diff --git a/pom.xml b/pom.xml index a1da7ec72..f06a4f123 100755 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ utf-8 utf-8 + cn.hutool 8 From c7f17f0119b975230a33c21eaecdfd064cfc127c Mon Sep 17 00:00:00 2001 From: wangdz50 Date: Wed, 1 Mar 2023 18:53:26 +0800 Subject: [PATCH 056/125] =?UTF-8?q?[fixbug]:=20optional=20=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=BAtrue=20=E8=A1=A8=E7=A4=BA=E8=AF=A5=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=98=AF=E5=8F=AF=E9=80=89=E7=9A=84=20=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=B9=8B=E9=97=B4=E4=BE=9D=E8=B5=96=E4=B8=8D=E4=BC=A0?= =?UTF-8?q?=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-swing/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml index c1b882fa0..c3efd8841 100755 --- a/hutool-swing/pom.xml +++ b/hutool-swing/pom.xml @@ -26,6 +26,7 @@ com.drewnoakes metadata-extractor 2.18.0 + true From 7160012e6bde4f7ff037b4127b701fe1719f2167 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 12:09:08 +0800 Subject: [PATCH 057/125] fix code --- hutool-swing/pom.xml | 3 +- .../java/cn/hutool/swing/img/ImgMetaUtil.java | 125 ++++++++++++++++++ .../cn/hutool/swing/img/ImgRevolveUtil.java | 88 ------------ .../java/cn/hutool/swing/img/ImgUtil.java | 2 +- 4 files changed, 128 insertions(+), 90 deletions(-) create mode 100644 hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java delete mode 100644 hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml index 5b088218a..c0c25192f 100755 --- a/hutool-swing/pom.xml +++ b/hutool-swing/pom.xml @@ -14,7 +14,7 @@ hutool-swing ${project.artifactId} - Hutool swing桌面相关封装 + Hutool swing桌面和图片多媒体相关封装 cn.hutool.swing @@ -26,6 +26,7 @@ hutool-core ${project.parent.version} + com.drewnoakes metadata-extractor diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java new file mode 100644 index 000000000..68a8e0594 --- /dev/null +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java @@ -0,0 +1,125 @@ +package cn.hutool.swing.img; + +import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.io.IORuntimeException; +import com.drew.imaging.ImageMetadataReader; +import com.drew.imaging.ImageProcessingException; +import com.drew.metadata.Directory; +import com.drew.metadata.Metadata; +import com.drew.metadata.Tag; + +import javax.imageio.ImageIO; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * 图片元信息工具类
+ * 借助metadata-extractor完成图片元信息的读取,如旋转角度等问题 + * + * @author wdz + * @since 5.8.13 + */ +public class ImgMetaUtil { + + /** + * 纠正图片旋转
+ * 通过读取图片元数据信息获取旋转角度,然后根据旋转角度修正图片的角度 + * + * @param f 图片文件 + * @return {@link BufferedImage} + * @throws IOException IO异常 + */ + public static BufferedImage correctBufferImg(final File file) throws IOException { + // 获取偏转角度 + final int orientation = getOrientation(file); + + + // 原始图片缓存 + final BufferedImage srcImg = ImageIO.read(file); + //如果不偏转,直接返回即可 + if (orientation != 90 && orientation != 270) { + return srcImg; + } + + + // 宽高互换 + // 原始宽度 + final int imgWidth = srcImg.getHeight(); + // 原始高度 + final int imgHeight = srcImg.getWidth(); + + // 中心点位置 + final double centerWidth = ((double) imgWidth) / 2; + final double centerHeight = ((double) imgHeight) / 2; + + // 图片缓存 + final BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); + + // 旋转对应角度 + final Graphics2D g = targetImg.createGraphics(); + g.rotate(Math.toRadians(orientation), centerWidth, centerHeight); + g.drawImage(srcImg, (imgWidth - srcImg.getWidth()) / 2, (imgHeight - srcImg.getHeight()) / 2, null); + g.rotate(Math.toRadians(-orientation), centerWidth, centerHeight); + g.dispose(); + return targetImg; + } + + /** + * 获取图片文件旋转角度 + * + * @param file 上传图片 + * @return 旋转角度 + * @throws IORuntimeException IO异常 + */ + public static int getOrientation(final File file) throws IORuntimeException { + final Metadata metadata; + try { + metadata = ImageMetadataReader.readMetadata(file); + } catch (final ImageProcessingException e) { + throw new UtilException(e); + } catch (final IOException e) { + throw new RuntimeException(e); + } + return getOrientation(metadata); + } + + /** + * 获取图片旋转角度 + * + * @param in 图片流 + * @return 旋转角度 + * @throws IORuntimeException IO异常 + */ + public static int getOrientation(final InputStream in) throws IORuntimeException { + final Metadata metadata; + try { + metadata = ImageMetadataReader.readMetadata(in); + } catch (final ImageProcessingException e) { + throw new UtilException(e); + } catch (final IOException e) { + throw new RuntimeException(e); + } + return getOrientation(metadata); + } + + private static int getOrientation(final Metadata metadata) { + for (final Directory directory : metadata.getDirectories()) { + for (final Tag tag : directory.getTags()) { + if ("Orientation".equals(tag.getTagName())) { + final String orientation = tag.getDescription(); + if (orientation.contains("90")) { + return 90; + } else if (orientation.contains("180")) { + return 180; + } else if (orientation.contains("270")) { + return 270; + } + } + } + } + return 0; + } +} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java deleted file mode 100644 index 42e355471..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgRevolveUtil.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.hutool.swing.img; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IORuntimeException; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.*; - -import com.drew.imaging.ImageMetadataReader; -import com.drew.imaging.ImageProcessingException; -import com.drew.metadata.Directory; -import com.drew.metadata.Metadata; -import com.drew.metadata.Tag; - -/** - * 图片避免旋转工具类 - * - *@Date: 2023/2/28 19:21
- * @author wdz - * @since 5.8.13 - */ -public class ImgRevolveUtil { - /** - * 纠正图片旋转 - * - * @param srcFile - */ - public static BufferedImage correctBufferImg(File srcFile) throws IOException, ImageProcessingException { - // 获取偏转角度 - int angle = getAngle(srcFile); - //如果不偏转,直接返回即可 - if (angle != 90 && angle != 270) { - return ImageIO.read(srcFile); - } - - // 原始图片缓存 - BufferedImage srcImg = ImageIO.read(srcFile); - - // 宽高互换 - // 原始宽度 - int imgWidth = srcImg.getHeight(); - // 原始高度 - int imgHeight = srcImg.getWidth(); - - // 中心点位置 - double centerWidth = ((double) imgWidth) / 2; - double centerHeight = ((double) imgHeight) / 2; - - // 图片缓存 - BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); - - // 旋转对应角度 - Graphics2D g = targetImg.createGraphics(); - g.rotate(Math.toRadians(angle), centerWidth, centerHeight); - g.drawImage(srcImg, (imgWidth - srcImg.getWidth()) / 2, (imgHeight - srcImg.getHeight()) / 2, null); - g.rotate(Math.toRadians(-angle), centerWidth, centerHeight); - g.dispose(); - return targetImg; - } - - - /** - * 获取图片旋转角度 - * - * @param file 上传图片 - * @return - */ - public static int getAngle(File file) throws ImageProcessingException, IOException { - Metadata metadata = ImageMetadataReader.readMetadata(file); - for (Directory directory : metadata.getDirectories()) { - for (Tag tag : directory.getTags()) { - if ("Orientation".equals(tag.getTagName())) { - String orientation = tag.getDescription(); - if (orientation.contains("90")) { - return 90; - } else if (orientation.contains("180")) { - return 180; - } else if (orientation.contains("270")) { - return 270; - } - } - } - } - return 0; - } -} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index 08ee070a4..1ab5ab80b 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -1631,7 +1631,7 @@ public class ImgUtil { public static BufferedImage read(final File imageFile) { final BufferedImage result; try { - result = ImgRevolveUtil.correctBufferImg(imageFile); + result = ImageIO.read(imageFile); } catch (final IOException e) { throw new IORuntimeException(e); } From 9ca5ed3592018f63165edbf4139b1bdf67fc9a05 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 12:09:23 +0800 Subject: [PATCH 058/125] fix code --- hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java index 68a8e0594..9e05bf973 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java @@ -28,7 +28,7 @@ public class ImgMetaUtil { * 纠正图片旋转
* 通过读取图片元数据信息获取旋转角度,然后根据旋转角度修正图片的角度 * - * @param f 图片文件 + * @param file 图片文件 * @return {@link BufferedImage} * @throws IOException IO异常 */ From b44fea04a3da06e727e6edb776205f171cc59ca9 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 12:09:43 +0800 Subject: [PATCH 059/125] fix code --- hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java index 9e05bf973..44a5e8f08 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java @@ -20,7 +20,7 @@ import java.io.InputStream; * 借助metadata-extractor完成图片元信息的读取,如旋转角度等问题 * * @author wdz - * @since 5.8.13 + * @since 6.0.0 */ public class ImgMetaUtil { From 0f06e591bb45c92f60af430f320aa4d5c65917a0 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 16:05:12 +0800 Subject: [PATCH 060/125] fix comment --- .../src/main/java/cn/hutool/swing/img/ImgMetaUtil.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java index 44a5e8f08..65e8bc015 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java @@ -105,6 +105,11 @@ public class ImgMetaUtil { return getOrientation(metadata); } + /** + * 获取旋转角度 + * @param metadata {@link Metadata} + * @return 旋转角度,可能为90,180,270 + */ private static int getOrientation(final Metadata metadata) { for (final Directory directory : metadata.getDirectories()) { for (final Tag tag : directory.getTags()) { From a99dd899d6bf3af1ebeb3e1d289463a3ca3e4379 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 18:03:59 +0800 Subject: [PATCH 061/125] remove compiler --- README-EN.md | 2 +- .../core/compiler/CompilerException.java | 34 --- .../cn/hutool/core/compiler/CompilerUtil.java | 80 ------ .../hutool/core/compiler/DiagnosticUtil.java | 26 -- .../core/compiler/JavaClassFileManager.java | 78 ------ .../core/compiler/JavaClassFileObject.java | 60 ----- .../core/compiler/JavaFileObjectUtil.java | 112 --------- .../core/compiler/JavaSourceCompiler.java | 234 ------------------ .../core/compiler/JavaSourceFileObject.java | 90 ------- .../cn/hutool/core/compiler/package-info.java | 6 - .../core/compiler/JavaSourceCompilerTest.java | 53 ---- .../test/resources/test-compile/a/A$1.class | Bin 1679 -> 0 bytes .../test-compile/a/A$InnerClass.class | Bin 447 -> 0 bytes .../src/test/resources/test-compile/a/A.class | Bin 357 -> 0 bytes .../src/test/resources/test-compile/a/A.java | 22 -- .../src/test/resources/test-compile/b/B.class | Bin 260 -> 0 bytes .../src/test/resources/test-compile/b/B.java | 8 - .../src/test/resources/test-compile/c/C.class | Bin 260 -> 0 bytes .../src/test/resources/test-compile/c/C.java | 9 - 19 files changed, 1 insertion(+), 813 deletions(-) delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/CompilerException.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/CompilerUtil.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/DiagnosticUtil.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileManager.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileObject.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/JavaFileObjectUtil.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceCompiler.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceFileObject.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/compiler/package-info.java delete mode 100644 hutool-core/src/test/java/cn/hutool/core/compiler/JavaSourceCompilerTest.java delete mode 100644 hutool-core/src/test/resources/test-compile/a/A$1.class delete mode 100644 hutool-core/src/test/resources/test-compile/a/A$InnerClass.class delete mode 100644 hutool-core/src/test/resources/test-compile/a/A.class delete mode 100755 hutool-core/src/test/resources/test-compile/a/A.java delete mode 100644 hutool-core/src/test/resources/test-compile/b/B.class delete mode 100644 hutool-core/src/test/resources/test-compile/b/B.java delete mode 100644 hutool-core/src/test/resources/test-compile/c/C.class delete mode 100644 hutool-core/src/test/resources/test-compile/c/C.java diff --git a/README-EN.md b/README-EN.md index 20d702170..545f935ea 100755 --- a/README-EN.md +++ b/README-EN.md @@ -51,7 +51,7 @@ ------------------------------------------------------------------------------- ## 📚Introduction -**Hutool** is a small but comprehensive library of Java tools, encapsulation by static methods, reduce the cost of learning related APIs, increase productivity, and make Java as elegant as a functional programming language,let the Java be "sweet" too. +**Hutool** is a small but comprehensive library of Java tools, achieved by encapsulation through static methods, reduce the cost of learning related APIs, increase productivity, and make Java as elegant as a functional programming language,let the Java be "sweet" too. **Hutool** tools and methods from each user's crafted, it covers all aspects of the underlying code of Java development, it is a powerful tool for large project development to solve small problems, but also the efficiency of small projects; diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerException.java b/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerException.java deleted file mode 100644 index 1455a4c7c..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerException.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.text.StrUtil; - -/** - * 编译异常 - * - * @author looly - * @since 5.5.2 - */ -public class CompilerException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public CompilerException(final Throwable e) { - super(ExceptionUtil.getMessage(e), e); - } - - public CompilerException(final String message) { - super(message); - } - - public CompilerException(final String messageTemplate, final Object... params) { - super(StrUtil.format(messageTemplate, params)); - } - - public CompilerException(final String message, final Throwable throwable) { - super(message, throwable); - } - - public CompilerException(final Throwable throwable, final String messageTemplate, final Object... params) { - super(StrUtil.format(messageTemplate, params), throwable); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerUtil.java b/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerUtil.java deleted file mode 100644 index 5e50df3d2..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/CompilerUtil.java +++ /dev/null @@ -1,80 +0,0 @@ -package cn.hutool.core.compiler; - -import javax.tools.DiagnosticListener; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -/** - * 源码编译工具类,主要封装{@link JavaCompiler} 相关功能 - * - * @author looly - * @since 5.5.2 - */ -public class CompilerUtil { - - /** - * java 编译器 - */ - public static final JavaCompiler SYSTEM_COMPILER = ToolProvider.getSystemJavaCompiler(); - - /** - * 编译指定的源码文件 - * - * @param sourceFiles 源码文件路径 - * @return 0表示成功,否则其他 - */ - public static boolean compile(final String... sourceFiles) { - return 0 == SYSTEM_COMPILER.run(null, null, null, sourceFiles); - } - - /** - * 获取{@link StandardJavaFileManager} - * - * @return {@link StandardJavaFileManager} - */ - public static StandardJavaFileManager getFileManager() { - return getFileManager(null); - } - - /** - * 获取{@link StandardJavaFileManager} - * - * @param diagnosticListener 异常收集器 - * @return {@link StandardJavaFileManager} - * @since 5.5.8 - */ - public static StandardJavaFileManager getFileManager(final DiagnosticListener diagnosticListener) { - return SYSTEM_COMPILER.getStandardFileManager(diagnosticListener, null, null); - } - - /** - * 新建编译任务 - * - * @param fileManager {@link JavaFileManager},用于管理已经编译好的文件 - * @param diagnosticListener 诊断监听 - * @param options 选项,例如 -cpXXX等 - * @param compilationUnits 编译单元,即需要编译的对象 - * @return {@link JavaCompiler.CompilationTask} - */ - public static JavaCompiler.CompilationTask getTask( - final JavaFileManager fileManager, - final DiagnosticListener diagnosticListener, - final Iterable options, - final Iterable compilationUnits) { - return SYSTEM_COMPILER.getTask(null, fileManager, diagnosticListener, options, null, compilationUnits); - } - - /** - * 获取{@link JavaSourceCompiler} - * - * @param parent 父{@link ClassLoader} - * @return {@link JavaSourceCompiler} - * @see JavaSourceCompiler#of(ClassLoader) - */ - public static JavaSourceCompiler getCompiler(final ClassLoader parent) { - return JavaSourceCompiler.of(parent); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/DiagnosticUtil.java b/hutool-core/src/main/java/cn/hutool/core/compiler/DiagnosticUtil.java deleted file mode 100644 index 07d93f221..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/DiagnosticUtil.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.hutool.core.compiler; - -import javax.tools.DiagnosticCollector; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 诊断工具类 - * - * @author looly - * @since 5.5.2 - */ -public class DiagnosticUtil { - - /** - * 获取{@link DiagnosticCollector}收集到的诊断信息,以文本返回 - * - * @param collector {@link DiagnosticCollector} - * @return 诊断消息 - */ - public static String getMessages(final DiagnosticCollector collector) { - final List diagnostics = collector.getDiagnostics(); - return diagnostics.stream().map(String::valueOf) - .collect(Collectors.joining(System.lineSeparator())); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileManager.java b/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileManager.java deleted file mode 100644 index 7c8f79314..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileManager.java +++ /dev/null @@ -1,78 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.io.resource.FileObjectResource; -import cn.hutool.core.classloader.ResourceClassLoader; -import cn.hutool.core.classloader.ClassLoaderUtil; -import cn.hutool.core.util.ObjUtil; - -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import java.util.HashMap; -import java.util.Map; - -/** - * Java 字节码文件对象管理器 - * - *

- * 正常我们使用javac命令编译源码时会将class文件写入到磁盘中,但在运行时动态编译类不适合保存在磁盘中 - * 我们采取此对象来管理运行时动态编译类生成的字节码。 - *

- * - * @author lzpeng - * @since 5.5.2 - */ -class JavaClassFileManager extends ForwardingJavaFileManager { - - /** - * 存储java字节码文件对象映射 - */ - private final Map classFileObjectMap = new HashMap<>(); - - /** - * 加载动态编译生成类的父类加载器 - */ - private final ClassLoader parent; - - /** - * 构造 - * - * @param parent 父类加载器 - * @param fileManager 字节码文件管理器 - */ - protected JavaClassFileManager(final ClassLoader parent, final JavaFileManager fileManager) { - super(fileManager); - this.parent = ObjUtil.defaultIfNull(parent, ClassLoaderUtil::getClassLoader); - } - - /** - * 获得动态编译生成的类的类加载器 - * - * @param location 源码位置 - * @return 动态编译生成的类的类加载器 - */ - @Override - public ClassLoader getClassLoader(final Location location) { - return new ResourceClassLoader<>(this.parent, this.classFileObjectMap); - } - - /** - * 获得Java字节码文件对象 - * 编译器编译源码时会将Java源码对象编译转为Java字节码对象 - * - * @param location 源码位置 - * @param className 类名 - * @param kind 文件类型 - * @param sibling Java源码对象 - * @return Java字节码文件对象 - */ - @Override - public JavaFileObject getJavaFileForOutput(final Location location, final String className, final Kind kind, final FileObject sibling) { - final JavaFileObject javaFileObject = new JavaClassFileObject(className); - this.classFileObjectMap.put(className, new FileObjectResource(javaFileObject)); - return javaFileObject; - } - -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileObject.java b/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileObject.java deleted file mode 100644 index 6db6d22f9..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaClassFileObject.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.hutool.core.compiler; - - -import cn.hutool.core.util.CharUtil; -import cn.hutool.core.net.url.URLUtil; - -import javax.tools.SimpleJavaFileObject; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Java 字节码文件对象,用于在内存中暂存class字节码,从而可以在ClassLoader中动态加载。 - * - * @author lzpeng - * @since 5.5.2 - */ -class JavaClassFileObject extends SimpleJavaFileObject { - - /** - * 字节码输出流 - */ - private final ByteArrayOutputStream byteArrayOutputStream; - - /** - * 构造 - * - * @param className 编译后的class文件的类名 - * @see JavaClassFileManager#getJavaFileForOutput(javax.tools.JavaFileManager.Location, java.lang.String, javax.tools.JavaFileObject.Kind, javax.tools.FileObject) - */ - protected JavaClassFileObject(final String className) { - super(URLUtil.getStringURI(className.replace(CharUtil.DOT, CharUtil.SLASH) + Kind.CLASS.extension), Kind.CLASS); - this.byteArrayOutputStream = new ByteArrayOutputStream(); - } - - /** - * 获得字节码输入流 - * 编译器编辑源码后,我们将通过此输出流获得编译后的字节码,以便运行时加载类 - * - * @return 字节码输入流 - * @see JavaClassFileManager#getClassLoader(javax.tools.JavaFileManager.Location) - */ - @Override - public InputStream openInputStream() { - return new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); - } - - /** - * 获得字节码输出流 - * 编译器编辑源码时,会将编译结果输出到本输出流中 - * - * @return 字节码输出流 - */ - @Override - public OutputStream openOutputStream() { - return this.byteArrayOutputStream; - } - -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaFileObjectUtil.java b/hutool-core/src/main/java/cn/hutool/core/compiler/JavaFileObjectUtil.java deleted file mode 100644 index 7e06b3011..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaFileObjectUtil.java +++ /dev/null @@ -1,112 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.file.FileNameUtil; -import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.resource.FileResource; -import cn.hutool.core.io.resource.Resource; - -import javax.tools.JavaFileObject; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.ZipFile; - -/** - * {@link JavaFileObject} 相关工具类封装 - * - * @author lzpeng, looly - * @since 5.5.2 - */ -public class JavaFileObjectUtil { - - /** - * 获取指定资源下的所有待编译的java源码文件,并以{@link JavaFileObject}形式返回 - *
    - *
  • 如果资源为目录,则遍历目录找到目录中的.java或者.jar等文件加载之
  • - *
  • 如果资源为.jar或.zip等,解压读取其中的.java文件加载之
  • - *
  • 其他情况直接读取资源流并加载之
  • - *
- * - * @param resource 资源,可以为目录、文件或流 - * @return 所有待编译的 {@link JavaFileObject} - */ - public static List getJavaFileObjects(final Resource resource) { - final List result = new ArrayList<>(); - - if (resource instanceof FileResource) { - final File file = ((FileResource) resource).getFile(); - result.addAll(JavaFileObjectUtil.getJavaFileObjects(file)); - } else { - result.add(new JavaSourceFileObject(resource.getName(), resource.getStream())); - } - - return result; - } - - /** - * 获取指定文件下的所有待编译的java文件,并以{@link JavaFileObject}形式返回 - *
    - *
  • 如果文件为目录,则遍历目录找到目录中的.java或者.jar等文件加载之
  • - *
  • 如果文件为.jar或.zip等,解压读取其中的.java文件加载之
  • - *
- * - * @param file 文件或目录,文件支持.java、.jar和.zip文件 - * @return 所有待编译的 {@link JavaFileObject} - */ - public static List getJavaFileObjects(final File file) { - final List result = new ArrayList<>(); - if (file.isDirectory()) { - FileUtil.walkFiles(file, (subFile) -> result.addAll(getJavaFileObjects(file))); - } else { - final String fileName = file.getName(); - if (isJavaFile(fileName)) { - result.add(new JavaSourceFileObject(file.toURI())); - } else if (isJarOrZipFile(fileName)) { - result.addAll(getJavaFileObjectByZipOrJarFile(file)); - } - } - - return result; - } - - /** - * 是否是jar 或 zip 文件
- * 通过扩展名判定 - * - * @param fileName 文件名 - * @return 是否是jar 或 zip 文件 - */ - public static boolean isJarOrZipFile(final String fileName) { - return FileNameUtil.isType(fileName, "jar", "zip"); - } - - /** - * 是否是java文件
- * 通过扩展名判定 - * - * @param fileName 文件名 - * @return 是否是.java文件 - */ - public static boolean isJavaFile(final String fileName) { - return FileNameUtil.isType(fileName, "java"); - } - - /** - * 通过zip包或jar包创建Java文件对象 - * - * @param file 压缩文件 - * @return Java文件对象 - */ - private static List getJavaFileObjectByZipOrJarFile(final File file) { - final List collection = new ArrayList<>(); - final ZipFile zipFile = ZipUtil.toZipFile(file, null); - ZipUtil.read(zipFile, (zipEntry) -> { - final String name = zipEntry.getName(); - if (isJavaFile(name)) { - collection.add(new JavaSourceFileObject(name, ZipUtil.getStream(zipFile, zipEntry))); - } - }); - return collection; - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceCompiler.java b/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceCompiler.java deleted file mode 100644 index af7faace9..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceCompiler.java +++ /dev/null @@ -1,234 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.classloader.ClassLoaderUtil; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.io.resource.FileResource; -import cn.hutool.core.io.resource.Resource; -import cn.hutool.core.io.resource.StringResource; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.net.url.URLUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjUtil; - -import javax.tools.DiagnosticCollector; -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * Java 源码编译器 - *

通过此类可以动态编译java源码,并加载到ClassLoader,从而动态获取加载的类。

- *

JavaSourceCompiler支持加载的源码类型包括:

- *
    - *
  • 源码文件
  • - *
  • 源码文件源码字符串
  • - *
- * - *

使用方法如下:

- *
- *     ClassLoader classLoader = JavaSourceCompiler.create(null)
- *         .addSource(FileUtil.file("test-compile/b/B.java"))
- *         .addSource("c.C", FileUtil.readUtf8String("test-compile/c/C.java"))
- *         // 增加编译依赖的类库
- *         .addLibrary(libFile)
- *         .compile();
- *     Class<?> clazz = classLoader.loadClass("c.C");
- * 
- * - * @author lzpeng - */ -public class JavaSourceCompiler { - - /** - * 待编译的资源,支持: - * - *
    - *
  • 源码字符串,使用{@link StringResource}
  • - *
  • 源码文件、源码jar包或源码zip包,亦或者文件夹,使用{@link FileResource}
  • - *
- * 可以是 .java文件 压缩文件 文件夹 递归搜索文件夹内的zip包和jar包 - */ - private final List sourceList = new ArrayList<>(); - - /** - * 编译时需要加入classpath中的文件 可以是 压缩文件 文件夹递归搜索文件夹内的zip包和jar包 - */ - private final List libraryFileList = new ArrayList<>(); - - /** - * 编译类时使用的父类加载器 - */ - private final ClassLoader parentClassLoader; - - /** - * 创建Java源码编译器 - * - * @param parent 父类加载器 - * @return Java源码编译器 - */ - public static JavaSourceCompiler of(final ClassLoader parent) { - return new JavaSourceCompiler(parent); - } - - /** - * 构造 - * - * @param parent 父类加载器,null则使用默认类加载器 - */ - private JavaSourceCompiler(final ClassLoader parent) { - this.parentClassLoader = ObjUtil.defaultIfNull(parent, ClassLoaderUtil::getClassLoader); - } - - /** - * 向编译器中加入待编译的资源
- * 支持 .java, 文件夹, 压缩文件 递归搜索文件夹内的压缩文件和jar包 - * - * @param resources 待编译的资源,支持 .java, 文件夹, 压缩文件 递归搜索文件夹内的压缩文件和jar包 - * @return Java源码编译器 - */ - public JavaSourceCompiler addSource(final Resource... resources) { - if (ArrayUtil.isNotEmpty(resources)) { - this.sourceList.addAll(Arrays.asList(resources)); - } - return this; - } - - /** - * 向编译器中加入待编译的文件
- * 支持 .java, 文件夹, 压缩文件 递归搜索文件夹内的压缩文件和jar包 - * - * @param files 待编译的文件 支持 .java, 文件夹, 压缩文件 递归搜索文件夹内的压缩文件和jar包 - * @return Java源码编译器 - */ - public JavaSourceCompiler addSource(final File... files) { - if (ArrayUtil.isNotEmpty(files)) { - for (final File file : files) { - this.sourceList.add(new FileResource(file)); - } - } - return this; - } - - /** - * 向编译器中加入待编译的源码Map - * - * @param sourceCodeMap 源码Map key: 类名 value 源码 - * @return Java源码编译器 - */ - public JavaSourceCompiler addSource(final Map sourceCodeMap) { - if (MapUtil.isNotEmpty(sourceCodeMap)) { - sourceCodeMap.forEach(this::addSource); - } - return this; - } - - /** - * 向编译器中加入待编译的源码 - * - * @param className 类名 - * @param sourceCode 源码 - * @return Java文件编译器 - */ - public JavaSourceCompiler addSource(final String className, final String sourceCode) { - if (className != null && sourceCode != null) { - this.sourceList.add(new StringResource(sourceCode, className)); - } - return this; - } - - /** - * 加入编译Java源码时所需要的jar包,jar包中必须为字节码 - * - * @param files 编译Java源码时所需要的jar包 - * @return Java源码编译器 - */ - public JavaSourceCompiler addLibrary(final File... files) { - if (ArrayUtil.isNotEmpty(files)) { - this.libraryFileList.addAll(Arrays.asList(files)); - } - return this; - } - - /** - * 编译所有文件并返回类加载器 - * - * @return 类加载器 - */ - public ClassLoader compile() { - // 获得classPath - final List classPath = getClassPath(); - final URL[] urLs = URLUtil.getURLs(classPath.toArray(new File[0])); - final URLClassLoader ucl = URLClassLoader.newInstance(urLs, this.parentClassLoader); - if (sourceList.isEmpty()) { - // 没有需要编译的源码文件返回加载zip或jar包的类加载器 - return ucl; - } - - // 创建编译器 - final JavaClassFileManager javaFileManager = new JavaClassFileManager(ucl, CompilerUtil.getFileManager()); - - // classpath - final List options = new ArrayList<>(); - if (false == classPath.isEmpty()) { - final List cp = CollUtil.map(classPath, File::getAbsolutePath, true); - options.add("-cp"); - options.add(CollUtil.join(cp, FileUtil.isWindows() ? ";" : ":")); - } - - // 编译文件 - final DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>(); - final List javaFileObjectList = getJavaFileObject(); - final CompilationTask task = CompilerUtil.getTask(javaFileManager, diagnosticCollector, options, javaFileObjectList); - try { - if (task.call()) { - // 加载编译后的类 - return javaFileManager.getClassLoader(StandardLocation.CLASS_OUTPUT); - } - } finally { - IoUtil.close(javaFileManager); - } - //编译失败,收集错误信息 - throw new CompilerException(DiagnosticUtil.getMessages(diagnosticCollector)); - } - - /** - * 获得编译源码时需要的classpath - * - * @return 编译源码时需要的classpath - */ - private List getClassPath() { - final List classPathFileList = new ArrayList<>(); - for (final File file : libraryFileList) { - final List jarOrZipFile = FileUtil.loopFiles(file, (subFile) -> JavaFileObjectUtil.isJarOrZipFile(subFile.getName())); - classPathFileList.addAll(jarOrZipFile); - if (file.isDirectory()) { - classPathFileList.add(file); - } - } - return classPathFileList; - } - - /** - * 获得待编译的Java文件对象 - * - * @return 待编译的Java文件对象 - */ - private List getJavaFileObject() { - final List list = new ArrayList<>(); - - for (final Resource resource : this.sourceList) { - list.addAll(JavaFileObjectUtil.getJavaFileObjects(resource)); - } - - return list; - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceFileObject.java b/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceFileObject.java deleted file mode 100644 index d4d2ea4a7..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/JavaSourceFileObject.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.CharUtil; -import cn.hutool.core.net.url.URLUtil; - -import javax.tools.SimpleJavaFileObject; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.nio.charset.Charset; - -/** - * Java 源码文件对象,支持:
- *
    - *
  1. 源文件,通过文件的uri传入
  2. - *
  3. 代码内容,通过流传入
  4. - *
- * - * @author lzpeng - * @since 5.5.2 - */ -class JavaSourceFileObject extends SimpleJavaFileObject { - - /** - * 输入流 - */ - private InputStream inputStream; - - /** - * 构造,支持File等路径类型的源码 - * - * @param uri 需要编译的文件uri - */ - protected JavaSourceFileObject(final URI uri) { - super(uri, Kind.SOURCE); - } - - /** - * 构造,支持String类型的源码 - * - * @param className 需要编译的类名 - * @param code 需要编译的类源码 - */ - protected JavaSourceFileObject(final String className, final String code, final Charset charset) { - this(className, IoUtil.toStream(code, charset)); - } - - /** - * 构造,支持流中读取源码(例如zip或网络等) - * - * @param name 需要编译的文件名 - * @param inputStream 输入流 - */ - protected JavaSourceFileObject(final String name, final InputStream inputStream) { - this(URLUtil.getStringURI(name.replace(CharUtil.DOT, CharUtil.SLASH) + Kind.SOURCE.extension)); - this.inputStream = inputStream; - } - - /** - * 获得类源码的输入流 - * - * @return 类源码的输入流 - * @throws IOException IO 异常 - */ - @Override - public InputStream openInputStream() throws IOException { - if (inputStream == null) { - inputStream = toUri().toURL().openStream(); - } - return new BufferedInputStream(inputStream); - } - - /** - * 获得类源码 - * 编译器编辑源码前,会通过此方法获取类的源码 - * - * @param ignoreEncodingErrors 是否忽略编码错误 - * @return 需要编译的类的源码 - * @throws IOException IO异常 - */ - @Override - public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws IOException { - try(final InputStream in = openInputStream()){ - return IoUtil.readUtf8(in); - } - } - -} diff --git a/hutool-core/src/main/java/cn/hutool/core/compiler/package-info.java b/hutool-core/src/main/java/cn/hutool/core/compiler/package-info.java deleted file mode 100644 index a0f3ef2b4..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/compiler/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 运行时编译java源码,动态从字符串或外部文件加载类 - * - * @author : Lzpeng - */ -package cn.hutool.core.compiler; \ No newline at end of file diff --git a/hutool-core/src/test/java/cn/hutool/core/compiler/JavaSourceCompilerTest.java b/hutool-core/src/test/java/cn/hutool/core/compiler/JavaSourceCompilerTest.java deleted file mode 100644 index ce97e0236..000000000 --- a/hutool-core/src/test/java/cn/hutool/core/compiler/JavaSourceCompilerTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.hutool.core.compiler; - -import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Console; -import cn.hutool.core.reflect.ConstructorUtil; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; -import java.io.InputStream; - -/** - * Java源码编译器测试 - * - * @author lzpeng - */ -public class JavaSourceCompilerTest { - - @Test - @Ignore - public void compilerATest(){ - final boolean compile = CompilerUtil.compile(FileUtil.file("test-compile/a/A.java").getAbsolutePath()); - Assert.assertTrue(compile); - } - - /** - * 测试编译Java源码 - */ - @Test - public void testCompile() throws ClassNotFoundException { - // 依赖A,编译B和C - final File libFile = ZipUtil.zip(FileUtil.file("lib.jar"), - new String[]{"a/A.class", "a/A$1.class", "a/A$InnerClass.class"}, - new InputStream[]{ - FileUtil.getInputStream("test-compile/a/A.class"), - FileUtil.getInputStream("test-compile/a/A$1.class"), - FileUtil.getInputStream("test-compile/a/A$InnerClass.class") - }); - Console.log(libFile.getAbsolutePath()); - final ClassLoader classLoader = CompilerUtil.getCompiler(null) - .addSource(FileUtil.file("test-compile/b/B.java")) - .addSource("c.C", FileUtil.readUtf8String("test-compile/c/C.java")) - .addLibrary(libFile) -// .addLibrary(FileUtil.file("D:\\m2_repo\\cn\\hutool\\hutool-all\\5.5.7\\hutool-all-5.5.7.jar")) - .compile(); - final Class clazz = classLoader.loadClass("c.C"); - final Object obj = ConstructorUtil.newInstance(clazz); - Assert.assertTrue(String.valueOf(obj).startsWith("c.C@")); - } - -} diff --git a/hutool-core/src/test/resources/test-compile/a/A$1.class b/hutool-core/src/test/resources/test-compile/a/A$1.class deleted file mode 100644 index 78aff511d2899e9b4560c2ec7a0e5d2260291e01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1679 zcma)6TW=dh6#gb&XPxah7dvj_kb)^`vE7TCQYgeBkeHT+I!VE;gDJO-JxMm*>{|A^ zC=xG}J|Hd<5(o(-B;MM`wi27DQTmF+FX#`zO8FC%GrJ9r(^kdnotZsz<~!dxbI$qm zpF4K}oWzQX4u+tfnHU~Xp)hpI<&C#5`XWl1n*ScWss5Kej$ zZ%7pxl$>1=U0~S55k#kk0Kyz9x)}yqsyo25siKBnL{#)K94uRzrG{hMW~OY{M8?#u z#Y|Z@O;O9_yy>E2m>f~`GjuHq#}_j6C#O>RW&MioAMt2sRqSO*JPtBvTXowM7xZ~k zXoz7zQj9YMlBuGKXBc{0SOuqMSc@U-C$G0|Z8X3CE`;Y8xLkkz+x^YW=Fc}I#`7Ep z@B-1&E0wcCuZSAMspO>{tbC+wD*rS}*)AN!iz*Ja6Irc0Vud4#6fw0M4nxdGH|)%L zBI%F;p|6nNhZ*+m_F%GMm_#asqYPT}t6!VfziEE^Q$j-;8R5nG#JtdJodXs~oRkltQRitHP=<9NlTlN2AC*fpj*6F@{KD z>z8ZyZ+^M;vA!ZjC4*f58$8+p$O3sNRAdhzBw6aiBh&+!LGKh@sb8QBeLJqtuRv0uEIsh_glE{>ZgaJ| zZMT0n>R5W5tcMGZUcNl7S3Pw|KJq)X^kKFJ9vI)hj-F9v z1F_N?_KgPP!QdtaOM%Exp`=8fEx1U`-Nx_+(xu3eH5^O37;$kbl6CRAi#J`obseeg zLvdvtQ*B}Ivx;wrwXQGf&MhjsAPhgSO80;(E$U?G%HxZ04~!iLNXas`3sQLM906$ C`lH|g diff --git a/hutool-core/src/test/resources/test-compile/a/A$InnerClass.class b/hutool-core/src/test/resources/test-compile/a/A$InnerClass.class deleted file mode 100644 index ad922c85f0fb829e396f11664d0b3fcf6ce9f8f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmZut%SyvQ6g@XdlQzaS)>nNjToma8j0<;)Pzr(&bfI)Vjf1Ad1d`PMav=p5et;h( z-Wv-Qk%2oiXU;w6p85QG{{V1?Lk9+-se)1WI!$#xPE=7iun7K4y{I5j>0@v^o$06~ z*yU4PbWaJjkQ>e!xQNrZyd>0n71Ey&ta0|B8z8KCsKIt&V%>v-Cc*3pp%uodzL`Hy zb$+j=i6*qeEK8n@_?9qv& zA$Y5hnq%(sOf1jr6^xdZNC_{L=c@3rEzxZ2DCbA7H} ob#}3VHUx06xl}mjesQn|!v(hf?-mCGJ5}99hj&Rw*uw#gZWmnT8N58#Iq zXIG(nc#nC^Z)W!U=i>{&84f~tgr3Z1A$-DUDPLt)N%NH56-!ligy2FO-Cc6i-~r1aV)lno?bB3k0(hdmJIUF-A4>O17y5To*V5pU!^;JC8=d z8gg~TDY3`XcWit@OxdG14m=E569) caller = CallerUtil.getCaller(i); - while (caller != null) { - Console.log("{} {}", caller, caller.getClassLoader()); - caller = CallerUtil.getCaller(++i); - } - }}; - } -} diff --git a/hutool-core/src/test/resources/test-compile/b/B.class b/hutool-core/src/test/resources/test-compile/b/B.class deleted file mode 100644 index ed23f2757a9207be24aebd5d9d31f9ffe7bb315a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 260 zcmXYryH3ME5Jk^8evpkxLihqYpui0s4=F)PWrYHier;B;k+CJ?@LyDsK;i@VD8x9T zxubjc+}Zj0{rm4J!{hZww8&`HheC=!B-70i?wid#>=E)fb z3{xWFgpt13Y;G_Ng-Pyfx7xlIu6?vc<%C(@l(t&i*7yED47(TqCPcY@d?lENX4{r- z>H9*wxahCo1l_DhqEk^~)kNLR-oxm8$H5n7NBW_0z@h4RUx^46H;RunOSPal6Q(+a IBh`S}AMYY6h5!Hn diff --git a/hutool-core/src/test/resources/test-compile/b/B.java b/hutool-core/src/test/resources/test-compile/b/B.java deleted file mode 100644 index 84c294dea..000000000 --- a/hutool-core/src/test/resources/test-compile/b/B.java +++ /dev/null @@ -1,8 +0,0 @@ -package b; -import a.A; - -public class B { - public B() { - new A(); - } -} \ No newline at end of file diff --git a/hutool-core/src/test/resources/test-compile/c/C.class b/hutool-core/src/test/resources/test-compile/c/C.class deleted file mode 100644 index 42966eed7c45baee48b4b4abc8ec58ea94e8442a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 260 zcmXYry-veG5QM*VoO5z9B!nlR0}9;G@l#-l%7Oxv{%lTgk+CJ?@Lp7rK;i*-D8xFV znbGXd?9R{c=QnW9VL~K~sw_{4g~i&vyR3H2b9P^@ebo!*GBlyTR@3pxN{I9J$y-KD zQ^uHtnQqGL#$uTY^CC3 Date: Fri, 3 Mar 2023 18:55:29 +0800 Subject: [PATCH 062/125] fix code --- .../main/java/cn/hutool/swing/img/Img.java | 4 ++ .../java/cn/hutool/swing/img/ImgMetaUtil.java | 46 ------------------- .../java/cn/hutool/swing/img/ImgUtilTest.java | 13 ++++++ 3 files changed, 17 insertions(+), 46 deletions(-) diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java index c9a033881..6520e75a6 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java @@ -597,6 +597,10 @@ public class Img implements Serializable { * @since 3.2.2 */ public Img rotate(final int degree) { + if(0 == degree){ + // 不旋转 + return this; + } final Image image = getValidSrcImg(); final int width = image.getWidth(null); final int height = image.getHeight(null); diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java index 65e8bc015..397781e5d 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgMetaUtil.java @@ -8,9 +8,6 @@ import com.drew.metadata.Directory; import com.drew.metadata.Metadata; import com.drew.metadata.Tag; -import javax.imageio.ImageIO; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -24,49 +21,6 @@ import java.io.InputStream; */ public class ImgMetaUtil { - /** - * 纠正图片旋转
- * 通过读取图片元数据信息获取旋转角度,然后根据旋转角度修正图片的角度 - * - * @param file 图片文件 - * @return {@link BufferedImage} - * @throws IOException IO异常 - */ - public static BufferedImage correctBufferImg(final File file) throws IOException { - // 获取偏转角度 - final int orientation = getOrientation(file); - - - // 原始图片缓存 - final BufferedImage srcImg = ImageIO.read(file); - //如果不偏转,直接返回即可 - if (orientation != 90 && orientation != 270) { - return srcImg; - } - - - // 宽高互换 - // 原始宽度 - final int imgWidth = srcImg.getHeight(); - // 原始高度 - final int imgHeight = srcImg.getWidth(); - - // 中心点位置 - final double centerWidth = ((double) imgWidth) / 2; - final double centerHeight = ((double) imgHeight) / 2; - - // 图片缓存 - final BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); - - // 旋转对应角度 - final Graphics2D g = targetImg.createGraphics(); - g.rotate(Math.toRadians(orientation), centerWidth, centerHeight); - g.drawImage(srcImg, (imgWidth - srcImg.getWidth()) / 2, (imgHeight - srcImg.getHeight()) / 2, null); - g.rotate(Math.toRadians(-orientation), centerWidth, centerHeight); - g.dispose(); - return targetImg; - } - /** * 获取图片文件旋转角度 * diff --git a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java index 13ce5507f..47dcd5fdd 100755 --- a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java +++ b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java @@ -2,6 +2,7 @@ package cn.hutool.swing.img; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.lang.Console; import cn.hutool.swing.img.color.ColorUtil; import org.junit.Assert; import org.junit.Ignore; @@ -170,4 +171,16 @@ public class ImgUtilTest { ImageIO.createImageOutputStream(new File("d:/test/createTransparentImageTest.png")) ); } + + @Test + @Ignore + public void issue2765Test() { + // 利用图片元数据工具读取图片旋转角度信息 + final File file = FileUtil.file("d:/test/204691690-715c29d9-793a-4b29-ab1d-191a741438bb.jpg"); + final int orientation = ImgMetaUtil.getOrientation(file); + Console.log(orientation); + Img.from(file) + .rotate(orientation) + .write(FileUtil.file("d:/test/aaa.jpg")); + } } From 201fe2404f64db0d189859a84f97255a9d6d5c6a Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 19:03:48 +0800 Subject: [PATCH 063/125] add test --- .../java/cn/hutool/http/Issue2901Test.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 hutool-http/src/test/java/cn/hutool/http/Issue2901Test.java diff --git a/hutool-http/src/test/java/cn/hutool/http/Issue2901Test.java b/hutool-http/src/test/java/cn/hutool/http/Issue2901Test.java new file mode 100644 index 000000000..58d7e43a1 --- /dev/null +++ b/hutool-http/src/test/java/cn/hutool/http/Issue2901Test.java @@ -0,0 +1,30 @@ +package cn.hutool.http; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.resource.FileResource; +import cn.hutool.core.io.resource.HttpResource; +import cn.hutool.core.lang.Console; +import cn.hutool.http.client.Request; +import cn.hutool.http.client.Response; +import cn.hutool.http.client.body.ResourceBody; +import cn.hutool.http.meta.ContentType; +import cn.hutool.http.meta.Method; +import org.junit.Ignore; +import org.junit.Test; + +public class Issue2901Test { + + @Test + @Ignore + public void bodyTest() { + // 自定义请求体,请求体作为资源读取,解决一次性读取到内存的问题 + final Response res = Request.of("http://localhost:8888/restTest") + .method(Method.POST) + .body(new ResourceBody( + new HttpResource(new FileResource("d:/test/test.jpg"), ContentType.OCTET_STREAM.getValue()))) + .send(); + + Console.log(res.bodyStr()); + IoUtil.close(res); + } +} From 772d80a8be2936ccb60816ee8f17f480bf948464 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 20:59:17 +0800 Subject: [PATCH 064/125] fix code --- .../main/java/cn/hutool/core/io/FileTypeUtil.java | 3 +-- .../src/main/java/cn/hutool/core/io/FileUtil.java | 1 + .../src/main/java/cn/hutool/core/io/IoUtil.java | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java index cebe88de8..cb7d25f5b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java @@ -4,7 +4,6 @@ import cn.hutool.core.codec.HexUtil; import cn.hutool.core.text.StrUtil; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; @@ -194,7 +193,7 @@ public class FileTypeUtil { * @throws IORuntimeException 读取文件引起的异常 */ public static String getType(File file,boolean isExact) throws IORuntimeException { - FileInputStream in = null; + InputStream in = null; try { in = IoUtil.toStream(file); return getType(in, file.getName(),isExact); diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 15a1a4941..33016d60b 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -1763,6 +1763,7 @@ public class FileUtil extends PathUtil { * @param file 文件 * @return 输入流 * @throws IORuntimeException 文件未找到 + * @see IoUtil#toStream(File) */ public static BufferedInputStream getInputStream(final File file) throws IORuntimeException { return IoUtil.toBuffered(IoUtil.toStream(file)); diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java index 739b68437..adf81e8c2 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java @@ -23,7 +23,6 @@ import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.Flushable; import java.io.IOException; @@ -38,6 +37,7 @@ import java.io.UnsupportedEncodingException; import java.io.Writer; import java.nio.CharBuffer; import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.Collection; import java.util.Objects; @@ -525,15 +525,15 @@ public class IoUtil extends NioUtil { } /** - * 文件转为{@link FileInputStream} + * 文件转为{@link InputStream} * * @param file 文件 - * @return {@link FileInputStream} + * @return {@link InputStream} */ - public static FileInputStream toStream(final File file) { + public static InputStream toStream(final File file) { try { - return new FileInputStream(file); - } catch (final FileNotFoundException e) { + return Files.newInputStream(file.toPath()); + } catch (final IOException e) { throw new IORuntimeException(e); } } From cf8c890e8dcad56db67953e5d3c5c09b5647d532 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 21:21:36 +0800 Subject: [PATCH 065/125] del gif --- .../cn/hutool/core/compress/ZipWriter.java | 18 +- .../main/java/cn/hutool/core/io/IoUtil.java | 17 +- hutool-swing/pom.xml | 6 + .../cn/hutool/swing/captcha/GifCaptcha.java | 2 +- .../swing/img/gif/AnimatedGifEncoder.java | 583 ------------- .../cn/hutool/swing/img/gif/GifDecoder.java | 793 ------------------ .../cn/hutool/swing/img/gif/LZWEncoder.java | 306 ------- .../cn/hutool/swing/img/gif/NeuQuant.java | 444 ---------- .../cn/hutool/swing/img/gif/package-info.java | 7 - 9 files changed, 37 insertions(+), 2139 deletions(-) delete mode 100755 hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java delete mode 100755 hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java delete mode 100755 hutool-swing/src/main/java/cn/hutool/swing/img/gif/LZWEncoder.java delete mode 100755 hutool-swing/src/main/java/cn/hutool/swing/img/gif/NeuQuant.java delete mode 100755 hutool-swing/src/main/java/cn/hutool/swing/img/gif/package-info.java diff --git a/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java b/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java index 3bb70e92d..e2d39f817 100755 --- a/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java @@ -100,6 +100,18 @@ public class ZipWriter implements Closeable { return this; } + /** + * 设置压缩方式 + * + * @param method 压缩方式,支持{@link ZipOutputStream#DEFLATED}和{@link ZipOutputStream#STORED} + * @return this + * @since 6.0.0 + */ + public ZipWriter setMethod(final int method) { + this.out.setMethod(method); + return this; + } + /** * 获取原始的{@link ZipOutputStream} * @@ -233,9 +245,10 @@ public class ZipWriter implements Closeable { * @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩),{@code null}表示不过滤 * @throws IORuntimeException IO异常 */ - private ZipWriter _add(final File file, final String srcRootDir, final FileFilter filter) throws IORuntimeException { + @SuppressWarnings("resource") + private void _add(final File file, final String srcRootDir, final FileFilter filter) throws IORuntimeException { if (null == file || (null != filter && false == filter.accept(file))) { - return this; + return; } // 获取文件相对于压缩文件夹根目录的子路径 @@ -256,7 +269,6 @@ public class ZipWriter implements Closeable { // 如果是文件或其它符号,则直接压缩该文件 putEntry(subPath, FileUtil.getInputStream(file)); } - return this; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java index adf81e8c2..a9d1f0dce 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java @@ -38,6 +38,7 @@ import java.io.Writer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.Objects; @@ -527,12 +528,24 @@ public class IoUtil extends NioUtil { /** * 文件转为{@link InputStream} * - * @param file 文件 + * @param file 文件,非空 * @return {@link InputStream} */ public static InputStream toStream(final File file) { + Assert.notNull(file); + return toStream(file.toPath()); + } + + /** + * 文件转为{@link InputStream} + * + * @param path {@link Path},非空 + * @return {@link InputStream} + */ + public static InputStream toStream(final Path path) { + Assert.notNull(path); try { - return Files.newInputStream(file.toPath()); + return Files.newInputStream(path); } catch (final IOException e) { throw new IORuntimeException(e); } diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml index c0c25192f..7764fdc24 100755 --- a/hutool-swing/pom.xml +++ b/hutool-swing/pom.xml @@ -27,6 +27,12 @@ ${project.parent.version}
+ + com.madgag + animated-gif-lib + 1.4 + true + com.drewnoakes metadata-extractor diff --git a/hutool-swing/src/main/java/cn/hutool/swing/captcha/GifCaptcha.java b/hutool-swing/src/main/java/cn/hutool/swing/captcha/GifCaptcha.java index 4781264ad..1a78b45f1 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/captcha/GifCaptcha.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/captcha/GifCaptcha.java @@ -1,9 +1,9 @@ package cn.hutool.swing.captcha; -import cn.hutool.swing.img.gif.AnimatedGifEncoder; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.RandomUtil; +import com.madgag.gif.fmsware.AnimatedGifEncoder; import java.awt.AlphaComposite; import java.awt.Color; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java deleted file mode 100755 index 30f7f3b6b..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/AnimatedGifEncoder.java +++ /dev/null @@ -1,583 +0,0 @@ -package cn.hutool.swing.img.gif; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferByte; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Paths; - -/** - * 动态GIF动画生成器,可生成一个或多个帧的GIF。 - * - *
- * Example:
- *    AnimatedGifEncoder e = new AnimatedGifEncoder();
- *    e.start(outputFileName);
- *    e.setDelay(1000);   // 1 frame per sec
- *    e.addFrame(image1);
- *    e.addFrame(image2);
- *    e.finish();
- * 
- *

- * 来自:https://github.com/rtyley/animated-gif-lib-for-java - * - * @author Kevin Weiner, FM Software - * @version 1.03 November 2003 - * @since 5.3.8 - */ -public class AnimatedGifEncoder { - - protected int width; // image size - protected int height; - protected Color transparent = null; // transparent color if given - protected boolean transparentExactMatch = false; // transparent color will be found by looking for the closest color - // or for the exact color if transparentExactMatch == true - protected Color background = null; // background color if given - protected int transIndex; // transparent index in color table - protected int repeat = -1; // no repeat - protected int delay = 0; // frame delay (hundredths) - protected boolean started = false; // ready to output frames - protected OutputStream out; - protected BufferedImage image; // current frame - protected byte[] pixels; // BGR byte array from frame - protected byte[] indexedPixels; // converted frame indexed to palette - protected int colorDepth; // number of bit planes - protected byte[] colorTab; // RGB palette - protected boolean[] usedEntry = new boolean[256]; // active palette entries - protected int palSize = 7; // color table size (bits-1) - protected int dispose = -1; // disposal code (-1 = use default) - protected boolean closeStream = false; // close stream when finished - protected boolean firstFrame = true; - protected boolean sizeSet = false; // if false, get size from first frame - protected int sample = 10; // default sample interval for quantizer - - /** - * 设置每一帧的间隔时间 - * Sets the delay time between each frame, or changes it - * for subsequent frames (applies to last frame added). - * - * @param ms 间隔时间,单位毫秒 - */ - public void setDelay(final int ms) { - delay = Math.round(ms / 10.0f); - } - - /** - * Sets the GIF frame disposal code for the last added frame - * and any subsequent frames. Default is 0 if no transparent - * color has been set, otherwise 2. - * - * @param code int disposal code. - */ - public void setDispose(final int code) { - if (code >= 0) { - dispose = code; - } - } - - /** - * Sets the number of times the set of GIF frames - * should be played. Default is 1; 0 means play - * indefinitely. Must be invoked before the first - * image is added. - * - * @param iter int number of iterations. - */ - public void setRepeat(final int iter) { - if (iter >= 0) { - repeat = iter; - } - } - - /** - * Sets the transparent color for the last added frame - * and any subsequent frames. - * Since all colors are subject to modification - * in the quantization process, the color in the final - * palette for each frame closest to the given color - * becomes the transparent color for that frame. - * May be set to null to indicate no transparent color. - * - * @param c Color to be treated as transparent on display. - */ - public void setTransparent(final Color c) { - setTransparent(c, false); - } - - /** - * Sets the transparent color for the last added frame - * and any subsequent frames. - * Since all colors are subject to modification - * in the quantization process, the color in the final - * palette for each frame closest to the given color - * becomes the transparent color for that frame. - * If exactMatch is set to true, transparent color index - * is search with exact match, and not looking for the - * closest one. - * May be set to null to indicate no transparent color. - * - * @param c Color to be treated as transparent on display. - * @param exactMatch If exactMatch is set to true, transparent color index is search with exact match - */ - public void setTransparent(final Color c, final boolean exactMatch) { - transparent = c; - transparentExactMatch = exactMatch; - } - - - /** - * Sets the background color for the last added frame - * and any subsequent frames. - * Since all colors are subject to modification - * in the quantization process, the color in the final - * palette for each frame closest to the given color - * becomes the background color for that frame. - * May be set to null to indicate no background color - * which will default to black. - * - * @param c Color to be treated as background on display. - */ - public void setBackground(final Color c) { - background = c; - } - - /** - * Adds next GIF frame. The frame is not written immediately, but is - * actually deferred until the next frame is received so that timing - * data can be inserted. Invoking {@code finish()} flushes all - * frames. If {@code setSize} was not invoked, the size of the - * first image is used for all subsequent frames. - * - * @param im BufferedImage containing frame to write. - * @return true if successful. - */ - public boolean addFrame(final BufferedImage im) { - if ((im == null) || !started) { - return false; - } - boolean ok = true; - try { - if (!sizeSet) { - // use first frame's size - setSize(im.getWidth(), im.getHeight()); - } - image = im; - getImagePixels(); // convert to correct format if necessary - analyzePixels(); // build color table & map pixels - if (firstFrame) { - writeLSD(); // logical screen descriptior - writePalette(); // global color table - if (repeat >= 0) { - // use NS app extension to indicate reps - writeNetscapeExt(); - } - } - writeGraphicCtrlExt(); // write graphic control extension - writeImageDesc(); // image descriptor - if (!firstFrame) { - writePalette(); // local color table - } - writePixels(); // encode and write pixel data - firstFrame = false; - } catch (final IOException e) { - ok = false; - } - - return ok; - } - - /** - * Flushes any pending data and closes output file. - * If writing to an OutputStream, the stream is not - * closed. - * - * @return is ok - */ - public boolean finish() { - if (!started) return false; - boolean ok = true; - started = false; - try { - out.write(0x3b); // gif trailer - out.flush(); - if (closeStream) { - out.close(); - } - } catch (final IOException e) { - ok = false; - } - - // reset for subsequent use - transIndex = 0; - out = null; - image = null; - pixels = null; - indexedPixels = null; - colorTab = null; - closeStream = false; - firstFrame = true; - - return ok; - } - - /** - * Sets frame rate in frames per second. Equivalent to - * {@code setDelay(1000/fps)}. - * - * @param fps float frame rate (frames per second) - */ - public void setFrameRate(final float fps) { - if (fps != 0f) { - delay = Math.round(100f / fps); - } - } - - /** - * Sets quality of color quantization (conversion of images - * to the maximum 256 colors allowed by the GIF specification). - * Lower values (minimum = 1) produce better colors, but slow - * processing significantly. 10 is the default, and produces - * good color mapping at reasonable speeds. Values greater - * than 20 do not yield significant improvements in speed. - * - * @param quality int greater than 0. - */ - public void setQuality(int quality) { - if (quality < 1) quality = 1; - sample = quality; - } - - /** - * Sets the GIF frame size. The default size is the - * size of the first frame added if this method is - * not invoked. - * - * @param w int frame width. - * @param h int frame width. - */ - public void setSize(final int w, final int h) { - if (started && !firstFrame) return; - width = w; - height = h; - if (width < 1) width = 320; - if (height < 1) height = 240; - sizeSet = true; - } - - /** - * Initiates GIF file creation on the given stream. The stream - * is not closed automatically. - * - * @param os OutputStream on which GIF images are written. - * @return false if initial write failed. - */ - public boolean start(final OutputStream os) { - if (os == null) return false; - boolean ok = true; - closeStream = false; - out = os; - try { - writeString("GIF89a"); // header - } catch (final IOException e) { - ok = false; - } - return started = ok; - } - - /** - * Initiates writing of a GIF file with the specified name. - * - * @param file String containing output file name. - * @return false if open or initial write failed. - */ - public boolean start(final String file) { - boolean ok; - try { - out = new BufferedOutputStream(Files.newOutputStream(Paths.get(file))); - ok = start(out); - closeStream = true; - } catch (final IOException e) { - ok = false; - } - return started = ok; - } - - /** - * @return 是否开始 - */ - public boolean isStarted() { - return started; - } - - /** - * Analyzes image colors and creates color map. - */ - protected void analyzePixels() { - final int len = pixels.length; - final int nPix = len / 3; - indexedPixels = new byte[nPix]; - final NeuQuant nq = new NeuQuant(pixels, len, sample); - // initialize quantizer - colorTab = nq.process(); // create reduced palette - // convert map from BGR to RGB - for (int i = 0; i < colorTab.length; i += 3) { - final byte temp = colorTab[i]; - colorTab[i] = colorTab[i + 2]; - colorTab[i + 2] = temp; - usedEntry[i / 3] = false; - } - // map image pixels to new palette - int k = 0; - for (int i = 0; i < nPix; i++) { - final int index = - nq.map(pixels[k++] & 0xff, - pixels[k++] & 0xff, - pixels[k++] & 0xff); - usedEntry[index] = true; - indexedPixels[i] = (byte) index; - } - pixels = null; - colorDepth = 8; - palSize = 7; - // get the closest match to transparent color if specified - if (transparent != null) { - transIndex = transparentExactMatch ? findExact(transparent) : findClosest(transparent); - } - } - - /** - * Returns index of palette color closest to c - * - * @param c Color - * @return index - */ - protected int findClosest(final Color c) { - if (colorTab == null) return -1; - final int r = c.getRed(); - final int g = c.getGreen(); - final int b = c.getBlue(); - int minpos = 0; - int dmin = 256 * 256 * 256; - final int len = colorTab.length; - for (int i = 0; i < len; ) { - final int dr = r - (colorTab[i++] & 0xff); - final int dg = g - (colorTab[i++] & 0xff); - final int db = b - (colorTab[i] & 0xff); - final int d = dr * dr + dg * dg + db * db; - final int index = i / 3; - if (usedEntry[index] && (d < dmin)) { - dmin = d; - minpos = index; - } - i++; - } - return minpos; - } - - /** - * Returns true if the exact matching color is existing, and used in the color palette, otherwise, return false. - * This method has to be called before finishing the image, - * because after finished the palette is destroyed, and it will always return false. - * - * @param c 颜色 - * @return 颜色是否存在 - */ - boolean isColorUsed(final Color c) { - return findExact(c) != -1; - } - - /** - * Returns index of palette exactly matching to color c or -1 if there is no exact matching. - * - * @param c Color - * @return index - */ - protected int findExact(final Color c) { - if (colorTab == null) { - return -1; - } - - final int r = c.getRed(); - final int g = c.getGreen(); - final int b = c.getBlue(); - final int len = colorTab.length / 3; - for (int index = 0; index < len; ++index) { - final int i = index * 3; - // If the entry is used in colorTab, then check if it is the same exact color we're looking for - if (usedEntry[index] && r == (colorTab[i] & 0xff) && g == (colorTab[i + 1] & 0xff) && b == (colorTab[i + 2] & 0xff)) { - return index; - } - } - return -1; - } - - /** - * Extracts image pixels into byte array "pixels" - */ - protected void getImagePixels() { - final int w = image.getWidth(); - final int h = image.getHeight(); - final int type = image.getType(); - if ((w != width) - || (h != height) - || (type != BufferedImage.TYPE_3BYTE_BGR)) { - // create new image with right size/format - final BufferedImage temp = - new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); - final Graphics2D g = temp.createGraphics(); - g.setColor(background); - g.fillRect(0, 0, width, height); - g.drawImage(image, 0, 0, null); - image = temp; - } - pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); - } - - /** - * Writes Graphic Control Extension - * - * @throws IOException IO异常 - */ - protected void writeGraphicCtrlExt() throws IOException { - out.write(0x21); // extension introducer - out.write(0xf9); // GCE label - out.write(4); // data block size - final int transp; - int disp; - if (transparent == null) { - transp = 0; - disp = 0; // dispose = no action - } else { - transp = 1; - disp = 2; // force clear if using transparent color - } - if (dispose >= 0) { - disp = dispose & 7; // user override - } - disp <<= 2; - - // packed fields - //noinspection PointlessBitwiseExpression - out.write(0 | // 1:3 reserved - disp | // 4:6 disposal - 0 | // 7 user input - 0 = none - transp); // 8 transparency flag - - writeShort(delay); // delay x 1/100 sec - out.write(transIndex); // transparent color index - out.write(0); // block terminator - } - - /** - * Writes Image Descriptor - * - * @throws IOException IO异常 - */ - protected void writeImageDesc() throws IOException { - out.write(0x2c); // image separator - writeShort(0); // image position x,y = 0,0 - writeShort(0); - writeShort(width); // image size - writeShort(height); - // packed fields - if (firstFrame) { - // no LCT - GCT is used for first (or only) frame - out.write(0); - } else { - // specify normal LCT - //noinspection PointlessBitwiseExpression - out.write(0x80 | // 1 local color table 1=yes - 0 | // 2 interlace - 0=no - 0 | // 3 sorted - 0=no - 0 | // 4-5 reserved - palSize); // 6-8 size of color table - } - } - - /** - * Writes Logical Screen Descriptor - * - * @throws IOException IO异常 - */ - protected void writeLSD() throws IOException { - // logical screen size - writeShort(width); - writeShort(height); - // packed fields - //noinspection PointlessBitwiseExpression - out.write((0x80 | // 1 : global color table flag = 1 (gct used) - 0x70 | // 2-4 : color resolution = 7 - 0x00 | // 5 : gct sort flag = 0 - palSize)); // 6-8 : gct size - - out.write(0); // background color index - out.write(0); // pixel aspect ratio - assume 1:1 - } - - /** - * Writes Netscape application extension to define - * repeat count. - * - * @throws IOException IO异常 - */ - protected void writeNetscapeExt() throws IOException { - out.write(0x21); // extension introducer - out.write(0xff); // app extension label - out.write(11); // block size - writeString("NETSCAPE" + "2.0"); // app id + auth code - out.write(3); // sub-block size - out.write(1); // loop sub-block id - writeShort(repeat); // loop count (extra iterations, 0=repeat forever) - out.write(0); // block terminator - } - - /** - * Writes color table - * - * @throws IOException IO异常 - */ - protected void writePalette() throws IOException { - out.write(colorTab, 0, colorTab.length); - final int n = (3 * 256) - colorTab.length; - for (int i = 0; i < n; i++) { - out.write(0); - } - } - - /** - * Encodes and writes pixel data - * - * @throws IOException IO异常 - */ - protected void writePixels() throws IOException { - final LZWEncoder encoder = new LZWEncoder(width, height, indexedPixels, colorDepth); - encoder.encode(out); - } - - /** - * Write 16-bit value to output stream, LSB first - * - * @param value 16-bit value - * @throws IOException IO异常 - */ - protected void writeShort(final int value) throws IOException { - out.write(value & 0xff); - out.write((value >> 8) & 0xff); - } - - /** - * Writes string to output stream - * - * @param s String - * @throws IOException IO异常 - */ - protected void writeString(final String s) throws IOException { - for (int i = 0; i < s.length(); i++) { - out.write((byte) s.charAt(i)); - } - } -} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java deleted file mode 100755 index 676008a5a..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/GifDecoder.java +++ /dev/null @@ -1,793 +0,0 @@ -package cn.hutool.swing.img.gif; - -import cn.hutool.core.io.IoUtil; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; - -/** - * GIF文件解析 - * Class GifDecoder - Decodes a GIF file into one or more frames. - *

- * Example: - * - *

- * {@code
- *    GifDecoder d = new GifDecoder();
- *    d.read("sample.gif");
- *    int n = d.getFrameCount();
- *    for (int i = 0; i < n; i++) {
- *       BufferedImage frame = d.getFrame(i);  // frame i
- *       int t = d.getDelay(i);  // display duration of frame in milliseconds
- *       // do something with frame
- *    }
- * }
- * 
- *

- * 来自:https://github.com/rtyley/animated-gif-lib-for-java - * - * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick. - */ -public class GifDecoder { - - /** - * File read status: No errors. - */ - public static final int STATUS_OK = 0; - - /** - * File read status: Error decoding file (may be partially decoded) - */ - public static final int STATUS_FORMAT_ERROR = 1; - - /** - * File read status: Unable to open source. - */ - public static final int STATUS_OPEN_ERROR = 2; - - protected BufferedInputStream in; - protected int status; - - protected int width; // full image width - protected int height; // full image height - protected boolean gctFlag; // global color table used - protected int gctSize; // size of global color table - protected int loopCount = 1; // iterations; 0 = repeat forever - - protected int[] gct; // global color table - protected int[] lct; // local color table - protected int[] act; // active color table - - protected int bgIndex; // background color index - protected int bgColor; // background color - protected int lastBgColor; // previous bg color - protected int pixelAspect; // pixel aspect ratio - - protected boolean lctFlag; // local color table flag - protected boolean interlace; // interlace flag - protected int lctSize; // local color table size - - protected int ix, iy, iw, ih; // current image rectangle - protected Rectangle lastRect; // last image rect - protected BufferedImage image; // current frame - protected BufferedImage lastImage; // previous frame - - protected byte[] block = new byte[256]; // current data block - protected int blockSize = 0; // block size - - // last graphic control extension info - protected int dispose = 0; - // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev - protected int lastDispose = 0; - protected boolean transparency = false; // use transparent color - protected int delay = 0; // delay in milliseconds - protected int transIndex; // transparent color index - - protected static final int MAX_STACK_SIZE = 4096; - // max decoder pixel stack size - - // LZW decoder working arrays - protected short[] prefix; - protected byte[] suffix; - protected byte[] pixelStack; - protected byte[] pixels; - - protected ArrayList frames; // frames read from current file - protected int frameCount; - - static class GifFrame { - public GifFrame(final BufferedImage im, final int del) { - image = im; - delay = del; - } - - public BufferedImage image; - public int delay; - } - - /** - * Gets display duration for specified frame. - * - * @param n int index of frame - * @return delay in milliseconds - */ - public int getDelay(final int n) { - // - delay = -1; - if ((n >= 0) && (n < frameCount)) { - delay = frames.get(n).delay; - } - return delay; - } - - /** - * Gets the number of frames read from file. - * - * @return frame count - */ - public int getFrameCount() { - return frameCount; - } - - /** - * Gets the first (or only) image read. - * - * @return BufferedImage containing first frame, or null if none. - */ - public BufferedImage getImage() { - return getFrame(0); - } - - /** - * Gets the "Netscape" iteration count, if any. - * A count of 0 means repeat indefinitiely. - * - * @return iteration count if one was specified, else 1. - */ - public int getLoopCount() { - return loopCount; - } - - /** - * Creates new frame image from current data (and previous - * frames as specified by their disposition codes). - */ - protected void setPixels() { - // expose destination image's pixels as int array - final int[] dest = - ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); - - // fill in starting image contents based on last image's dispose code - if (lastDispose > 0) { - if (lastDispose == 3) { - // use image before last - final int n = frameCount - 2; - if (n > 0) { - lastImage = getFrame(n - 1); - } else { - lastImage = null; - } - } - - if (lastImage != null) { - final int[] prev = - ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); - System.arraycopy(prev, 0, dest, 0, width * height); - // copy pixels - - if (lastDispose == 2) { - // fill last image rect area with background color - final Graphics2D g = image.createGraphics(); - final Color c; - if (transparency) { - c = new Color(0, 0, 0, 0); // assume background is transparent - } else { - c = new Color(lastBgColor); // use given background color - } - g.setColor(c); - g.setComposite(AlphaComposite.Src); // replace area - g.fill(lastRect); - g.dispose(); - } - } - } - - // copy each source line to the appropriate place in the destination - int pass = 1; - int inc = 8; - int iline = 0; - for (int i = 0; i < ih; i++) { - int line = i; - if (interlace) { - if (iline >= ih) { - pass++; - switch (pass) { - case 2: - iline = 4; - break; - case 3: - iline = 2; - inc = 4; - break; - case 4: - iline = 1; - inc = 2; - } - } - line = iline; - iline += inc; - } - line += iy; - if (line < height) { - final int k = line * width; - int dx = k + ix; // start of line in dest - int dlim = dx + iw; // end of dest line - if ((k + width) < dlim) { - dlim = k + width; // past dest edge - } - int sx = i * iw; // start of line in source - while (dx < dlim) { - // map color and insert in destination - final int index = ((int) pixels[sx++]) & 0xff; - final int c = act[index]; - if (c != 0) { - dest[dx] = c; - } - dx++; - } - } - } - } - - /** - * Gets the image contents of frame n. - * - * @param n frame - * @return BufferedImage - */ - public BufferedImage getFrame(final int n) { - BufferedImage im = null; - if ((n >= 0) && (n < frameCount)) { - im = frames.get(n).image; - } - return im; - } - - /** - * Gets image size. - * - * @return GIF image dimensions - */ - public Dimension getFrameSize() { - return new Dimension(width, height); - } - - /** - * Reads GIF image from stream - * - * @param is BufferedInputStream containing GIF file. - * @return read status code (0 = no errors) - */ - public int read(final BufferedInputStream is) { - init(); - if (is != null) { - in = is; - readHeader(); - if (false == err()) { - readContents(); - if (frameCount < 0) { - status = STATUS_FORMAT_ERROR; - } - } - } else { - status = STATUS_OPEN_ERROR; - } - IoUtil.close(is); - return status; - } - - /** - * Reads GIF image from stream - * - * @param is InputStream containing GIF file. - * @return read status code (0 = no errors) - */ - public int read(InputStream is) { - init(); - if (is != null) { - if (!(is instanceof BufferedInputStream)) - is = new BufferedInputStream(is); - in = (BufferedInputStream) is; - readHeader(); - if (!err()) { - readContents(); - if (frameCount < 0) { - status = STATUS_FORMAT_ERROR; - } - } - } else { - status = STATUS_OPEN_ERROR; - } - IoUtil.close(is); - return status; - } - - /** - * Reads GIF file from specified file/URL source - * (URL assumed if name contains ":/" or "file:") - * - * @param name String containing source - * @return read status code (0 = no errors) - */ - public int read(String name) { - status = STATUS_OK; - try { - name = name.trim().toLowerCase(); - if ((name.contains("file:")) || - (name.indexOf(":/") > 0)) { - final URL url = new URL(name); - in = new BufferedInputStream(url.openStream()); - } else { - in = new BufferedInputStream(Files.newInputStream(Paths.get(name))); - } - status = read(in); - } catch (final IOException e) { - status = STATUS_OPEN_ERROR; - } - - return status; - } - - /** - * Decodes LZW image data into pixel array. - * Adapted from John Cristy's ImageMagick. - */ - protected void decodeImageData() { - final int NullCode = -1; - final int npix = iw * ih; - int available; - final int clear; - int code_mask; - int code_size; - final int end_of_information; - int in_code; - int old_code; - int bits; - int code; - int count; - int i; - int datum; - final int data_size; - int first; - int top; - int bi; - int pi; - - if ((pixels == null) || (pixels.length < npix)) { - pixels = new byte[npix]; // allocate new pixel array - } - if (prefix == null) prefix = new short[MAX_STACK_SIZE]; - if (suffix == null) suffix = new byte[MAX_STACK_SIZE]; - if (pixelStack == null) pixelStack = new byte[MAX_STACK_SIZE + 1]; - - // Initialize GIF data stream decoder. - - data_size = read(); - clear = 1 << data_size; - end_of_information = clear + 1; - available = clear + 2; - old_code = NullCode; - code_size = data_size + 1; - code_mask = (1 << code_size) - 1; - for (code = 0; code < clear; code++) { - prefix[code] = 0; - suffix[code] = (byte) code; - } - - // Decode GIF pixel stream. - - datum = bits = count = first = top = pi = bi = 0; - - for (i = 0; i < npix; ) { - if (top == 0) { - if (bits < code_size) { - // Load bytes until there are enough bits for a code. - if (count == 0) { - // Read a new data block. - count = readBlock(); - if (count <= 0) - break; - bi = 0; - } - datum += (((int) block[bi]) & 0xff) << bits; - bits += 8; - bi++; - count--; - continue; - } - - // Get the next code. - - code = datum & code_mask; - datum >>= code_size; - bits -= code_size; - - // Interpret the code - - if ((code > available) || (code == end_of_information)) - break; - if (code == clear) { - // Reset decoder. - code_size = data_size + 1; - code_mask = (1 << code_size) - 1; - available = clear + 2; - old_code = NullCode; - continue; - } - if (old_code == NullCode) { - pixelStack[top++] = suffix[code]; - old_code = code; - first = code; - continue; - } - in_code = code; - if (code == available) { - pixelStack[top++] = (byte) first; - code = old_code; - } - while (code > clear) { - pixelStack[top++] = suffix[code]; - code = prefix[code]; - } - first = ((int) suffix[code]) & 0xff; - - // Add a new string to the string table, - - if (available >= MAX_STACK_SIZE) { - pixelStack[top++] = (byte) first; - continue; - } - pixelStack[top++] = (byte) first; - prefix[available] = (short) old_code; - suffix[available] = (byte) first; - available++; - if (((available & code_mask) == 0) - && (available < MAX_STACK_SIZE)) { - code_size++; - code_mask += available; - } - old_code = in_code; - } - - // Pop a pixel off the pixel stack. - - top--; - pixels[pi++] = pixelStack[top]; - i++; - } - - for (i = pi; i < npix; i++) { - pixels[i] = 0; // clear missing pixels - } - - } - - /** - * Returns true if an error was encountered during reading/decoding - * - * @return true if an error was encountered during reading/decoding - */ - protected boolean err() { - return status != STATUS_OK; - } - - /** - * Initializes or re-initializes reader - */ - protected void init() { - status = STATUS_OK; - frameCount = 0; - frames = new ArrayList<>(); - gct = null; - lct = null; - } - - /** - * Reads a single byte from the input stream. - * - * @return single byte - */ - protected int read() { - int curByte = 0; - try { - curByte = in.read(); - } catch (final IOException e) { - status = STATUS_FORMAT_ERROR; - } - return curByte; - } - - /** - * Reads next variable length block from input. - * - * @return number of bytes stored in "buffer" - */ - protected int readBlock() { - blockSize = read(); - int n = 0; - if (blockSize > 0) { - try { - int count; - while (n < blockSize) { - count = in.read(block, n, blockSize - n); - if (count == -1) - break; - n += count; - } - } catch (final IOException e) { - //ignore - } - - if (n < blockSize) { - status = STATUS_FORMAT_ERROR; - } - } - return n; - } - - /** - * Reads color table as 256 RGB integer values - * - * @param ncolors int number of colors to read - * @return int array containing 256 colors (packed ARGB with full alpha) - */ - protected int[] readColorTable(final int ncolors) { - final int nbytes = 3 * ncolors; - int[] tab = null; - final byte[] c = new byte[nbytes]; - int n = 0; - try { - n = in.read(c); - } catch (final IOException e) { - //ignore - } - if (n < nbytes) { - status = STATUS_FORMAT_ERROR; - } else { - tab = new int[256]; // max size to avoid bounds checks - int i = 0; - int j = 0; - while (i < ncolors) { - final int r = ((int) c[j++]) & 0xff; - final int g = ((int) c[j++]) & 0xff; - final int b = ((int) c[j++]) & 0xff; - tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; - } - } - return tab; - } - - /** - * Main file parser. Reads GIF content blocks. - */ - protected void readContents() { - // read GIF file content blocks - boolean done = false; - while (!(done || err())) { - int code = read(); - switch (code) { - - case 0x2C: // image separator - readImage(); - break; - - case 0x21: // extension - code = read(); - switch (code) { - case 0xf9: // graphics control extension - readGraphicControlExt(); - break; - - case 0xff: // application extension - readBlock(); - final StringBuilder app = new StringBuilder(); - for (int i = 0; i < 11; i++) { - app.append((char) block[i]); - } - if ("NETSCAPE2.0".equals(app.toString())) { - readNetscapeExt(); - } else { - skip(); // don't care - } - break; - - default: // uninteresting extension - skip(); - } - break; - - case 0x3b: // terminator - done = true; - break; - - case 0x00: // bad byte, but keep going and see what happens - break; - - default: - status = STATUS_FORMAT_ERROR; - } - } - } - - /** - * Reads Graphics Control Extension values - */ - protected void readGraphicControlExt() { - read(); // block size - final int packed = read(); // packed fields - dispose = (packed & 0x1c) >> 2; // disposal method - if (dispose == 0) { - dispose = 1; // elect to keep old image if discretionary - } - transparency = (packed & 1) != 0; - delay = readShort() * 10; // delay in milliseconds - transIndex = read(); // transparent color index - read(); // block terminator - } - - /** - * Reads GIF file header information. - */ - protected void readHeader() { - final StringBuilder id = new StringBuilder(); - for (int i = 0; i < 6; i++) { - id.append((char) read()); - } - if (false == id.toString().startsWith("GIF")) { - status = STATUS_FORMAT_ERROR; - return; - } - - readLSD(); - if (gctFlag && !err()) { - gct = readColorTable(gctSize); - bgColor = gct[bgIndex]; - } - } - - /** - * Reads next frame image - */ - protected void readImage() { - ix = readShort(); // (sub)image position & size - iy = readShort(); - iw = readShort(); - ih = readShort(); - - final int packed = read(); - lctFlag = (packed & 0x80) != 0; // 1 - local color table flag - interlace = (packed & 0x40) != 0; // 2 - interlace flag - // 3 - sort flag - // 4-5 - reserved - lctSize = 2 << (packed & 7); // 6-8 - local color table size - - if (lctFlag) { - lct = readColorTable(lctSize); // read table - act = lct; // make local table active - } else { - act = gct; // make global table active - if (bgIndex == transIndex) - bgColor = 0; - } - int save = 0; - if (transparency) { - save = act[transIndex]; - act[transIndex] = 0; // set transparent color if specified - } - - if (act == null) { - status = STATUS_FORMAT_ERROR; // no color table defined - } - - if (err()) return; - - decodeImageData(); // decode pixel data - skip(); - - if (err()) return; - - frameCount++; - - // create new image to receive frame data - image = - new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); - - setPixels(); // transfer pixel data to image - - frames.add(new GifFrame(image, delay)); // add image to frame list - - if (transparency) { - act[transIndex] = save; - } - resetFrame(); - - } - - /** - * Reads Logical Screen Descriptor - */ - protected void readLSD() { - - // logical screen size - width = readShort(); - height = readShort(); - - // packed fields - final int packed = read(); - gctFlag = (packed & 0x80) != 0; // 1 : global color table flag - // 2-4 : color resolution - // 5 : gct sort flag - gctSize = 2 << (packed & 7); // 6-8 : gct size - - bgIndex = read(); // background color index - pixelAspect = read(); // pixel aspect ratio - } - - /** - * Reads Netscape extenstion to obtain iteration count - */ - protected void readNetscapeExt() { - do { - readBlock(); - if (block[0] == 1) { - // loop count sub-block - final int b1 = ((int) block[1]) & 0xff; - final int b2 = ((int) block[2]) & 0xff; - loopCount = (b2 << 8) | b1; - } - } while ((blockSize > 0) && !err()); - } - - /** - * Reads next 16-bit value, LSB first - * - * @return next 16-bit value - */ - protected int readShort() { - // read 16-bit value, LSB first - return read() | (read() << 8); - } - - /** - * Resets frame state for reading next image. - */ - protected void resetFrame() { - lastDispose = dispose; - lastRect = new Rectangle(ix, iy, iw, ih); - lastImage = image; - lastBgColor = bgColor; - lct = null; - } - - /** - * Skips variable length blocks up to and including - * next zero length block. - */ - protected void skip() { - do { - readBlock(); - } while ((blockSize > 0) && !err()); - } -} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/LZWEncoder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/LZWEncoder.java deleted file mode 100755 index 0dc2e1ed8..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/LZWEncoder.java +++ /dev/null @@ -1,306 +0,0 @@ -package cn.hutool.swing.img.gif; - -import java.io.IOException; -import java.io.OutputStream; - -//============================================================================== -// Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott. -// K Weiner 12/00 - -class LZWEncoder { - - private static final int EOF = -1; - - private final int imgW; - private final int imgH; - private final byte[] pixAry; - private final int initCodeSize; - - private int remaining; - private int curPixel; - - // GIFCOMPR.C - GIF Image compression routines - // - // Lempel-Ziv compression based on 'compress'. GIF modifications by - // David Rowley (mgardi@watdcsu.waterloo.edu) - - // General DEFINEs - - static final int BITS = 12; - - static final int HSIZE = 5003; // 80% occupancy - - // GIF Image compression - modified 'compress' - // - // Based on: compress.c - File compression ala IEEE Computer, June 1984. - // - // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - // Jim McKie (decvax!mcvax!jim) - // Steve Davies (decvax!vax135!petsd!peora!srd) - // Ken Turkowski (decvax!decwrl!turtlevax!ken) - // James A. Woods (decvax!ihnp4!ames!jaw) - // Joe Orost (decvax!vax135!petsd!joe) - - int n_bits; // number of bits/code - int maxbits = BITS; // user settable max # bits/code - int maxcode; // maximum code, given n_bits - int maxmaxcode = 1 << BITS; // should NEVER generate this code - - int[] htab = new int[HSIZE]; - int[] codetab = new int[HSIZE]; - - int hsize = HSIZE; // for dynamic table sizing - - int free_ent = 0; // first unused entry - - // block compression parameters -- after all codes are used up, - // and compression rate changes, start over. - boolean clear_flg = false; - - // Algorithm: use open addressing double hashing (no chaining) on the - // prefix code / next character combination. We do a variant of Knuth's - // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime - // secondary probe. Here, the modular division first probe is gives way - // to a faster exclusive-or manipulation. Also do block compression with - // an adaptive reset, whereby the code table is cleared when the compression - // ratio decreases, but after the table fills. The variable-length output - // codes are re-sized at this point, and a special CLEAR code is generated - // for the decompressor. Late addition: construct the table according to - // file size for noticeable speed improvement on small files. Please direct - // questions about this implementation to ames!jaw. - - int g_init_bits; - - int ClearCode; - int EOFCode; - - // output - // - // Output the given code. - // Inputs: - // code: A n_bits-bit integer. If == -1, then EOF. This assumes - // that n_bits =< wordsize - 1. - // Outputs: - // Outputs code to the file. - // Assumptions: - // Chars are 8 bits long. - // Algorithm: - // Maintain a BITS character long buffer (so that 8 codes will - // fit in it exactly). Use the VAX insv instruction to insert each - // code in turn. When the buffer fills up empty it and start over. - - int cur_accum = 0; - int cur_bits = 0; - - final int[] masks = - { - 0x0000, - 0x0001, - 0x0003, - 0x0007, - 0x000F, - 0x001F, - 0x003F, - 0x007F, - 0x00FF, - 0x01FF, - 0x03FF, - 0x07FF, - 0x0FFF, - 0x1FFF, - 0x3FFF, - 0x7FFF, - 0xFFFF }; - - // Number of characters so far in this 'packet' - int a_count; - - // Define the storage for the packet accumulator - byte[] accum = new byte[256]; - - //---------------------------------------------------------------------------- - LZWEncoder(final int width, final int height, final byte[] pixels, final int color_depth) { - imgW = width; - imgH = height; - pixAry = pixels; - initCodeSize = Math.max(2, color_depth); - } - - // Add a character to the end of the current packet, and if it is 254 - // characters, flush the packet to disk. - void char_out(final byte c, final OutputStream outs) throws IOException { - accum[a_count++] = c; - if (a_count >= 254) - flush_char(outs); - } - - // Clear out the hash table - - // table clear for block compress - void cl_block(final OutputStream outs) throws IOException { - cl_hash(hsize); - free_ent = ClearCode + 2; - clear_flg = true; - - output(ClearCode, outs); - } - - // reset code table - void cl_hash(final int hsize) { - for (int i = 0; i < hsize; ++i) - htab[i] = -1; - } - - void compress(final int init_bits, final OutputStream outs) throws IOException { - int fcode; - int i /* = 0 */; - int c; - int ent; - int disp; - final int hsize_reg; - int hshift; - - // Set up the globals: g_init_bits - initial number of bits - g_init_bits = init_bits; - - // Set up the necessary values - clear_flg = false; - n_bits = g_init_bits; - maxcode = MAXCODE(n_bits); - - ClearCode = 1 << (init_bits - 1); - EOFCode = ClearCode + 1; - free_ent = ClearCode + 2; - - a_count = 0; // clear packet - - ent = nextPixel(); - - hshift = 0; - for (fcode = hsize; fcode < 65536; fcode *= 2) - ++hshift; - hshift = 8 - hshift; // set hash code range bound - - hsize_reg = hsize; - cl_hash(hsize_reg); // clear hash table - - output(ClearCode, outs); - - outer_loop : while ((c = nextPixel()) != EOF) { - fcode = (c << maxbits) + ent; - i = (c << hshift) ^ ent; // xor hashing - - if (htab[i] == fcode) { - ent = codetab[i]; - continue; - } else if (htab[i] >= 0) // non-empty slot - { - disp = hsize_reg - i; // secondary hash (after G. Knott) - if (i == 0) - disp = 1; - do { - if ((i -= disp) < 0) - i += hsize_reg; - - if (htab[i] == fcode) { - ent = codetab[i]; - continue outer_loop; - } - } while (htab[i] >= 0); - } - output(ent, outs); - ent = c; - if (free_ent < maxmaxcode) { - codetab[i] = free_ent++; // code -> hashtable - htab[i] = fcode; - } else { - cl_block(outs); - } - } - // Put out the final code. - output(ent, outs); - output(EOFCode, outs); - } - - //---------------------------------------------------------------------------- - void encode(final OutputStream os) throws IOException { - os.write(initCodeSize); // write "initial code size" byte - - remaining = imgW * imgH; // reset navigation variables - curPixel = 0; - - compress(initCodeSize + 1, os); // compress and write the pixel data - - os.write(0); // write block terminator - } - - // Flush the packet to disk, and reset the accumulator - void flush_char(final OutputStream outs) throws IOException { - if (a_count > 0) { - outs.write(a_count); - outs.write(accum, 0, a_count); - a_count = 0; - } - } - - final int MAXCODE(final int n_bits) { - return (1 << n_bits) - 1; - } - - //---------------------------------------------------------------------------- - // Return the next pixel from the image - //---------------------------------------------------------------------------- - private int nextPixel() { - if (remaining == 0) - return EOF; - - --remaining; - - final byte pix = pixAry[curPixel++]; - - return pix & 0xff; - } - - void output(final int code, final OutputStream outs) throws IOException { - cur_accum &= masks[cur_bits]; - - if (cur_bits > 0) - cur_accum |= (code << cur_bits); - else - cur_accum = code; - - cur_bits += n_bits; - - while (cur_bits >= 8) { - char_out((byte) (cur_accum & 0xff), outs); - cur_accum >>= 8; - cur_bits -= 8; - } - - // If the next entry is going to be too big for the code size, - // then increase it, if possible. - if (free_ent > maxcode || clear_flg) { - if (clear_flg) { - maxcode = MAXCODE(n_bits = g_init_bits); - clear_flg = false; - } else { - ++n_bits; - if (n_bits == maxbits) - maxcode = maxmaxcode; - else - maxcode = MAXCODE(n_bits); - } - } - - if (code == EOFCode) { - // At EOF, write the rest of the buffer. - while (cur_bits > 0) { - char_out((byte) (cur_accum & 0xff), outs); - cur_accum >>= 8; - cur_bits -= 8; - } - - flush_char(outs); - } - } -} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/NeuQuant.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/NeuQuant.java deleted file mode 100755 index ff128f59e..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/NeuQuant.java +++ /dev/null @@ -1,444 +0,0 @@ -package cn.hutool.swing.img.gif; - -/** - * NeuQuant Neural-Net Quantization Algorithm - * - * @author Dekker - */ -public class NeuQuant { - - protected static final int NETSIZE = 256; /* number of colours used */ - - /* four primes near 500 - assume no image has a length so large */ - /* that it is divisible by all four primes */ - protected static final int PRIME1 = 499; - protected static final int PRIME2 = 491; - protected static final int PRIME3 = 487; - protected static final int PRIME4 = 503; - - protected static final int MINPICTUREBYTES = (3 * PRIME4); - /* minimum size for input image */ - - /* Program Skeleton - ---------------- - [select samplefac in range 1..30] - [read image from input file] - pic = (unsigned char*) malloc(3*width*height); - initnet(pic,3*width*height,samplefac); - learn(); - unbiasnet(); - [write output image header, using writecolourmap(f)] - inxbuild(); - write output image using inxsearch(b,g,r) */ - - /* Network Definitions - ------------------- */ - - protected static final int MAXNETPOS = (NETSIZE - 1); - protected static final int NETBIASSHIFT = 4; /* bias for colour values */ - protected static final int NCYCLES = 100; /* no. of learning cycles */ - - /* defs for freq and bias */ - protected static final int INTBIASSHIFT = 16; /* bias for fractions */ - protected static final int INTBIAS = (1 << INTBIASSHIFT); - protected static final int GAMMASHIFT = 10; /* gamma = 1024 */ - protected static final int GAMMA = (1 << GAMMASHIFT); - protected static final int BETASHIFT = 10; - protected static final int BETA = (INTBIAS >> BETASHIFT); /* beta = 1/1024 */ - protected static final int BETAGAMMA = - (INTBIAS << (GAMMASHIFT - BETASHIFT)); - - /* defs for decreasing radius factor */ - protected static final int INITRAD = (NETSIZE >> 3); /* for 256 cols, radius starts */ - protected static final int RADIUSBIASSHIFT = 6; /* at 32.0 biased by 6 bits */ - protected static final int RADIUSBIAS = (1 << RADIUSBIASSHIFT); - protected static final int INITRADIUS = (INITRAD * RADIUSBIAS); /* and decreases by a */ - protected static final int RADIUSDEC = 30; /* factor of 1/30 each cycle */ - - /* defs for decreasing alpha factor */ - protected static final int ALPHABIASSHIFT = 10; /* alpha starts at 1.0 */ - protected static final int INITALPHA = (1 << ALPHABIASSHIFT); - - protected int alphadec; /* biased by 10 bits */ - - /* radbias and alpharadbias used for radpower calculation */ - protected static final int RADBIASSHIFT = 8; - protected static final int RADBIAS = (1 << RADBIASSHIFT); - protected static final int ALPHARADBSHIFT = (ALPHABIASSHIFT + RADBIASSHIFT); - protected static final int ALPHARADBIAS = (1 << ALPHARADBSHIFT); - - /* Types and Global Variables - -------------------------- */ - - protected byte[] thepicture; /* the input image itself */ - protected int lengthcount; /* lengthcount = H*W*3 */ - - protected int samplefac; /* sampling factor 1..30 */ - - // typedef int pixel[4]; /* BGRc */ - protected int[][] network; /* the network itself - [netsize][4] */ - - protected int[] netindex = new int[256]; - /* for network lookup - really 256 */ - - protected int[] bias = new int[NETSIZE]; - /* bias and freq arrays for learning */ - protected int[] freq = new int[NETSIZE]; - protected int[] radpower = new int[INITRAD]; - /* radpower for precomputation */ - - /* Initialise network in range (0,0,0) to (255,255,255) and set parameters - ----------------------------------------------------------------------- */ - public NeuQuant(final byte[] thepic, final int len, final int sample) { - - int i; - int[] p; - - thepicture = thepic; - lengthcount = len; - samplefac = sample; - - network = new int[NETSIZE][]; - for (i = 0; i < NETSIZE; i++) { - network[i] = new int[4]; - p = network[i]; - p[0] = p[1] = p[2] = (i << (NETBIASSHIFT + 8)) / NETSIZE; - freq[i] = INTBIAS / NETSIZE; /* 1/netsize */ - bias[i] = 0; - } - } - - public byte[] colorMap() { - final byte[] map = new byte[3 * NETSIZE]; - final int[] index = new int[NETSIZE]; - for (int i = 0; i < NETSIZE; i++) - index[network[i][3]] = i; - int k = 0; - for (int i = 0; i < NETSIZE; i++) { - final int j = index[i]; - map[k++] = (byte) (network[j][0]); - map[k++] = (byte) (network[j][1]); - map[k++] = (byte) (network[j][2]); - } - return map; - } - - /* Insertion sort of network and building of netindex[0..255] (to do after unbias) - ------------------------------------------------------------------------------- */ - public void inxbuild() { - - int i, j, smallpos, smallval; - int[] p; - int[] q; - int previouscol, startpos; - - previouscol = 0; - startpos = 0; - for (i = 0; i < NETSIZE; i++) { - p = network[i]; - smallpos = i; - smallval = p[1]; /* index on g */ - /* find smallest in i..netsize-1 */ - for (j = i + 1; j < NETSIZE; j++) { - q = network[j]; - if (q[1] < smallval) { /* index on g */ - smallpos = j; - smallval = q[1]; /* index on g */ - } - } - q = network[smallpos]; - /* swap p (i) and q (smallpos) entries */ - if (i != smallpos) { - j = q[0]; - q[0] = p[0]; - p[0] = j; - j = q[1]; - q[1] = p[1]; - p[1] = j; - j = q[2]; - q[2] = p[2]; - p[2] = j; - j = q[3]; - q[3] = p[3]; - p[3] = j; - } - /* smallval entry is now in position i */ - if (smallval != previouscol) { - netindex[previouscol] = (startpos + i) >> 1; - for (j = previouscol + 1; j < smallval; j++) - netindex[j] = i; - previouscol = smallval; - startpos = i; - } - } - netindex[previouscol] = (startpos + MAXNETPOS) >> 1; - for (j = previouscol + 1; j < 256; j++) - netindex[j] = MAXNETPOS; /* really 256 */ - } - - /* Main Learning Loop - ------------------ */ - public void learn() { - - int i, j, b, g, r; - int radius; - int rad; - int alpha; - final int step; - int delta; - final int samplepixels; - final byte[] p; - int pix; - final int lim; - - if (lengthcount < MINPICTUREBYTES) - samplefac = 1; - alphadec = 30 + ((samplefac - 1) / 3); - p = thepicture; - pix = 0; - lim = lengthcount; - samplepixels = lengthcount / (3 * samplefac); - delta = samplepixels / NCYCLES; - alpha = INITALPHA; - radius = INITRADIUS; - - rad = radius >> RADIUSBIASSHIFT; - for (i = 0; i < rad; i++) - radpower[i] = - alpha * (((rad * rad - i * i) * RADBIAS) / (rad * rad)); - - //fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad); - - if (lengthcount < MINPICTUREBYTES) - step = 3; - else if ((lengthcount % PRIME1) != 0) - step = 3 * PRIME1; - else { - if ((lengthcount % PRIME2) != 0) - step = 3 * PRIME2; - else { - if ((lengthcount % PRIME3) != 0) - step = 3 * PRIME3; - else - step = 3 * PRIME4; - } - } - - i = 0; - while (i < samplepixels) { - b = (p[pix] & 0xff) << NETBIASSHIFT; - g = (p[pix + 1] & 0xff) << NETBIASSHIFT; - r = (p[pix + 2] & 0xff) << NETBIASSHIFT; - j = contest(b, g, r); - - altersingle(alpha, j, b, g, r); - if (rad != 0) - alterneigh(rad, j, b, g, r); /* alter neighbours */ - - pix += step; - if (pix >= lim) - pix -= lengthcount; - - i++; - if (delta == 0) - delta = 1; - if (i % delta == 0) { - alpha -= alpha / alphadec; - radius -= radius / RADIUSDEC; - rad = radius >> RADIUSBIASSHIFT; - if (rad <= 1) - rad = 0; - for (j = 0; j < rad; j++) - radpower[j] = - alpha * (((rad * rad - j * j) * RADBIAS) / (rad * rad)); - } - } - //fprintf(stderr,"finished 1D learning: final alpha=%f !\n",((float)alpha)/initalpha); - } - - /* Search for BGR values 0..255 (after net is unbiased) and return colour index - ---------------------------------------------------------------------------- */ - public int map(final int b, final int g, final int r) { - - int i, j, dist, a, bestd; - int[] p; - int best; - - bestd = 1000; /* biggest possible dist is 256*3 */ - best = -1; - i = netindex[g]; /* index on g */ - j = i - 1; /* start at netindex[g] and work outwards */ - - while ((i < NETSIZE) || (j >= 0)) { - if (i < NETSIZE) { - p = network[i]; - dist = p[1] - g; /* inx key */ - if (dist >= bestd) - i = NETSIZE; /* stop iter */ - else { - i++; - if (dist < 0) - dist = -dist; - a = p[0] - b; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - a = p[2] - r; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - if (j >= 0) { - p = network[j]; - dist = g - p[1]; /* inx key - reverse dif */ - if (dist >= bestd) - j = -1; /* stop iter */ - else { - j--; - if (dist < 0) - dist = -dist; - a = p[0] - b; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - a = p[2] - r; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - } - return (best); - } - - public byte[] process() { - learn(); - unbiasnet(); - inxbuild(); - return colorMap(); - } - - /* Unbias network to give byte values 0..255 and record position i to prepare for sort - ----------------------------------------------------------------------------------- */ - public void unbiasnet() { - for (int i = 0; i < NETSIZE; i++) { - network[i][0] >>= NETBIASSHIFT; - network[i][1] >>= NETBIASSHIFT; - network[i][2] >>= NETBIASSHIFT; - network[i][3] = i; /* record colour no */ - } - } - - /* Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|] - --------------------------------------------------------------------------------- */ - protected void alterneigh(final int rad, final int i, final int b, final int g, final int r) { - - int j, k, lo, hi, a, m; - int[] p; - - lo = i - rad; - if (lo < -1) - lo = -1; - hi = i + rad; - if (hi > NETSIZE) - hi = NETSIZE; - - j = i + 1; - k = i - 1; - m = 1; - while ((j < hi) || (k > lo)) { - a = radpower[m++]; - if (j < hi) { - p = network[j++]; - try { - p[0] -= (a * (p[0] - b)) / ALPHARADBIAS; - p[1] -= (a * (p[1] - g)) / ALPHARADBIAS; - p[2] -= (a * (p[2] - r)) / ALPHARADBIAS; - } catch (final Exception ignored) { - } // prevents 1.3 miscompilation - } - if (k > lo) { - p = network[k--]; - try { - p[0] -= (a * (p[0] - b)) / ALPHARADBIAS; - p[1] -= (a * (p[1] - g)) / ALPHARADBIAS; - p[2] -= (a * (p[2] - r)) / ALPHARADBIAS; - } catch (final Exception ignored) { - } - } - } - } - - /* Move neuron i towards biased (b,g,r) by factor alpha - ---------------------------------------------------- */ - protected void altersingle(final int alpha, final int i, final int b, final int g, final int r) { - - /* alter hit neuron */ - final int[] n = network[i]; - n[0] -= (alpha * (n[0] - b)) / INITALPHA; - n[1] -= (alpha * (n[1] - g)) / INITALPHA; - n[2] -= (alpha * (n[2] - r)) / INITALPHA; - } - - /* Search for biased BGR values - ---------------------------- */ - protected int contest(final int b, final int g, final int r) { - - /* finds closest neuron (min dist) and updates freq */ - /* finds best neuron (min dist-bias) and returns position */ - /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */ - /* bias[i] = gamma*((1/netsize)-freq[i]) */ - - int i, dist, a, biasdist, betafreq; - int bestpos, bestbiaspos, bestd, bestbiasd; - int[] n; - - bestd = ~(1 << 31); - bestbiasd = bestd; - bestpos = -1; - bestbiaspos = bestpos; - - for (i = 0; i < NETSIZE; i++) { - n = network[i]; - dist = n[0] - b; - if (dist < 0) - dist = -dist; - a = n[1] - g; - if (a < 0) - a = -a; - dist += a; - a = n[2] - r; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - bestpos = i; - } - biasdist = dist - ((bias[i]) >> (INTBIASSHIFT - NETBIASSHIFT)); - if (biasdist < bestbiasd) { - bestbiasd = biasdist; - bestbiaspos = i; - } - betafreq = (freq[i] >> BETASHIFT); - freq[i] -= betafreq; - bias[i] += (betafreq << GAMMASHIFT); - } - freq[bestpos] += BETA; - bias[bestpos] -= BETAGAMMA; - return (bestbiaspos); - } -} diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/package-info.java b/hutool-swing/src/main/java/cn/hutool/swing/img/gif/package-info.java deleted file mode 100755 index e0280645d..000000000 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/gif/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * GIF处理,来自:https://github.com/rtyley/animated-gif-lib-for-java - * - * @author looly - * - */ -package cn.hutool.swing.img.gif; From 09c3dd956544ce2157091483f34aed445283b07b Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 3 Mar 2023 21:58:42 +0800 Subject: [PATCH 066/125] fix bug --- .../impl/TemporalAccessorConverter.java | 11 +++- .../core/date/format/GlobalCustomFormat.java | 6 ++ .../cn/hutool/json/convert/JSONConverter.java | 14 ++++- .../main/java/cn/hutool/json/jwt/Claims.java | 3 +- .../cn/hutool/json/jwt/IssueI6IS5BTest.java | 55 +++++++++++++++++++ 5 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 hutool-json/src/test/java/cn/hutool/json/jwt/IssueI6IS5BTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java index af481448c..fbbb2f926 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java @@ -3,6 +3,7 @@ package cn.hutool.core.convert.impl; import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; @@ -156,7 +157,15 @@ public class TemporalAccessorConverter extends AbstractConverter { return IsoEra.of(Math.toIntExact(time)); } - return parseFromInstant(targetClass, Instant.ofEpochMilli(time), null); + final Instant instant; + if(GlobalCustomFormat.FORMAT_SECONDS.equals(this.format)){ + // https://gitee.com/dromara/hutool/issues/I6IS5B + // Unix时间戳 + instant = Instant.ofEpochSecond(time); + }else{ + instant = Instant.ofEpochMilli(time); + } + return parseFromInstant(targetClass, instant, null); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/GlobalCustomFormat.java b/hutool-core/src/main/java/cn/hutool/core/date/format/GlobalCustomFormat.java index 8fdc29d93..b80b6adb5 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/GlobalCustomFormat.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/GlobalCustomFormat.java @@ -18,7 +18,13 @@ import java.util.function.Function; */ public class GlobalCustomFormat { + /** + * 格式:秒时间戳(Unix时间戳) + */ public static final String FORMAT_SECONDS = "#sss"; + /** + * 格式:毫秒时间戳 + */ public static final String FORMAT_MILLISECONDS = "#SSS"; private static final Map> formatterMap; diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java index 253258b0a..5e82f329a 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java @@ -6,14 +6,24 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConvertException; import cn.hutool.core.convert.Converter; import cn.hutool.core.convert.RegisterConverter; -import cn.hutool.core.convert.impl.*; +import cn.hutool.core.convert.impl.ArrayConverter; +import cn.hutool.core.convert.impl.CollectionConverter; +import cn.hutool.core.convert.impl.DateConverter; +import cn.hutool.core.convert.impl.MapConverter; +import cn.hutool.core.convert.impl.TemporalAccessorConverter; import cn.hutool.core.map.MapWrapper; import cn.hutool.core.reflect.ConstructorUtil; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.reflect.TypeUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; -import cn.hutool.json.*; +import cn.hutool.json.InternalJSONUtil; +import cn.hutool.json.JSON; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONConfig; +import cn.hutool.json.JSONException; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import cn.hutool.json.serialize.JSONDeserializer; import cn.hutool.json.serialize.JSONString; diff --git a/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java b/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java index 8ff46020e..af10857ce 100755 --- a/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java +++ b/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java @@ -1,6 +1,7 @@ package cn.hutool.json.jwt; import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.json.JSONConfig; @@ -21,7 +22,7 @@ public class Claims implements Serializable { private static final long serialVersionUID = 1L; // 时间使用秒级时间戳表示 - private final JSONConfig CONFIG = JSONConfig.of().setDateFormat("#sss"); + private final JSONConfig CONFIG = JSONConfig.of().setDateFormat(GlobalCustomFormat.FORMAT_SECONDS); private JSONObject claimJSON; diff --git a/hutool-json/src/test/java/cn/hutool/json/jwt/IssueI6IS5BTest.java b/hutool-json/src/test/java/cn/hutool/json/jwt/IssueI6IS5BTest.java new file mode 100644 index 000000000..e2de93d70 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/jwt/IssueI6IS5BTest.java @@ -0,0 +1,55 @@ +package cn.hutool.json.jwt; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.TimeUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.Date; + +/** + * https://gitee.com/dromara/hutool/issues/I6IS5B + */ +public class IssueI6IS5BTest { + + @Test + public void payloadToBeanTest() { + final LocalDateTime iat = TimeUtil.of(DateUtil.parse("2023-03-03")); + final JwtToken jwtToken = new JwtToken(); + jwtToken.setIat(iat); + final String token = JWTUtil.createToken(JSONUtil.parseObj(jwtToken), "123".getBytes(StandardCharsets.UTF_8)); + Assert.assertEquals("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2Nzc3NzI4MDB9.SXU_mm1wT5lNoK-Dq5Y8f3BItv_44zuAlyeWLqajpXg", token); + final JSONObject payloads = JWTUtil.parseToken(token).getPayloads(); + Assert.assertEquals("{\"iat\":1677772800}", payloads.toString()); + final JwtToken o = payloads.toBean(JwtToken.class); + Assert.assertEquals(iat, o.getIat()); + } + + @Data + static class JwtToken { + private LocalDateTime iat; + } + + @Test + public void payloadToBeanTest2() { + final Date iat = DateUtil.parse("2023-03-03"); + final JwtToken2 jwtToken = new JwtToken2(); + jwtToken.setIat(iat); + final String token = JWTUtil.createToken(JSONUtil.parseObj(jwtToken), "123".getBytes(StandardCharsets.UTF_8)); + Assert.assertEquals("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2Nzc3NzI4MDB9.SXU_mm1wT5lNoK-Dq5Y8f3BItv_44zuAlyeWLqajpXg", token); + final JSONObject payloads = JWTUtil.parseToken(token).getPayloads(); + Assert.assertEquals("{\"iat\":1677772800}", payloads.toString()); + final JwtToken2 o = payloads.toBean(JwtToken2.class); + Assert.assertEquals(iat, o.getIat()); + } + + @Data + static class JwtToken2 { + private Date iat; + } +} From f79c67044647169aa3c8bce0b6e0d3d17e9913cf Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 5 Mar 2023 13:38:35 +0800 Subject: [PATCH 067/125] 1.update code; 2.fix doc; 3.add test method; --- .../java/cn/hutool/core/net/Ipv4Util.java | 146 +++++++----------- .../main/java/cn/hutool/core/net/MaskBit.java | 5 +- .../java/cn/hutool/core/net/Ipv4UtilTest.java | 27 +++- .../src/main/java/cn/hutool/db/Entity.java | 5 +- 4 files changed, 85 insertions(+), 98 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java index ac992a443..b600a24ec 100755 --- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java @@ -8,13 +8,12 @@ import cn.hutool.core.util.CharUtil; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.regex.Matcher; /** * IPV4地址工具类 * - *

pr自:https://gitee.com/loolly/hutool/pulls/161

+ *

工具类来源pr

* *

名词解释: *

    @@ -22,7 +21,7 @@ import java.util.regex.Matcher; *
  • ip的Long类型:有效位32位,每8位可以转为一个十进制数,例如:0xC0A802FA, 转为点分十进制是:192.168.2.250
  • *
  • 掩码地址:点分十进制,例如:255.255.255.0
  • *
  • 掩码位:int类型,例如 24, 它代表的掩码地址为:255.255.255.0;掩码位和掩码地址的相互转换,请使用 {@link MaskBit}
  • - *
  • CIDR:无类域间路由,形如:xxx.xxx.xxx.xxx/掩码位
  • + *
  • CIDR:无类域间路由,形如:xxx.xxx.xxx.xxx/掩码位,192.168.1.101/24
  • *
  • 全量地址:区间内所有ip地址,包含区间两端
  • *
  • 可用地址:区间内所有ip地址,但是不包含区间两端
  • *
@@ -39,7 +38,7 @@ public class Ipv4Util implements Ipv4Pool { * * @param ip IP地址,点分十进制,如:xxx.xxx.xxx.xxx * @param mask 掩码地址,点分十进制,如:255.255.255.0 - * @return 返回 {@literal xxx.xxx.xxx.xxx/掩码位} 的格式 + * @return 返回 {@literal xxx.xxx.xxx.xxx/掩码位} 的格式,例如:192.168.1.101/24 */ public static String formatIpBlock(final String ip, final String mask) { return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask); @@ -78,35 +77,24 @@ public class Ipv4Util implements Ipv4Pool { assertMaskBitValid(maskBit); // 避免后续的计算异常 if (countByMaskBit(maskBit, isAll) == 0) { - return new ArrayList<>(0); + return ListUtil.zero(); } - if (maskBit == IPV4_MASK_BIT_MAX) { - final List list = new ArrayList<>(isAll ? 1 : 0); - if (isAll) { - list.add(ip); - } - return list; - } - - String startIp = getBeginIpStr(ip, maskBit); - String endIp = getEndIpStr(ip, maskBit); + final long startIp = getBeginIpLong(ip, maskBit); + final long endIp = getEndIpLong(ip, maskBit); if (isAll) { return list(startIp, endIp); } - // 可用地址,排除开始和结束的地址 - int lastDotIndex = startIp.lastIndexOf(CharUtil.DOT) + 1; - startIp = StrUtil.subPre(startIp, lastDotIndex) + - (Integer.parseInt(Objects.requireNonNull(StrUtil.subSuf(startIp, lastDotIndex))) + 1); - lastDotIndex = endIp.lastIndexOf(CharUtil.DOT) + 1; - endIp = StrUtil.subPre(endIp, lastDotIndex) + - (Integer.parseInt(Objects.requireNonNull(StrUtil.subSuf(endIp, lastDotIndex))) - 1); - return list(startIp, endIp); + // 可用地址: 排除开始和结束的地址 + if (startIp + 1 > endIp - 1) { + return ListUtil.zero(); + } + return list(startIp + 1, endIp - 1); } /** - * 获得 指定区间内 所有ip地址 + * 获得 指定区间内 所有ip地址 * * @param ipFrom 开始IP,包含,点分十进制 * @param ipTo 结束IP,包含,点分十进制 @@ -128,41 +116,14 @@ public class Ipv4Util implements Ipv4Pool { final int count = countByIpRange(ipFrom, ipTo); final List ips = new ArrayList<>(count); - // 是否是循环的第一个值 - boolean aIsStart = true, bIsStart = true, cIsStart = true; - // 是否是循环的最后一个值 - boolean aIsEnd, bIsEnd, cIsEnd; - // 循环的结束值 - final int aEnd = getPartOfIpLong(ipTo, 1); - int bEnd; - int cEnd; - int dEnd; final StringBuilder sb = StrUtil.builder(15); - for (int a = getPartOfIpLong(ipFrom, 1); a <= aEnd; a++) { - aIsEnd = (a == aEnd); - // 本次循环的结束结束值 - bEnd = aIsEnd ? getPartOfIpLong(ipTo, 2) : 255; - for (int b = (aIsStart ? getPartOfIpLong(ipFrom, 2) : 0); b <= bEnd; b++) { - // 在上一个循环是最后值的基础上进行判断 - bIsEnd = aIsEnd && (b == bEnd); - cEnd = bIsEnd ? getPartOfIpLong(ipTo, 3) : 255; - for (int c = (bIsStart ? getPartOfIpLong(ipFrom, 3) : 0); c <= cEnd; c++) { - // 在之前循环是最后值的基础上进行判断 - cIsEnd = bIsEnd && (c == cEnd); - dEnd = cIsEnd ? getPartOfIpLong(ipTo, 4) : 255; - for (int d = (cIsStart ? getPartOfIpLong(ipFrom, 4) : 0); d <= dEnd; d++) { - sb.setLength(0); - ips.add(sb.append(a).append(CharUtil.DOT) - .append(b).append(CharUtil.DOT) - .append(c).append(CharUtil.DOT) - .append(d) - .toString()); - } - cIsStart = false; - } - bIsStart = false; - } - aIsStart = false; + for (long ip = ipFrom, end = ipTo + 1; ip < end; ip++) { + sb.setLength(0); + ips.add(sb.append((int) (ip >> 24) & 0xFF).append(CharUtil.DOT) + .append((int) (ip >> 16) & 0xFF).append(CharUtil.DOT) + .append((int) (ip >> 8) & 0xFF).append(CharUtil.DOT) + .append((int) ip & 0xFF) + .toString()); } return ips; } @@ -170,15 +131,15 @@ public class Ipv4Util implements Ipv4Pool { /** * 根据 ip的long值 获取 ip字符串,即:xxx.xxx.xxx.xxx * - * @param longIp IP的long表示形式 + * @param ip IP的long表示形式 * @return 点分十进制ip地址 */ - public static String longToIpv4(final long longIp) { + public static String longToIpv4(final long ip) { return StrUtil.builder(15) - .append(getPartOfIpLong(longIp, 1)).append(CharUtil.DOT) - .append(getPartOfIpLong(longIp, 2)).append(CharUtil.DOT) - .append(getPartOfIpLong(longIp, 3)).append(CharUtil.DOT) - .append(getPartOfIpLong(longIp, 4)) + .append((int) (ip >> 24) & 0xFF).append(CharUtil.DOT) + .append((int) (ip >> 16) & 0xFF).append(CharUtil.DOT) + .append((int) (ip >> 8) & 0xFF).append(CharUtil.DOT) + .append((int) ip & 0xFF) .toString(); } @@ -214,7 +175,7 @@ public class Ipv4Util implements Ipv4Pool { * @param maskBit 给定的掩码位,如:30 * @return 起始IP的长整型表示 */ - public static Long getBeginIpLong(final String ip, final int maskBit) { + public static long getBeginIpLong(final String ip, final int maskBit) { assertMaskBitValid(maskBit); return ipv4ToLong(ip) & MaskBit.getMaskIpLong(maskBit); } @@ -237,8 +198,8 @@ public class Ipv4Util implements Ipv4Pool { * @param maskBit 给定的掩码位,如:30 * @return 终止IP的长整型表示 */ - public static Long getEndIpLong(final String ip, final int maskBit) { - return getBeginIpLong(ip, maskBit) + ~MaskBit.getMaskIpLong(maskBit); + public static long getEndIpLong(final String ip, final int maskBit) { + return getBeginIpLong(ip, maskBit) + (IPV4_NUM_MAX & ~MaskBit.getMaskIpLong(maskBit)); } /** @@ -257,7 +218,7 @@ public class Ipv4Util implements Ipv4Pool { /** * 获取 子网内的 地址总数 * - * @param maskBit 掩码位,取值范围:({@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] + * @param maskBit 掩码位,取值范围:({@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}] * @param isAll true:全量地址,false:可用地址 * @return 子网内地址总数 */ @@ -276,10 +237,11 @@ public class Ipv4Util implements Ipv4Pool { /** * 根据 掩码位 获取 掩码地址 * - * @param maskBit 掩码位,如:24,取值范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] + * @param maskBit 掩码位,如:24,取值范围:[{@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}] * @return 掩码地址,点分十进制,如:255.255.255.0 */ public static String getMaskByMaskBit(final int maskBit) { + assertMaskBitValid(maskBit); return MaskBit.get(maskBit); } @@ -296,10 +258,10 @@ public class Ipv4Util implements Ipv4Pool { Assert.isTrue(fromIpLong <= toIpLong, "Start IP must be less than or equal to end IP!"); return StrUtil.builder(15) - .append(255 - getPartOfIpLong(toIpLong, 1) + getPartOfIpLong(fromIpLong, 1)).append(CharUtil.DOT) - .append(255 - getPartOfIpLong(toIpLong, 2) + getPartOfIpLong(fromIpLong, 2)).append(CharUtil.DOT) - .append(255 - getPartOfIpLong(toIpLong, 3) + getPartOfIpLong(fromIpLong, 3)).append(CharUtil.DOT) - .append(255 - getPartOfIpLong(toIpLong, 4) + getPartOfIpLong(fromIpLong, 4)) + .append(255 - getPartOfIp(toIpLong, 1) + getPartOfIp(fromIpLong, 1)).append(CharUtil.DOT) + .append(255 - getPartOfIp(toIpLong, 2) + getPartOfIp(fromIpLong, 2)).append(CharUtil.DOT) + .append(255 - getPartOfIp(toIpLong, 3) + getPartOfIp(fromIpLong, 3)).append(CharUtil.DOT) + .append(255 - getPartOfIp(toIpLong, 4) + getPartOfIp(fromIpLong, 4)) .toString(); } @@ -311,9 +273,7 @@ public class Ipv4Util implements Ipv4Pool { * @return IP数量 */ public static int countByIpRange(final String fromIp, final String toIp) { - final long toIpLong = ipv4ToLong(toIp); - final long fromIpLong = ipv4ToLong(fromIp); - return countByIpRange(fromIpLong, toIpLong); + return countByIpRange(ipv4ToLong(fromIp), ipv4ToLong(toIp)); } /** @@ -327,10 +287,10 @@ public class Ipv4Util implements Ipv4Pool { Assert.isTrue(fromIp <= toIp, "Start IP must be less than or equal to end IP!"); int count = 1; - count += (getPartOfIpLong(toIp, 4) - getPartOfIpLong(fromIp, 4)); - count += (getPartOfIpLong(toIp, 3) - getPartOfIpLong(fromIp, 3)) << 8; - count += (getPartOfIpLong(toIp, 2) - getPartOfIpLong(fromIp, 2)) << 16; - count += (getPartOfIpLong(toIp, 1) - getPartOfIpLong(fromIp, 1)) << 24; + count += (getPartOfIp(toIp, 4) - getPartOfIp(fromIp, 4)) + + ((getPartOfIp(toIp, 3) - getPartOfIp(fromIp, 3)) << 8) + + ((getPartOfIp(toIp, 2) - getPartOfIp(fromIp, 2)) << 16) + + ((getPartOfIp(toIp, 1) - getPartOfIp(fromIp, 1)) << 24); return count; } @@ -347,7 +307,7 @@ public class Ipv4Util implements Ipv4Pool { /** * 判断掩码位是否合法 * - * @param maskBit 掩码位,有效范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}] + * @param maskBit 掩码位,有效范围:[{@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}] * @return true:掩码位合法;false:掩码位不合法 */ public static boolean isMaskBitValid(final int maskBit) { @@ -424,7 +384,7 @@ public class Ipv4Util implements Ipv4Pool { /** * 获取ip(Long类型)指定部分的十进制值,即,{@literal X.X.X.X }形式中每个部分的值 - *

例如,ip为{@literal 0xC0A802FA},第1部分的值为: + *

例如,ip为{@literal 0xC0A802FA}: *

    *
  • 第1部分的值为:{@literal 0xC0},十进制值为:192
  • *
  • 第2部分的值为:{@literal 0xA8},十进制值为:168
  • @@ -437,16 +397,16 @@ public class Ipv4Util implements Ipv4Pool { * @return ip地址指定部分的十进制值 * @since 6.0.0 */ - public static int getPartOfIpLong(final long ip, final int position) { + public static int getPartOfIp(final long ip, final int position) { switch (position) { case 1: - return ((int) ip >> 24) & 0xFF; + return (int) (ip >> 24) & 0xFF; case 2: - return ((int) ip >> 16) & 0xFF; + return (int) (ip >> 16) & 0xFF; case 3: - return ((int) ip >> 8) & 0xFF; + return (int) (ip >> 8) & 0xFF; case 4: - return ((int) ip) & 0xFF; + return (int)ip & 0xFF; default: throw new IllegalArgumentException("Illegal position of ip Long: " + position); } @@ -462,10 +422,14 @@ public class Ipv4Util implements Ipv4Pool { private static long matchAddress(final Matcher matcher) { int addr = 0; // 每个点分十进制数字 转为 8位二进制 - for (int i = 1; i <= 4; ++i) { - addr <<= 8; - addr |= Integer.parseInt(matcher.group(i)); - } + addr |= Integer.parseInt(matcher.group(1)); + addr <<= 8; + addr |= Integer.parseInt(matcher.group(2)); + addr <<= 8; + addr |= Integer.parseInt(matcher.group(3)); + addr <<= 8; + addr |= Integer.parseInt(matcher.group(4)); + // int的最高位无法直接使用,转为Long if (addr < 0) { return IPV4_NUM_MAX & addr; diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java index 934a93180..fcd96153b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java @@ -5,6 +5,9 @@ import cn.hutool.core.map.BiMap; import java.util.HashMap; +import static cn.hutool.core.net.Ipv4Pool.IPV4_MASK_BIT_MAX; +import static cn.hutool.core.net.Ipv4Pool.IPV4_NUM_MAX; + /** * 掩码位和掩码之间的Map对应 * @@ -84,6 +87,6 @@ public class MaskBit { */ public static long getMaskIpLong(final int maskBit) { Assert.isTrue(MASK_BIT_MAP.containsKey(maskBit), "非法的掩码位数:{}", maskBit); - return (0xffffffffL << (32 - maskBit)) & 0xffffffffL; + return (IPV4_NUM_MAX << (IPV4_MASK_BIT_MAX - maskBit)) & IPV4_NUM_MAX; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java index 4a1491002..97afd3939 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java @@ -7,7 +7,14 @@ import org.junit.function.ThrowingRunnable; public class Ipv4UtilTest { @Test - public void getMaskBitByMaskTest(){ + public void formatIpBlockTest() { + for (int i = Ipv4Util.IPV4_MASK_BIT_VALID_MIN; i < Ipv4Util.IPV4_MASK_BIT_MAX; i++) { + Assert.assertEquals("192.168.1.101/" + i, Ipv4Util.formatIpBlock("192.168.1.101", Ipv4Util.getMaskByMaskBit(i))); + } + } + + @Test + public void getMaskBitByMaskTest() { final int maskBitByMask = Ipv4Util.getMaskBitByMask("255.255.255.0"); Assert.assertEquals(24, maskBitByMask); } @@ -19,7 +26,7 @@ public class Ipv4UtilTest { } @Test - public void getMaskByMaskBitTest(){ + public void getMaskByMaskBitTest() { final String mask = Ipv4Util.getMaskByMaskBit(24); Assert.assertEquals("255.255.255.0", mask); } @@ -39,7 +46,7 @@ public class Ipv4UtilTest { } @Test - public void getEndIpStrTest(){ + public void getEndIpStrTest() { final String ip = "192.168.1.1"; final int maskBitByMask = Ipv4Util.getMaskBitByMask("255.255.255.0"); final String endIpStr = Ipv4Util.getEndIpStr(ip, maskBitByMask); @@ -47,7 +54,7 @@ public class Ipv4UtilTest { } @Test - public void listTest(){ + public void listTest() { final String ip = "192.168.100.2"; testGenerateIpList(ip, 22, false); testGenerateIpList(ip, 22, true); @@ -66,7 +73,10 @@ public class Ipv4UtilTest { testGenerateIpList(ip, 32, false); testGenerateIpList(ip, 32, true); + } + @Test + public void listTest2() { testGenerateIpList("10.1.0.1", "10.2.1.2"); testGenerateIpList("10.2.1.1", "10.2.1.2"); @@ -182,4 +192,13 @@ public class Ipv4UtilTest { Assert.assertFalse(Ipv4Util.isPublicIP("172.20.10.1")); } + @Test + public void getMaskBitByIpRange() { + final String ip = "192.168.100.2"; + for (int i = 1; i <= 32; i++) { + String beginIpStr = Ipv4Util.getBeginIpStr(ip, i); + String endIpStr = Ipv4Util.getEndIpStr(ip, i); + Assert.assertEquals(Ipv4Util.getMaskByMaskBit(i), Ipv4Util.getMaskByIpRange(beginIpStr, endIpStr)); + } + } } diff --git a/hutool-db/src/main/java/cn/hutool/db/Entity.java b/hutool-db/src/main/java/cn/hutool/db/Entity.java index f9cdb7a54..79e5056aa 100755 --- a/hutool-db/src/main/java/cn/hutool/db/Entity.java +++ b/hutool-db/src/main/java/cn/hutool/db/Entity.java @@ -348,8 +348,9 @@ public class Entity extends Dict { * 获得字符串值
    * 支持Clob、Blob、RowId * - * @param field 字段名 - * @param charset 编码 + * @param field 字段名 + * @param charset 编码 + * @param defaultValue 默认值 * @return 字段对应值 */ public String getStr(final String field, final Charset charset, final String defaultValue) { From 1eb629bc3b3228bc34f83595cc6a09813ff944c0 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 17:05:40 +0800 Subject: [PATCH 068/125] fix code --- .../java/cn/hutool/core/net/Ipv4UtilTest.java | 4 +- .../http/client/engine/jdk/HttpBase.java | 321 ------------------ .../cn/hutool/http/webservice/SoapClient.java | 137 ++++---- .../http/webservice/SoapClientTest.java | 2 +- 4 files changed, 70 insertions(+), 394 deletions(-) delete mode 100644 hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpBase.java diff --git a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java index 97afd3939..234213362 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/Ipv4UtilTest.java @@ -196,8 +196,8 @@ public class Ipv4UtilTest { public void getMaskBitByIpRange() { final String ip = "192.168.100.2"; for (int i = 1; i <= 32; i++) { - String beginIpStr = Ipv4Util.getBeginIpStr(ip, i); - String endIpStr = Ipv4Util.getEndIpStr(ip, i); + final String beginIpStr = Ipv4Util.getBeginIpStr(ip, i); + final String endIpStr = Ipv4Util.getEndIpStr(ip, i); Assert.assertEquals(Ipv4Util.getMaskByMaskBit(i), Ipv4Util.getMaskByIpRange(beginIpStr, endIpStr)); } } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpBase.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpBase.java deleted file mode 100644 index f9ea28555..000000000 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpBase.java +++ /dev/null @@ -1,321 +0,0 @@ -package cn.hutool.http.client.engine.jdk; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.CaseInsensitiveMap; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.text.StrUtil; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.http.meta.Header; -import cn.hutool.http.client.HeaderOperation; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * http基类,提供请求和响应共用的属性和方法。 - * - * @param 子类类型,方便链式编程 - * @author Looly - */ -@SuppressWarnings("unchecked") -public abstract class HttpBase> implements HeaderOperation { - - /** - * 默认的请求编码、URL的encode、decode编码 - */ - protected static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8; - - /** - * HTTP/1.0 - */ - public static final String HTTP_1_0 = "HTTP/1.0"; - /** - * HTTP/1.1 - */ - public static final String HTTP_1_1 = "HTTP/1.1"; - - /** - * 存储头信息 - */ - protected Map> headers = new HashMap<>(); - /** - * 编码 - */ - protected Charset charset = DEFAULT_CHARSET; - /** - * http版本 - */ - protected String httpVersion = HTTP_1_1; - /** - * 存储主体 - */ - protected byte[] bodyBytes; - - // ---------------------------------------------------------------- Headers start - - /** - * 根据name获取头信息列表 - * - * @param name Header名 - * @return Header值 - * @since 3.1.1 - */ - public List headerList(final String name) { - if (StrUtil.isBlank(name)) { - return null; - } - - final CaseInsensitiveMap> headersIgnoreCase = new CaseInsensitiveMap<>(this.headers); - return headersIgnoreCase.get(name.trim()); - } - - /** - * 根据name获取头信息 - * - * @param header Header名 - * @return Header值 - */ - public String header(final Header header) { - if (null == header) { - return null; - } - return header(header.toString()); - } - - /** - * 设置一个header
    - * 如果覆盖模式,则替换之前的值,否则加入到值列表中 - * - * @param name Header名 - * @param value Header值 - * @param isOverride 是否覆盖已有值 - * @return T 本身 - */ - @Override - public T header(final String name, final String value, final boolean isOverride) { - if (null != name && null != value) { - final List values = headers.get(name.trim()); - if (isOverride || CollUtil.isEmpty(values)) { - final ArrayList valueList = new ArrayList<>(); - valueList.add(value); - headers.put(name.trim(), valueList); - } else { - values.add(value.trim()); - } - } - return (T) this; - } - - /** - * 设置请求头 - * - * @param headers 请求头 - * @param isOverride 是否覆盖已有头信息 - * @return this - * @since 4.6.3 - */ - public T headerMap(final Map headers, final boolean isOverride) { - if (MapUtil.isEmpty(headers)) { - return (T) this; - } - - for (final Entry entry : headers.entrySet()) { - this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), isOverride); - } - return (T) this; - } - - /** - * 设置请求头
    - * 不覆盖原有请求头 - * - * @param headers 请求头 - * @return this - */ - public T header(final Map> headers) { - return header(headers, false); - } - - /** - * 设置请求头 - * - * @param headers 请求头 - * @param isOverride 是否覆盖已有头信息 - * @return this - * @since 4.0.8 - */ - public T header(final Map> headers, final boolean isOverride) { - if (MapUtil.isEmpty(headers)) { - return (T) this; - } - - String name; - for (final Entry> entry : headers.entrySet()) { - name = entry.getKey(); - for (final String value : entry.getValue()) { - this.header(name, StrUtil.emptyIfNull(value), isOverride); - } - } - return (T) this; - } - - /** - * 新增请求头
    - * 不覆盖原有请求头 - * - * @param headers 请求头 - * @return this - * @since 4.0.3 - */ - public T addHeaders(final Map headers) { - if (MapUtil.isEmpty(headers)) { - return (T) this; - } - - for (final Entry entry : headers.entrySet()) { - this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), false); - } - return (T) this; - } - - /** - * 移除一个头信息 - * - * @param name Header名 - * @return this - */ - public T removeHeader(final String name) { - if (name != null) { - headers.remove(name.trim()); - } - return (T) this; - } - - /** - * 移除一个头信息 - * - * @param name Header名 - * @return this - */ - public T removeHeader(final Header name) { - return removeHeader(name.toString()); - } - - /** - * 获取headers - * - * @return Headers Map - */ - @Override - public Map> headers() { - return Collections.unmodifiableMap(headers); - } - - /** - * 清除所有头信息,包括全局头信息 - * - * @return this - * @since 5.7.13 - */ - public T clearHeaders() { - this.headers.clear(); - return (T) this; - } - // ---------------------------------------------------------------- Headers end - - /** - * 返回http版本 - * - * @return String - */ - public String httpVersion() { - return httpVersion; - } - - /** - * 设置http版本,此方法不会影响到实际请求的HTTP版本,只用于帮助判断是否connect:Keep-Alive - * - * @param httpVersion Http版本,{@link HttpBase#HTTP_1_0},{@link HttpBase#HTTP_1_1} - * @return this - */ - public T httpVersion(final String httpVersion) { - this.httpVersion = httpVersion; - return (T) this; - } - - /** - * 返回字符集 - * - * @return 字符集 - */ - public String charsetName() { - return charset.name(); - } - - /** - * 返回字符集 - * - * @return 字符集 - */ - public Charset charset() { - return this.charset; - } - - /** - * 设置字符集 - * - * @param charset 字符集 - * @return T 自己 - * @see CharsetUtil - */ - public T charset(final String charset) { - if (StrUtil.isNotBlank(charset)) { - charset(Charset.forName(charset)); - } - return (T) this; - } - - /** - * 设置字符集 - * - * @param charset 字符集 - * @return T 自己 - * @see CharsetUtil - */ - public T charset(final Charset charset) { - if (null != charset) { - this.charset = charset; - } - return (T) this; - } - - /** - * 获取bodyBytes存储字节码 - * - * @return byte[] - */ - public byte[] bodyBytes() { - return this.bodyBytes; - } - - @Override - public String toString() { - final StringBuilder sb = StrUtil.builder(); - sb.append("Request Headers: ").append(StrUtil.CRLF); - for (final Entry> entry : this.headers.entrySet()) { - sb.append(" ") - .append(entry.getKey()).append(":").append(CollUtil.join(entry.getValue(), ",")) - .append(StrUtil.CRLF); - } - - sb.append("Request Body: ").append(StrUtil.CRLF); - sb.append(" ").append(StrUtil.str(this.bodyBytes, this.charset)).append(StrUtil.CRLF); - - return sb.toString(); - } -} diff --git a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java index 5754f581b..f403f8f61 100644 --- a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java +++ b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java @@ -4,13 +4,17 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.XmlUtil; import cn.hutool.http.HttpGlobalConfig; +import cn.hutool.http.HttpUtil; +import cn.hutool.http.client.HeaderOperation; import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; import cn.hutool.http.client.engine.ClientEngineFactory; import cn.hutool.http.client.engine.jdk.HttpBase; +import cn.hutool.http.meta.Header; import javax.xml.XMLConstants; import javax.xml.namespace.QName; @@ -25,8 +29,7 @@ import javax.xml.soap.SOAPMessage; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; /** @@ -51,7 +54,7 @@ import java.util.Map.Entry; * @author looly * @since 4.5.4 */ -public class SoapClient extends HttpBase { +public class SoapClient implements HeaderOperation { /** * XML消息体的Content-Type @@ -66,15 +69,7 @@ public class SoapClient extends HttpBase { * 请求的URL地址 */ private String url; - - /** - * 默认连接超时 - */ - private int connectionTimeout = HttpGlobalConfig.getTimeout(); - /** - * 默认读取超时 - */ - private int readTimeout = HttpGlobalConfig.getTimeout(); + private Charset charset = CharsetUtil.UTF_8; /** * 消息工厂,用于创建消息 @@ -98,6 +93,10 @@ public class SoapClient extends HttpBase { * soap1.2 : application/soap+xml */ private final SoapProtocol protocol; + /** + * 存储头信息 + */ + private final Map> headers = new HashMap<>(); /** * 创建SOAP客户端,默认使用soap1.1版本协议 @@ -211,20 +210,16 @@ public class SoapClient extends HttpBase { * * @param charset 编码 * @return this - * @see #charset(Charset) */ - public SoapClient setCharset(final Charset charset) { - return this.charset(charset); - } - - @Override public SoapClient charset(final Charset charset) { - super.charset(charset); - try { - this.message.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, this.charset()); - this.message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true"); - } catch (final SOAPException e) { - // ignore + if (null != charset) { + this.charset = charset; + try { + this.message.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset.name()); + this.message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true"); + } catch (final SOAPException e) { + // ignore + } } return this; @@ -241,6 +236,51 @@ public class SoapClient extends HttpBase { return this; } + /** + * 设置一个header
    + * 如果覆盖模式,则替换之前的值,否则加入到值列表中 + * + * @param name Header名 + * @param value Header值 + * @param isOverride 是否覆盖已有值 + * @return T 本身 + */ + @Override + public SoapClient header(final String name, final String value, final boolean isOverride) { + if (null != name && null != value) { + final List values = headers.get(name.trim()); + if (isOverride || CollUtil.isEmpty(values)) { + final ArrayList valueList = new ArrayList<>(); + valueList.add(value); + headers.put(name.trim(), valueList); + } else { + values.add(value.trim()); + } + } + return this; + } + + /** + * 获取headers + * + * @return Headers Map + */ + @Override + public Map> headers() { + return Collections.unmodifiableMap(headers); + } + + /** + * 清除所有头信息,包括全局头信息 + * + * @return this + * @since 5.7.13 + */ + public SoapClient clearHeaders() { + this.headers.clear(); + return this; + } + /** * 增加SOAP头信息,方法返回{@link SOAPHeaderElement}可以设置具体属性和子节点 * @@ -493,50 +533,6 @@ public class SoapClient extends HttpBase { return this; } - /** - * 设置超时,单位:毫秒
    - * 超时包括: - * - *
    -	 * 1. 连接超时
    -	 * 2. 读取响应超时
    -	 * 
    - * - * @param milliseconds 超时毫秒数 - * @return this - * @see #setConnectionTimeout(int) - * @see #setReadTimeout(int) - */ - public SoapClient timeout(final int milliseconds) { - setConnectionTimeout(milliseconds); - setReadTimeout(milliseconds); - return this; - } - - /** - * 设置连接超时,单位:毫秒 - * - * @param milliseconds 超时毫秒数 - * @return this - * @since 4.5.6 - */ - public SoapClient setConnectionTimeout(final int milliseconds) { - this.connectionTimeout = milliseconds; - return this; - } - - /** - * 设置连接超时,单位:毫秒 - * - * @param milliseconds 超时毫秒数 - * @return this - * @since 4.5.6 - */ - public SoapClient setReadTimeout(final int milliseconds) { - this.readTimeout = milliseconds; - return this; - } - /** * 执行Webservice请求,即发送SOAP内容 * @@ -574,6 +570,7 @@ public class SoapClient extends HttpBase { * @param pretty 是否格式化 * @return 返回结果 */ + @SuppressWarnings("resource") public String send(final boolean pretty) { final String body = sendForResponse().bodyStr(); return pretty ? XmlUtil.format(body) : body; @@ -592,7 +589,7 @@ public class SoapClient extends HttpBase { .contentType(getXmlContentType()) .header(this.headers, false) .body(getMsgStr(false)); - return ClientEngineFactory.get().send(request); + return request.send(); } /** @@ -601,7 +598,7 @@ public class SoapClient extends HttpBase { * @return 请求的Content-Type */ private String getXmlContentType() { - switch (this.protocol){ + switch (this.protocol) { case SOAP_1_1: return CONTENT_TYPE_SOAP11_TEXT_XML.concat(this.charset.toString()); case SOAP_1_2: diff --git a/hutool-http/src/test/java/cn/hutool/http/webservice/SoapClientTest.java b/hutool-http/src/test/java/cn/hutool/http/webservice/SoapClientTest.java index c4266161d..4e7a28f62 100644 --- a/hutool-http/src/test/java/cn/hutool/http/webservice/SoapClientTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/webservice/SoapClientTest.java @@ -21,7 +21,7 @@ public class SoapClientTest { public void requestTest() { final SoapClient client = SoapClient.of("http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx") .setMethod("web:getCountryCityByIp", "http://WebXml.com.cn/") - .setCharset(CharsetUtil.GBK) + .charset(CharsetUtil.GBK) .setParam("theIpAddress", "218.21.240.106"); Console.log(client.getMsgStr(true)); From 01dc2450a0e02c83fcb4c7a52c03835c96e73535 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 17:09:03 +0800 Subject: [PATCH 069/125] fix code --- .../http/client/engine/ClientEngineFactory.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/ClientEngineFactory.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/ClientEngineFactory.java index 511ec716b..a1c19fce0 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/ClientEngineFactory.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/ClientEngineFactory.java @@ -4,6 +4,7 @@ import cn.hutool.core.lang.Singleton; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ServiceLoaderUtil; import cn.hutool.http.HttpException; +import cn.hutool.http.client.ClientConfig; import cn.hutool.http.client.ClientEngine; import cn.hutool.log.StaticLog; @@ -24,6 +25,18 @@ public class ClientEngineFactory { return Singleton.get(ClientEngine.class.getName(), ClientEngineFactory::of); } + /** + * 根据用户引入的HTTP客户端引擎jar,自动创建对应的拼音引擎对象
    + * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎 + * + * @param config Http客户端配置 + * @return {@code ClientEngine} + */ + @SuppressWarnings("resource") + public static ClientEngine of(final ClientConfig config) { + return of().setConfig(config); + } + /** * 根据用户引入的HTTP客户端引擎jar,自动创建对应的拼音引擎对象
    * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎 From 9784e8e2b4863ca94c9c34fa49603d9030c96e15 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 17:22:33 +0800 Subject: [PATCH 070/125] =?UTF-8?q?lambda=E4=BB=A3=E6=9B=BF=E5=8F=8D?= =?UTF-8?q?=E5=B0=84=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/bean/PropDesc.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java index 5946eaab1..5ffccf534 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java @@ -3,6 +3,7 @@ package cn.hutool.core.bean; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.annotation.PropIgnore; import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.reflect.FieldUtil; import cn.hutool.core.reflect.MethodUtil; import cn.hutool.core.reflect.ModifierUtil; @@ -153,7 +154,8 @@ public class PropDesc { */ public Object getValue(final Object bean) { if (null != this.getter) { - return MethodUtil.invoke(bean, this.getter); + //return MethodUtil.invoke(bean, this.getter); + return LambdaUtil.buildGetter(this.getter).apply(bean); } else if (ModifierUtil.isPublic(this.field)) { return FieldUtil.getFieldValue(bean, this.field); } @@ -224,7 +226,8 @@ public class PropDesc { */ public PropDesc setValue(final Object bean, final Object value) { if (null != this.setter) { - MethodUtil.invoke(bean, this.setter, value); + //MethodUtil.invoke(bean, this.setter, value); + LambdaUtil.buildSetter(this.setter).accept(bean, value); } else if (ModifierUtil.isPublic(this.field)) { FieldUtil.setFieldValue(bean, this.field, value); } From 7713db17303e0e925223024d36e67d4f1fcc2628 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 19:07:07 +0800 Subject: [PATCH 071/125] add PathMover --- .../main/java/cn/hutool/core/io/FileUtil.java | 41 ++--- .../cn/hutool/core/io/file/PathMover.java | 148 ++++++++++++++++++ .../java/cn/hutool/core/io/file/PathUtil.java | 89 +++-------- .../hutool/core/io/file/IssueI666HBTest.java | 47 ++++++ 4 files changed, 231 insertions(+), 94 deletions(-) create mode 100755 hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java create mode 100755 hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 33016d60b..b41fbbd86 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -1097,34 +1097,27 @@ public class FileUtil extends PathUtil { } /** - * 移动文件或者目录 + * 移动文件或目录到目标中,例如: + *
      + *
    • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
    • + *
    • 如果src为文件,target为文件,则按照是否覆盖参数执行。
    • + *
    • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
    • + *
    • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
    • + *
    • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
    • + *
    • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
    • + *
    * - * @param src 源文件或者目录 - * @param target 目标文件或者目录 - * @param isOverride 是否覆盖目标,只有目标为文件才覆盖 + * @param src 源文件或目录路径 + * @param target 目标路径,如果为目录,则移动到此目录下 + * @param isOverride 是否覆盖目标文件 + * @return 目标文件或目录 * @throws IORuntimeException IO异常 * @see PathUtil#move(Path, Path, boolean) */ - public static void move(final File src, final File target, final boolean isOverride) throws IORuntimeException { + public static File move(final File src, final File target, final boolean isOverride) throws IORuntimeException { Assert.notNull(src, "Src file must be not null!"); Assert.notNull(target, "target file must be not null!"); - move(src.toPath(), target.toPath(), isOverride); - } - - /** - * 移动文件或者目录 - * - * @param src 源文件或者目录 - * @param target 目标文件或者目录 - * @param isOverride 是否覆盖目标,只有目标为文件才覆盖 - * @throws IORuntimeException IO异常 - * @see PathUtil#moveContent(Path, Path, boolean) - * @since 5.7.9 - */ - public static void moveContent(final File src, final File target, final boolean isOverride) throws IORuntimeException { - Assert.notNull(src, "Src file must be not null!"); - Assert.notNull(target, "target file must be not null!"); - moveContent(src.toPath(), target.toPath(), isOverride); + return move(src.toPath(), target.toPath(), isOverride).toFile(); } /** @@ -1763,7 +1756,7 @@ public class FileUtil extends PathUtil { * @param file 文件 * @return 输入流 * @throws IORuntimeException 文件未找到 - * @see IoUtil#toStream(File) + * @see IoUtil#toStream(File) */ public static BufferedInputStream getInputStream(final File file) throws IORuntimeException { return IoUtil.toBuffered(IoUtil.toStream(file)); @@ -3048,7 +3041,7 @@ public class FileUtil extends PathUtil { * getParent(file("d:/aaa/bbb/cc/ddd")) -》 "d:/aaa/bbb/cc" *
* - * @param file 目录或文件 + * @param file 目录或文件 * @return 路径File,如果不存在返回null * @since 6.0.0 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java new file mode 100755 index 000000000..30c53a11c --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -0,0 +1,148 @@ +package cn.hutool.core.io.file; + +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.visitor.MoveVisitor; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; + +import java.io.IOException; +import java.nio.file.*; + +/** + * 文件移动封装 + * + * @author looly + * @since 6.0.0 + */ +public class PathMover { + + /** + * 创建文件或目录移动器 + * + * @param src 源文件或目录 + * @param target 目标文件或目录 + * @param isOverride 是否覆盖目标文件 + * @return {@link PathMover} + */ + public static PathMover of(final Path src, final Path target, final boolean isOverride) { + return of(src, target, isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}); + } + + /** + * 创建文件或目录移动器 + * + * @param src 源文件或目录 + * @param target 目标文件或目录 + * @param options 移动参数 + * @return {@link PathMover} + */ + public static PathMover of(final Path src, final Path target, final CopyOption[] options) { + return new PathMover(src, target, options); + } + + private final Path src; + private final Path target; + private final CopyOption[] options; + + /** + * 构造 + * + * @param src 源文件或目录 + * @param target 目标文件或目录 + * @param options 移动参数 + */ + public PathMover(final Path src, final Path target, final CopyOption[] options) { + this.src = Assert.notNull(src, "Src path must be not null !"); + this.target = Assert.notNull(target, "Target path must be not null !"); + this.options = options; + } + + /** + * 移动文件或目录到目标中,例如: + *
    + *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • + *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • + *
  • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • + *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • + *
+ * + * @return 目标文件Path + */ + public Path move() { + final Path src = this.src; + Path target = this.target; + final CopyOption[] options = ObjUtil.defaultIfNull(this.options, new CopyOption[]{}); + + if (false == PathUtil.exists(target, false) || PathUtil.isDirectory(target)) { + // 创建子路径的情况,1是目标是目录,需要移动到目录下,2是目标不能存在,自动创建目录 + target = target.resolve(src.getFileName()); + } + + // issue#2893 target 不存在导致NoSuchFileException + if (Files.exists(target) && PathUtil.equals(src, target)) { + // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 + return target; + } + + // 自动创建目标的父目录 + PathUtil.mkParentDirs(target); + try { + return Files.move(src, target, options); + } catch (final IOException e) { + if (e instanceof FileAlreadyExistsException) { + // 目标文件已存在,直接抛出异常 + // issue#I4QV0L@Gitee + throw new IORuntimeException(e); + } + // 移动失败,可能是跨分区移动导致的,采用递归移动方式 + try { + Files.walkFileTree(src, new MoveVisitor(src, target, options)); + // 移动后空目录没有删除, + PathUtil.del(src); + } catch (final IOException e2) { + throw new IORuntimeException(e2); + } + return target; + } + } + + /** + * 移动文件或目录内容到目标中,例如: + *
    + *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • + *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • + *
  • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中。
  • + *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中。
  • + *
+ * + * @return 目标文件Path + */ + public Path moveContent() { + final Path src = this.src; + final Path target = this.target; + final CopyOption[] options = ObjUtil.defaultIfNull(this.options, new CopyOption[]{}); + + // 移动失败,可能是跨分区移动导致的,采用递归移动方式 + try { + if (false == PathUtil.isDirectory(src)) { + // 文件移动到目标目录或文件 + return Files.move(src, target, options); + } + + if (false == PathUtil.isDirectory(target)) { + throw new IllegalArgumentException("Can not move dir content to a file"); + } + + // 移动源目录下的内容而不删除目录 + Files.walkFileTree(src, new MoveVisitor(src, target, options)); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + return target; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 84eb66659..e7bb8e108 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -4,31 +4,12 @@ import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.visitor.CopyVisitor; import cn.hutool.core.io.file.visitor.DelVisitor; -import cn.hutool.core.io.file.visitor.MoveVisitor; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.CharsetUtil; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.nio.charset.Charset; -import java.nio.file.AccessDeniedException; -import java.nio.file.CopyOption; -import java.nio.file.DirectoryStream; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.FileVisitOption; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.EnumSet; @@ -470,75 +451,43 @@ public class PathUtil { } /** - * 移动文件或目录
- * 当目标是目录时,会将源文件或文件夹整体移动至目标目录下
- * 例如: + * 移动文件或目录到目标中,例如: *
    - *
  • move("/usr/aaa/abc.txt", "/usr/bbb")结果为:"/usr/bbb/abc.txt"
  • - *
  • move("/usr/aaa", "/usr/bbb")结果为:"/usr/bbb/aaa"
  • + *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • + *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • + *
  • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • + *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • *
* * @param src 源文件或目录路径 * @param target 目标路径,如果为目录,则移动到此目录下 * @param isOverride 是否覆盖目标文件 * @return 目标文件Path - * @since 5.5.1 */ - public static Path move(final Path src, Path target, final boolean isOverride) { - Assert.notNull(src, "Src path must be not null !"); - Assert.notNull(target, "Target path must be not null !"); - - if (isDirectory(target)) { - target = target.resolve(src.getFileName()); - } - return moveContent(src, target, isOverride); + public static Path move(final Path src, final Path target, final boolean isOverride) { + return PathMover.of(src, target, isOverride).move(); } /** - * 移动文件或目录内容到目标目录中,例如: + * 移动文件或目录内容到目标中,例如: *
    - *
  • moveContent("/usr/aaa/abc.txt", "/usr/bbb")结果为:"/usr/bbb/abc.txt"
  • - *
  • moveContent("/usr/aaa", "/usr/bbb")结果为:"/usr/bbb"
  • + *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • + *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • + *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • + *
  • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中。
  • + *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中。
  • *
* * @param src 源文件或目录路径 * @param target 目标路径,如果为目录,则移动到此目录下 * @param isOverride 是否覆盖目标文件 * @return 目标文件Path - * @since 5.7.9 */ public static Path moveContent(final Path src, final Path target, final boolean isOverride) { - Assert.notNull(src, "Src path must be not null !"); - Assert.notNull(target, "Target path must be not null !"); - - // issue#2893 target 不存在导致NoSuchFileException - if(Files.exists(target) && equals(src, target)){ - // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 - return target; - } - - final CopyOption[] options = isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}; - - // 自动创建目标的父目录 - mkParentDirs(target); - try { - return Files.move(src, target, options); - } catch (final IOException e) { - if(e instanceof FileAlreadyExistsException){ - // 目标文件已存在,直接抛出异常 - // issue#I4QV0L@Gitee - throw new IORuntimeException(e); - } - // 移动失败,可能是跨分区移动导致的,采用递归移动方式 - try { - Files.walkFileTree(src, new MoveVisitor(src, target, options)); - // 移动后空目录没有删除, - del(src); - } catch (final IOException e2) { - throw new IORuntimeException(e2); - } - return target; - } + return PathMover.of(src, target, isOverride).moveContent(); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java new file mode 100755 index 000000000..46285b176 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java @@ -0,0 +1,47 @@ +package cn.hutool.core.io.file; + +import cn.hutool.core.io.FileUtil; +import org.junit.Ignore; +import org.junit.Test; + +/** + * 移动情况测试,环境: + *
+ *     d:/test/dir1/test1.txt   文件
+ *     d:/test/dir2/            空目录
+ * 
+ */ +public class IssueI666HBTest { + + @Test + @Ignore + public void moveDirToDirTest() { + // 目录移动到目录,将整个目录移动 + // 会将dir1及其内容移动到dir2下,变成dir2/dir1 + FileUtil.move(FileUtil.file("d:/test/dir1"), FileUtil.file("d:/test/dir2"), false); + } + + @Test + @Ignore + public void moveFileToDirTest() { + // 文件移动到目录 + // 会将test1.txt移动到dir2下,变成dir2/test1.txt + FileUtil.move(FileUtil.file("d:/test/dir1/test1.txt"), FileUtil.file("d:/test/dir2"), false); + } + + @Test + @Ignore + public void moveDirToDirNotExistTest() { + // 目录移动到目标,dir3不存在,将整个目录移动 + // 会将目录dir1变成目录dir3 + FileUtil.move(FileUtil.file("d:/test/dir1"), FileUtil.file("d:/test/dir3"), false); + } + + @Test + @Ignore + public void moveFileToTargetNotExistTest() { + // 目录移动到目录,将整个目录移动 + // 会将test1.txt重命名为test2 + FileUtil.move(FileUtil.file("d:/test/dir1/test1.txt"), FileUtil.file("d:/test/test2"), false); + } +} From fb49d79f8b6c7a2b01ff4f1c58a1b9a542d723e1 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 19:59:00 +0800 Subject: [PATCH 072/125] fixcode --- .../cn/hutool/core/io/file/PathMover.java | 71 ++++++++++++------- .../java/cn/hutool/core/io/file/PathUtil.java | 25 ++++++- .../hutool/core/io/file/IssueI666HBTest.java | 42 ++++++++++- 3 files changed, 109 insertions(+), 29 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java index 30c53a11c..4427b41dd 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -23,7 +23,7 @@ public class PathMover { * @param src 源文件或目录 * @param target 目标文件或目录 * @param isOverride 是否覆盖目标文件 - * @return {@link PathMover} + * @return {@code PathMover} */ public static PathMover of(final Path src, final Path target, final boolean isOverride) { return of(src, target, isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}); @@ -35,7 +35,7 @@ public class PathMover { * @param src 源文件或目录 * @param target 目标文件或目录 * @param options 移动参数 - * @return {@link PathMover} + * @return {@code PathMover} */ public static PathMover of(final Path src, final Path target, final CopyOption[] options) { return new PathMover(src, target, options); @@ -48,25 +48,30 @@ public class PathMover { /** * 构造 * - * @param src 源文件或目录 + * @param src 源文件或目录,不能为{@code null}且必须存在 * @param target 目标文件或目录 * @param options 移动参数 */ public PathMover(final Path src, final Path target, final CopyOption[] options) { - this.src = Assert.notNull(src, "Src path must be not null !"); + Assert.notNull(target, "Src path must be not null !"); + if(false == PathUtil.exists(src, false)){ + throw new IllegalArgumentException("Src path is not exist!"); + } + this.src = src; this.target = Assert.notNull(target, "Target path must be not null !"); - this.options = options; + this.options = ObjUtil.defaultIfNull(options, new CopyOption[]{});; } /** * 移动文件或目录到目标中,例如: *
    + *
  • 如果src和target为同一文件或目录,直接返回target。
  • *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • *
  • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • - *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • + *
  • 如果src为目录,target为不存在的路径,则重命名src到target,如move("/a/b", "/c/d"),结果为"/c/d/",相当于b重命名为d
  • *
* * @return 目标文件Path @@ -74,9 +79,9 @@ public class PathMover { public Path move() { final Path src = this.src; Path target = this.target; - final CopyOption[] options = ObjUtil.defaultIfNull(this.options, new CopyOption[]{}); + final CopyOption[] options = this.options; - if (false == PathUtil.exists(target, false) || PathUtil.isDirectory(target)) { + if (PathUtil.isDirectory(target)) { // 创建子路径的情况,1是目标是目录,需要移动到目录下,2是目标不能存在,自动创建目录 target = target.resolve(src.getFileName()); } @@ -98,13 +103,9 @@ public class PathMover { throw new IORuntimeException(e); } // 移动失败,可能是跨分区移动导致的,采用递归移动方式 - try { - Files.walkFileTree(src, new MoveVisitor(src, target, options)); - // 移动后空目录没有删除, - PathUtil.del(src); - } catch (final IOException e2) { - throw new IORuntimeException(e2); - } + walkMove(src, target, options); + // 移动后删除空目录 + PathUtil.del(src); return target; } } @@ -124,25 +125,43 @@ public class PathMover { */ public Path moveContent() { final Path src = this.src; + if (PathUtil.isNotDirectory(target, false)) { + // 文件移动调用move方法 + return move(); + } + final Path target = this.target; - final CopyOption[] options = ObjUtil.defaultIfNull(this.options, new CopyOption[]{}); + if (PathUtil.isNotDirectory(target, false)) { + // 目标不能为文件 + throw new IllegalArgumentException("Can not move dir content to a file"); + } + + // issue#2893 target 不存在导致NoSuchFileException + if (PathUtil.equals(src, target)) { + // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 + return target; + } + + final CopyOption[] options = this.options; // 移动失败,可能是跨分区移动导致的,采用递归移动方式 + walkMove(src, target, options); + return target; + } + + /** + * 递归移动 + * + * @param src 源目录 + * @param target 目标目录 + * @param options 移动参数 + */ + private static void walkMove(final Path src, final Path target, final CopyOption... options) { try { - if (false == PathUtil.isDirectory(src)) { - // 文件移动到目标目录或文件 - return Files.move(src, target, options); - } - - if (false == PathUtil.isDirectory(target)) { - throw new IllegalArgumentException("Can not move dir content to a file"); - } - // 移动源目录下的内容而不删除目录 Files.walkFileTree(src, new MoveVisitor(src, target, options)); } catch (final IOException e) { throw new IORuntimeException(e); } - return target; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index e7bb8e108..8a476d37d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -252,6 +252,22 @@ public class PathUtil { return isDirectory(path, false); } + /** + * 判断是否为非目录 + *
    + *
  • 如果path为{@code null},返回{@code false}
  • + *
  • 如果path不存在,返回{@code false}
  • + *
+ * + * @param path {@link Path} + * @param isFollowLinks 是否追踪到软链对应的真实地址 + * @return 如果为目录true + * @since 3.1.0 + */ + public static boolean isNotDirectory(final Path path, final boolean isFollowLinks) { + return exists(path, isFollowLinks) && false == isDirectory(path, isFollowLinks); + } + /** * 判断是否为目录,如果file为null,则返回false * @@ -438,6 +454,7 @@ public class PathUtil { * *
 	 * FileUtil.rename(file, "aaa.jpg", false) xx/xx.png =》xx/aaa.jpg
+	 * FileUtil.rename(dir, "dir2", false) xx/xx/ =》xx/dir2/
 	 * 
* * @param path 被修改的文件 @@ -453,12 +470,13 @@ public class PathUtil { /** * 移动文件或目录到目标中,例如: *
    + *
  • 如果src和target为同一文件或目录,直接返回target。
  • *
  • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
  • *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • *
  • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • - *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
  • + *
  • 如果src为目录,target为不存在的路径,则重命名src到target,如move("/a/b", "/c/d"),结果为"/c/d/",相当于b重命名为d
  • *
* * @param src 源文件或目录路径 @@ -539,12 +557,15 @@ public class PathUtil { /** * 判断文件或目录是否存在 * - * @param path 文件 + * @param path 文件,{@code null}返回{@code false} * @param isFollowLinks 是否跟踪软链(快捷方式) * @return 是否存在 * @since 5.5.3 */ public static boolean exists(final Path path, final boolean isFollowLinks) { + if (null == path) { + return false; + } final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS}; return Files.exists(path, options); } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java index 46285b176..6e16ca2f9 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java @@ -21,6 +21,16 @@ public class IssueI666HBTest { FileUtil.move(FileUtil.file("d:/test/dir1"), FileUtil.file("d:/test/dir2"), false); } + @Test + @Ignore + public void moveContentDirToDirTest() { + // 目录内容移动到目录 + // 移动内容,不移除目录本身 + PathUtil.moveContent( + FileUtil.file("d:/test/dir1").toPath(), + FileUtil.file("d:/test/dir2").toPath(), false); + } + @Test @Ignore public void moveFileToDirTest() { @@ -29,6 +39,16 @@ public class IssueI666HBTest { FileUtil.move(FileUtil.file("d:/test/dir1/test1.txt"), FileUtil.file("d:/test/dir2"), false); } + @Test + @Ignore + public void moveContentFileToDirTest() { + // 文件移动到目录 + // 会将test1.txt移动到dir2下,变成dir2/test1.txt + PathUtil.moveContent( + FileUtil.file("d:/test/dir1/test1.txt").toPath(), + FileUtil.file("d:/test/dir2").toPath(), false); + } + @Test @Ignore public void moveDirToDirNotExistTest() { @@ -37,11 +57,31 @@ public class IssueI666HBTest { FileUtil.move(FileUtil.file("d:/test/dir1"), FileUtil.file("d:/test/dir3"), false); } + @Test + @Ignore + public void moveContentDirToDirNotExistTest() { + // 目录移动到目标,dir3不存在 + // 会将目录dir1内容移动到dir3,但是dir1目录不删除 + PathUtil.moveContent( + FileUtil.file("d:/test/dir1").toPath(), + FileUtil.file("d:/test/dir3").toPath(), false); + } + @Test @Ignore public void moveFileToTargetNotExistTest() { - // 目录移动到目录,将整个目录移动 + // 文件移动到不存在的路径 // 会将test1.txt重命名为test2 FileUtil.move(FileUtil.file("d:/test/dir1/test1.txt"), FileUtil.file("d:/test/test2"), false); } + + @Test + @Ignore + public void moveContentFileToTargetNotExistTest() { + // 目录移动到目录,将整个目录移动 + // 会将test1.txt重命名为test2 + PathUtil.moveContent( + FileUtil.file("d:/test/dir1/test1.txt").toPath(), + FileUtil.file("d:/test/test2").toPath(), false); + } } From 81b0e95500a055bcb418dfd03cbceecf4f5bb061 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 21:04:04 +0800 Subject: [PATCH 073/125] remove FileCopier --- .../main/java/cn/hutool/core/io/FileUtil.java | 88 ++--- .../cn/hutool/core/io/file/FileCopier.java | 313 ------------------ .../cn/hutool/core/io/file/PathCopier.java | 165 +++++++++ .../cn/hutool/core/io/file/PathMover.java | 9 +- .../java/cn/hutool/core/io/file/PathUtil.java | 92 ++--- .../core/lang/copier/SrcToDestCopier.java | 12 +- .../cn/hutool/core/io/FileCopierTest.java | 59 ---- .../java/cn/hutool/core/io/FileUtilTest.java | 9 - .../cn/hutool/core/io/file/PathCopyTest.java | 79 +++++ .../cn/hutool/core/io/file/PathUtilTest.java | 2 +- 10 files changed, 296 insertions(+), 532 deletions(-) delete mode 100755 hutool-core/src/main/java/cn/hutool/core/io/file/FileCopier.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java delete mode 100644 hutool-core/src/test/java/cn/hutool/core/io/FileCopierTest.java create mode 100755 hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index b41fbbd86..78073629d 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -44,11 +44,7 @@ import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; -import java.nio.file.DirectoryNotEmptyException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; +import java.nio.file.*; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -984,43 +980,6 @@ public class FileUtil extends PathUtil { } } - /** - * 通过JDK7+的 Files#copy(Path, Path, CopyOption...) 方法拷贝文件 - * - * @param src 源文件路径 - * @param dest 目标文件或目录路径,如果为目录使用与源文件相同的文件名 - * @param options {@link StandardCopyOption} - * @return File - * @throws IORuntimeException IO异常 - */ - public static File copyFile(final String src, final String dest, final StandardCopyOption... options) throws IORuntimeException { - Assert.notBlank(src, "Source File path is blank !"); - Assert.notBlank(dest, "Destination File path is blank !"); - return copyFile(Paths.get(src), Paths.get(dest), options).toFile(); - } - - /** - * 通过JDK7+的 Files#copy(Path, Path, CopyOption...) 方法拷贝文件 - * - * @param src 源文件 - * @param dest 目标文件或目录,如果为目录使用与源文件相同的文件名 - * @param options {@link StandardCopyOption} - * @return 目标文件 - * @throws IORuntimeException IO异常 - */ - public static File copyFile(final File src, final File dest, final StandardCopyOption... options) throws IORuntimeException { - // check - Assert.notNull(src, "Source File is null !"); - if (false == src.exists()) { - throw new IORuntimeException("File not exist: " + src); - } - Assert.notNull(dest, "Destination File or directiory is null !"); - if (equals(src, dest)) { - throw new IORuntimeException("Files '{}' and '{}' are equal", src, dest); - } - return copyFile(src.toPath(), dest.toPath(), options).toFile(); - } - /** * 复制文件或目录
* 如果目标文件为目录,则将源文件以相同文件名拷贝到目标目录 @@ -1046,13 +1005,19 @@ public class FileUtil extends PathUtil { * * * @param src 源文件 - * @param dest 目标文件或目录,目标不存在会自动创建(目录、文件都创建) + * @param target 目标文件或目录,目标不存在会自动创建(目录、文件都创建) * @param isOverride 是否覆盖目标文件 * @return 目标目录或文件 * @throws IORuntimeException IO异常 */ - public static File copy(final File src, final File dest, final boolean isOverride) throws IORuntimeException { - return FileCopier.of(src, dest).setOverride(isOverride).copy(); + public static File copy(final File src, final File target, final boolean isOverride) throws IORuntimeException { + Assert.notNull(src, "Src file must be not null!"); + Assert.notNull(target, "target file must be not null!"); + return PathUtil.copy( + src.toPath(), + target.toPath(), + isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) + .toFile(); } /** @@ -1066,34 +1031,19 @@ public class FileUtil extends PathUtil { * * * @param src 源文件 - * @param dest 目标文件或目录,目标不存在会自动创建(目录、文件都创建) + * @param target 目标文件或目录,目标不存在会自动创建(目录、文件都创建) * @param isOverride 是否覆盖目标文件 * @return 目标目录或文件 * @throws IORuntimeException IO异常 */ - public static File copyContent(final File src, final File dest, final boolean isOverride) throws IORuntimeException { - return FileCopier.of(src, dest).setCopyContentIfDir(true).setOverride(isOverride).copy(); - } - - /** - * 复制文件或目录
- * 情况如下: - * - *
-	 * 1、src和dest都为目录,则将src下所有文件(包括子目录)拷贝到dest下
-	 * 2、src和dest都为文件,直接复制,名字为dest
-	 * 3、src为文件,dest为目录,将src拷贝到dest目录下
-	 * 
- * - * @param src 源文件 - * @param dest 目标文件或目录,目标不存在会自动创建(目录、文件都创建) - * @param isOverride 是否覆盖目标文件 - * @return 目标目录或文件 - * @throws IORuntimeException IO异常 - * @since 4.1.5 - */ - public static File copyFilesFromDir(final File src, final File dest, final boolean isOverride) throws IORuntimeException { - return FileCopier.of(src, dest).setCopyContentIfDir(true).setOnlyCopyFile(true).setOverride(isOverride).copy(); + public static File copyContent(final File src, final File target, final boolean isOverride) throws IORuntimeException { + Assert.notNull(src, "Src file must be not null!"); + Assert.notNull(target, "target file must be not null!"); + return PathUtil.copyContent( + src.toPath(), + target.toPath(), + isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) + .toFile(); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileCopier.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileCopier.java deleted file mode 100755 index 7ced5f670..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileCopier.java +++ /dev/null @@ -1,313 +0,0 @@ -package cn.hutool.core.io.file; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.copier.SrcToDestCopier; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.text.StrUtil; - -import java.io.File; -import java.io.IOException; -import java.nio.file.CopyOption; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; - -/** - * 文件拷贝器
- * 支持以下几种情况: - *
- * 1、文件复制到文件
- * 2、文件复制到目录
- * 3、目录复制到目录
- * 4、目录下的文件和目录复制到另一个目录
- * 
- * - * @author Looly - * @since 3.0.9 - */ -public class FileCopier extends SrcToDestCopier { - private static final long serialVersionUID = 1L; - - /** - * 是否覆盖目标文件 - */ - private boolean isOverride; - /** - * 是否拷贝所有属性 - */ - private boolean isCopyAttributes; - /** - * 当拷贝来源是目录时是否只拷贝目录下的内容 - */ - private boolean isCopyContentIfDir; - /** - * 当拷贝来源是目录时是否只拷贝文件而忽略子目录 - */ - private boolean isOnlyCopyFile; - - //-------------------------------------------------------------------------------------------------------- static method start - - /** - * 新建一个文件复制器 - * - * @param srcPath 源文件路径(相对ClassPath路径或绝对路径) - * @param destPath 目标文件路径(相对ClassPath路径或绝对路径) - * @return this - */ - public static FileCopier of(final String srcPath, final String destPath) { - return new FileCopier(FileUtil.file(srcPath), FileUtil.file(destPath)); - } - - /** - * 新建一个文件复制器 - * - * @param src 源文件 - * @param dest 目标文件 - * @return this - */ - public static FileCopier of(final File src, final File dest) { - return new FileCopier(src, dest); - } - //-------------------------------------------------------------------------------------------------------- static method end - - //-------------------------------------------------------------------------------------------------------- Constructor start - - /** - * 构造 - * - * @param src 源文件 - * @param dest 目标文件 - */ - public FileCopier(final File src, final File dest) { - this.src = src; - this.dest = dest; - } - //-------------------------------------------------------------------------------------------------------- Constructor end - - //-------------------------------------------------------------------------------------------------------- Getters and Setters start - - /** - * 是否覆盖目标文件 - * - * @return 是否覆盖目标文件 - */ - public boolean isOverride() { - return isOverride; - } - - /** - * 设置是否覆盖目标文件 - * - * @param isOverride 是否覆盖目标文件 - * @return this - */ - public FileCopier setOverride(final boolean isOverride) { - this.isOverride = isOverride; - return this; - } - - /** - * 是否拷贝所有属性 - * - * @return 是否拷贝所有属性 - */ - public boolean isCopyAttributes() { - return isCopyAttributes; - } - - /** - * 设置是否拷贝所有属性 - * - * @param isCopyAttributes 是否拷贝所有属性 - * @return this - */ - public FileCopier setCopyAttributes(final boolean isCopyAttributes) { - this.isCopyAttributes = isCopyAttributes; - return this; - } - - /** - * 当拷贝来源是目录时是否只拷贝目录下的内容 - * - * @return 当拷贝来源是目录时是否只拷贝目录下的内容 - */ - public boolean isCopyContentIfDir() { - return isCopyContentIfDir; - } - - /** - * 当拷贝来源是目录时是否只拷贝目录下的内容 - * - * @param isCopyContentIfDir 是否只拷贝目录下的内容 - * @return this - */ - public FileCopier setCopyContentIfDir(final boolean isCopyContentIfDir) { - this.isCopyContentIfDir = isCopyContentIfDir; - return this; - } - - /** - * 当拷贝来源是目录时是否只拷贝文件而忽略子目录 - * - * @return 当拷贝来源是目录时是否只拷贝文件而忽略子目录 - * @since 4.1.5 - */ - public boolean isOnlyCopyFile() { - return isOnlyCopyFile; - } - - /** - * 设置当拷贝来源是目录时是否只拷贝文件而忽略子目录 - * - * @param isOnlyCopyFile 当拷贝来源是目录时是否只拷贝文件而忽略子目录 - * @return this - * @since 4.1.5 - */ - public FileCopier setOnlyCopyFile(final boolean isOnlyCopyFile) { - this.isOnlyCopyFile = isOnlyCopyFile; - return this; - } - //-------------------------------------------------------------------------------------------------------- Getters and Setters end - - /** - * 执行拷贝
- * 拷贝规则为: - *
-	 * 1、源为文件,目标为已存在目录,则拷贝到目录下,文件名不变
-	 * 2、源为文件,目标为不存在路径,则目标以文件对待(自动创建父级目录)比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
-	 * 3、源为文件,目标是一个已存在的文件,则当{@link #setOverride(boolean)}设为true时会被覆盖,默认不覆盖
-	 * 4、源为目录,目标为已存在目录,当{@link #setCopyContentIfDir(boolean)}为true时,只拷贝目录中的内容到目标目录中,否则整个源目录连同其目录拷贝到目标目录中
-	 * 5、源为目录,目标为不存在路径,则自动创建目标为新目录,然后按照规则4复制
-	 * 6、源为目录,目标为文件,抛出IO异常
-	 * 7、源路径和目标路径相同时,抛出IO异常
-	 * 
- * - * @return 拷贝后目标的文件或目录 - * @throws IORuntimeException IO异常 - */ - @Override - public File copy() throws IORuntimeException { - final File src = this.src; - File dest = this.dest; - // check - Assert.notNull(src, "Source File is null !"); - if (false == src.exists()) { - throw new IORuntimeException("File not exist: " + src); - } - Assert.notNull(dest, "Destination File or directiory is null !"); - if (FileUtil.equals(src, dest)) { - throw new IORuntimeException("Files '{}' and '{}' are equal", src, dest); - } - - if (src.isDirectory()) {// 复制目录 - if (dest.exists() && false == dest.isDirectory()) { - //源为目录,目标为文件,抛出IO异常 - throw new IORuntimeException("Src is a directory but dest is a file!"); - } - if (FileUtil.isSub(src, dest)) { - throw new IORuntimeException("Dest is a sub directory of src !"); - } - - final File subTarget = isCopyContentIfDir ? dest : FileUtil.mkdir(FileUtil.file(dest, src.getName())); - internalCopyDirContent(src, subTarget); - } else {// 复制文件 - dest = internalCopyFile(src, dest); - } - return dest; - } - - //----------------------------------------------------------------------------------------- Private method start - - /** - * 拷贝目录内容,只用于内部,不做任何安全检查
- * 拷贝内容的意思为源目录下的所有文件和目录拷贝到另一个目录下,而不拷贝源目录本身 - * - * @param src 源目录 - * @param dest 目标目录 - * @throws IORuntimeException IO异常 - */ - private void internalCopyDirContent(final File src, final File dest) throws IORuntimeException { - if (null != copyPredicate && false == copyPredicate.test(src)) { - //被过滤的目录跳过 - return; - } - - if (false == dest.exists()) { - //目标为不存在路径,创建为目录 - //noinspection ResultOfMethodCallIgnored - dest.mkdirs(); - } else if (false == dest.isDirectory()) { - throw new IORuntimeException(StrUtil.format("Src [{}] is a directory but dest [{}] is a file!", src.getPath(), dest.getPath())); - } - - final String[] files = src.list(); - if (ArrayUtil.isNotEmpty(files)) { - File srcFile; - File destFile; - for (final String file : files) { - srcFile = new File(src, file); - destFile = this.isOnlyCopyFile ? dest : new File(dest, file); - // 递归复制 - if (srcFile.isDirectory()) { - internalCopyDirContent(srcFile, destFile); - } else { - internalCopyFile(srcFile, destFile); - } - } - } - } - - /** - * 拷贝文件,只用于内部,不做任何安全检查
- * 情况如下: - *
-	 * 1、如果目标是一个不存在的路径,则目标以文件对待(自动创建父级目录)比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
-	 * 2、如果目标是一个已存在的目录,则文件拷贝到此目录下,文件名与原文件名一致
-	 * 
- * - * @param src 源文件,必须为文件 - * @param dest 目标文件,如果非覆盖模式必须为目录 - * @return 目标文件 - * @throws IORuntimeException IO异常 - */ - private File internalCopyFile(final File src, File dest) throws IORuntimeException { - if (null != copyPredicate && false == copyPredicate.test(src)) { - //被过滤的文件跳过 - return dest; - } - - // 如果已经存在目标文件,切为不覆盖模式,跳过之 - if (dest.exists()) { - if (dest.isDirectory()) { - //目标为目录,目录下创建同名文件 - dest = new File(dest, src.getName()); - } - - if (dest.exists() && false == isOverride) { - //非覆盖模式跳过 - return dest; - } - } else { - //路径不存在则创建父目录 - FileUtil.mkParentDirs(dest); - } - - final ArrayList optionList = new ArrayList<>(2); - if (isOverride) { - optionList.add(StandardCopyOption.REPLACE_EXISTING); - } - if (isCopyAttributes) { - optionList.add(StandardCopyOption.COPY_ATTRIBUTES); - } - - try { - Files.copy(src.toPath(), dest.toPath(), optionList.toArray(new CopyOption[0])); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - return dest; - } - //----------------------------------------------------------------------------------------- Private method end -} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java new file mode 100755 index 000000000..99e27bcbe --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java @@ -0,0 +1,165 @@ +package cn.hutool.core.io.file; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.visitor.CopyVisitor; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.copier.SrcToDestCopier; +import cn.hutool.core.util.ObjUtil; + +import java.io.IOException; +import java.nio.file.*; + +/** + * 文件复制封装 + * + * @author looly + * @since 6.0.0 + */ +public class PathCopier extends SrcToDestCopier { + private static final long serialVersionUID = 1L; + + /** + * 创建文件或目录拷贝器 + * + * @param src 源文件或目录 + * @param target 目标文件或目录 + * @param isOverride 是否覆盖目标文件 + * @return {@code PathCopier} + */ + public static PathCopier of(final Path src, final Path target, final boolean isOverride) { + return of(src, target, isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}); + } + + /** + * 创建文件或目录拷贝器 + * + * @param src 源文件或目录 + * @param target 目标文件或目录 + * @param options 拷贝参数 + * @return {@code PathCopier} + */ + public static PathCopier of(final Path src, final Path target, final CopyOption[] options) { + return new PathCopier(src, target, options); + } + + private final CopyOption[] options; + + /** + * 构造 + * + * @param src 源文件或目录,不能为{@code null}且必须存在 + * @param target 目标文件或目录 + * @param options 移动参数 + */ + public PathCopier(final Path src, final Path target, final CopyOption[] options) { + Assert.notNull(target, "Src path must be not null !"); + if (false == PathUtil.exists(src, false)) { + throw new IllegalArgumentException("Src path is not exist!"); + } + this.src = src; + this.target = Assert.notNull(target, "Target path must be not null !"); + this.options = ObjUtil.defaultIfNull(options, new CopyOption[]{}); + ; + } + + /** + * 复制src到target中 + *
    + *
  • src路径和target路径相同时,不执行操作
  • + *
  • src为文件,target为已存在目录,则拷贝到目录下,文件名不变。
  • + *
  • src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录),相当于拷贝后重命名,比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
  • + *
  • src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖,抛出{@link FileAlreadyExistsException}
  • + *
  • src为目录,target为已存在目录,整个src目录连同其目录拷贝到目标目录中
  • + *
  • src为目录,target为不存在路径,则自动创建目标为新目录,并只拷贝src内容到目标目录中,相当于重命名目录。
  • + *
  • src为目录,target为文件,抛出{@link IllegalArgumentException}
  • + *
+ * + * @return 目标Path + * @throws IORuntimeException IO异常 + */ + @Override + public Path copy() throws IORuntimeException { + if (PathUtil.isDirectory(src)) { + if (PathUtil.exists(target, false)) { + if (PathUtil.isDirectory(target)) { + return _copyContent(src, target.resolve(src.getFileName()), options); + } else { + // src目录,target文件,无法拷贝 + throw new IllegalArgumentException("Can not copy directory to a file!"); + } + } else { + // 目标不存在,按照重命名对待 + return _copyContent(src, target, options); + } + } + return copyFile(src, target, options); + } + + /** + * 复制src的内容到target中 + *
    + *
  • src路径和target路径相同时,不执行操作
  • + *
  • src为文件,target为已存在目录,则拷贝到目录下,文件名不变。
  • + *
  • src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录),相当于拷贝后重命名,比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
  • + *
  • src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖,抛出{@link FileAlreadyExistsException}
  • + *
  • src为目录,target为已存在目录,整个src目录下的内容拷贝到目标目录中
  • + *
  • src为目录,target为不存在路径,则自动创建目标为新目录,整个src目录下的内容拷贝到目标目录中,相当于重命名目录。
  • + *
  • src为目录,target为文件,抛出IO异常
  • + *
+ * + * @return 目标Path + * @throws IORuntimeException IO异常 + */ + public Path copyContent() throws IORuntimeException { + if (PathUtil.isDirectory(src, false)) { + return _copyContent(src, target, options); + } + return copyFile(src, target, options); + } + + /** + * 拷贝目录下的所有文件或目录到目标目录中,此方法不支持文件对文件的拷贝。 + *
    + *
  • 源文件为目录,目标也为目录或不存在,则拷贝目录下所有文件和目录到目标目录下
  • + *
  • 源文件为文件,目标为目录或不存在,则拷贝文件到目标目录下
  • + *
+ * + * @param src 源文件路径,如果为目录只在目标中创建新目录 + * @param target 目标目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return Path + * @throws IORuntimeException IO异常 + */ + private static Path _copyContent(final Path src, final Path target, final CopyOption... options) throws IORuntimeException { + try { + Files.walkFileTree(src, new CopyVisitor(src, target, options)); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + return target; + } + + /** + * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
+ * 此方法不支持递归拷贝目录,如果src传入是目录,只会在目标目录中创建空目录 + * + * @param src 源文件路径,如果为目录只在目标中创建新目录 + * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 + * @param options {@link StandardCopyOption} + * @return Path + * @throws IORuntimeException IO异常 + */ + private static Path copyFile(final Path src, final Path target, final CopyOption... options) throws IORuntimeException { + Assert.notNull(src, "Source File is null !"); + Assert.notNull(target, "Destination File or directory is null !"); + + final Path targetPath = PathUtil.isDirectory(target) ? target.resolve(src.getFileName()) : target; + // 创建级联父目录 + PathUtil.mkParentDirs(targetPath); + try { + return Files.copy(src, targetPath, options); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java index 4427b41dd..44de9c576 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.file.visitor.MoveVisitor; import cn.hutool.core.lang.Assert; @@ -117,21 +116,21 @@ public class PathMover { *
  • 如果src为文件,target为文件,则按照是否覆盖参数执行。
  • *
  • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
  • *
  • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
  • - *
  • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中。
  • - *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中。
  • + *
  • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中,源目录不删除。
  • + *
  • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中,源目录不删除。
  • * * * @return 目标文件Path */ public Path moveContent() { final Path src = this.src; - if (PathUtil.isNotDirectory(target, false)) { + if (PathUtil.isExistsAndNotDirectory(target, false)) { // 文件移动调用move方法 return move(); } final Path target = this.target; - if (PathUtil.isNotDirectory(target, false)) { + if (PathUtil.isExistsAndNotDirectory(target, false)) { // 目标不能为文件 throw new IllegalArgumentException("Can not move dir content to a file"); } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 8a476d37d..d1f6a65d8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -2,7 +2,6 @@ package cn.hutool.core.io.file; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; -import cn.hutool.core.io.file.visitor.CopyVisitor; import cn.hutool.core.io.file.visitor.DelVisitor; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.CharsetUtil; @@ -150,51 +149,15 @@ public class PathUtil { } /** - * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
    - * 此方法不支持递归拷贝目录,如果src传入是目录,只会在目标目录中创建空目录 - * - * @param src 源文件路径,如果为目录只在目标中创建新目录 - * @param dest 目标文件或目录,如果为目录使用与源文件相同的文件名 - * @param options {@link StandardCopyOption} - * @return Path - * @throws IORuntimeException IO异常 - */ - public static Path copyFile(final Path src, final Path dest, final StandardCopyOption... options) throws IORuntimeException { - return copyFile(src, dest, (CopyOption[]) options); - } - - /** - * 通过JDK7+的 {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
    - * 此方法不支持递归拷贝目录,如果src传入是目录,只会在目标目录中创建空目录 - * - * @param src 源文件路径,如果为目录只在目标中创建新目录 - * @param target 目标文件或目录,如果为目录使用与源文件相同的文件名 - * @param options {@link StandardCopyOption} - * @return Path - * @throws IORuntimeException IO异常 - * @since 5.4.1 - */ - public static Path copyFile(final Path src, final Path target, final CopyOption... options) throws IORuntimeException { - Assert.notNull(src, "Source File is null !"); - Assert.notNull(target, "Destination File or directory is null !"); - - final Path targetPath = isDirectory(target) ? target.resolve(src.getFileName()) : target; - // 创建级联父目录 - mkParentDirs(targetPath); - try { - return Files.copy(src, targetPath, options); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - } - - /** - * 拷贝文件或目录,拷贝规则为: - * + * 复制src到target中 *
      - *
    • 源文件为目录,目标也为目录或不存在,则拷贝整个目录到目标目录下
    • - *
    • 源文件为文件,目标为目录或不存在,则拷贝文件到目标目录下
    • - *
    • 源文件为文件,目标也为文件,则在{@link StandardCopyOption#REPLACE_EXISTING}情况下覆盖之
    • + *
    • src路径和target路径相同时,不执行操作
    • + *
    • src为文件,target为已存在目录,则拷贝到目录下,文件名不变。
    • + *
    • src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录),相当于拷贝后重命名,比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
    • + *
    • src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖,抛出{@link FileAlreadyExistsException}
    • + *
    • src为目录,target为已存在目录,整个src目录连同其目录拷贝到目标目录中
    • + *
    • src为目录,target为不存在路径,则自动创建目标为新目录,并只拷贝src内容到目标目录中,相当于重命名目录。
    • + *
    • src为目录,target为文件,抛出{@link IllegalArgumentException}
    • *
    * * @param src 源文件路径,如果为目录会在目标中创建新目录 @@ -202,23 +165,21 @@ public class PathUtil { * @param options {@link StandardCopyOption} * @return Path * @throws IORuntimeException IO异常 - * @since 5.5.1 */ public static Path copy(final Path src, final Path target, final CopyOption... options) throws IORuntimeException { - Assert.notNull(src, "Src path must be not null !"); - Assert.notNull(target, "Target path must be not null !"); - - if (isDirectory(src)) { - return copyContent(src, target.resolve(src.getFileName()), options); - } - return copyFile(src, target, options); + return PathCopier.of(src, target, options).copy(); } /** - * 拷贝目录下的所有文件或目录到目标目录中,此方法不支持文件对文件的拷贝。 + * 复制src的内容到target中 *
      - *
    • 源文件为目录,目标也为目录或不存在,则拷贝目录下所有文件和目录到目标目录下
    • - *
    • 源文件为文件,目标为目录或不存在,则拷贝文件到目标目录下
    • + *
    • src路径和target路径相同时,不执行操作
    • + *
    • src为文件,target为已存在目录,则拷贝到目录下,文件名不变。
    • + *
    • src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录),相当于拷贝后重命名,比如:/dest/aaa,如果aaa不存在,则aaa被当作文件名
    • + *
    • src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖,抛出{@link FileAlreadyExistsException}
    • + *
    • src为目录,target为已存在目录,整个src目录下的内容拷贝到目标目录中
    • + *
    • src为目录,target为不存在路径,则自动创建目标为新目录,整个src目录下的内容拷贝到目标目录中,相当于重命名目录。
    • + *
    • src为目录,target为文件,抛出IO异常
    • *
    * * @param src 源文件路径,如果为目录只在目标中创建新目录 @@ -226,18 +187,9 @@ public class PathUtil { * @param options {@link StandardCopyOption} * @return Path * @throws IORuntimeException IO异常 - * @since 5.5.1 */ public static Path copyContent(final Path src, final Path target, final CopyOption... options) throws IORuntimeException { - Assert.notNull(src, "Src path must be not null !"); - Assert.notNull(target, "Target path must be not null !"); - - try { - Files.walkFileTree(src, new CopyVisitor(src, target, options)); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - return target; + return PathCopier.of(src, target, options).copyContent(); } /** @@ -253,7 +205,7 @@ public class PathUtil { } /** - * 判断是否为非目录 + * 判断是否存在且为非目录 *
      *
    • 如果path为{@code null},返回{@code false}
    • *
    • 如果path不存在,返回{@code false}
    • @@ -264,7 +216,7 @@ public class PathUtil { * @return 如果为目录true * @since 3.1.0 */ - public static boolean isNotDirectory(final Path path, final boolean isFollowLinks) { + public static boolean isExistsAndNotDirectory(final Path path, final boolean isFollowLinks) { return exists(path, isFollowLinks) && false == isDirectory(path, isFollowLinks); } @@ -495,8 +447,8 @@ public class PathUtil { *
    • 如果src为文件,target为文件,则按照是否覆盖参数执行。
    • *
    • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
    • *
    • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
    • - *
    • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中。
    • - *
    • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中。
    • + *
    • 如果src为目录,target为目录,则将源目录下的内容移动到目标路径目录中,源目录不删除。
    • + *
    • 如果src为目录,target为不存在的路径,则创建目标路径为目录,将源目录下的内容移动到目标路径目录中,源目录不删除。
    • *
    * * @param src 源文件或目录路径 diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/copier/SrcToDestCopier.java b/hutool-core/src/main/java/cn/hutool/core/lang/copier/SrcToDestCopier.java index 030eb1494..ec143686f 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/copier/SrcToDestCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/copier/SrcToDestCopier.java @@ -19,7 +19,7 @@ public abstract class SrcToDestCopier> implem /** 源 */ protected T src; /** 目标 */ - protected T dest; + protected T target; /** 拷贝过滤器,可以过滤掉不需要拷贝的源 */ protected Predicate copyPredicate; @@ -48,18 +48,18 @@ public abstract class SrcToDestCopier> implem * * @return 目标 */ - public T getDest() { - return dest; + public T getTarget() { + return target; } /** * 设置目标 * - * @param dest 目标 + * @param target 目标 * @return this */ @SuppressWarnings("unchecked") - public C setDest(final T dest) { - this.dest = dest; + public C setTarget(final T target) { + this.target = target; return (C)this; } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileCopierTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileCopierTest.java deleted file mode 100644 index 32b734028..000000000 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileCopierTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.hutool.core.io; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import cn.hutool.core.io.file.FileCopier; - -import java.io.File; - -/** - * 文件拷贝单元测试 - * - * @author Looly - */ -public class FileCopierTest { - - @Test - @Ignore - public void dirCopyTest() { - final FileCopier copier = FileCopier.of("D:\\Java", "e:/eclipse/eclipse2.zip"); - copier.copy(); - } - - @Test - @Ignore - public void dirCopyTest2() { - //测试带.的文件夹复制 - final FileCopier copier = FileCopier.of("D:\\workspace\\java\\.metadata", "D:\\workspace\\java\\.metadata\\temp"); - copier.copy(); - - FileUtil.copy("D:\\workspace\\java\\looly\\hutool\\.git", "D:\\workspace\\java\\temp", true); - } - - @Test(expected = IORuntimeException.class) - public void dirCopySubTest() { - //测试父目录复制到子目录报错 - final FileCopier copier = FileCopier.of("D:\\workspace\\java\\.metadata", "D:\\workspace\\java\\.metadata\\temp"); - copier.copy(); - } - - @Test - @Ignore - public void copyFileToDirTest() { - final FileCopier copier = FileCopier.of("d:/GReen_Soft/XshellXftpPortable.zip", "c:/hp/"); - copier.copy(); - } - - @Test - @Ignore - public void copyFileByRelativePath(){ - // https://github.com/dromara/hutool/pull/2188 - // 当复制的目标文件位置是相对路径的时候可以通过 - final FileCopier copier = FileCopier.of(new File("pom.xml"),new File("aaa.txt")); - copier.copy(); - final boolean delete = new File("aaa.txt").delete(); - Assert.assertTrue(delete); - } -} diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index d0db01e8c..29d764e2c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -92,15 +92,6 @@ public class FileUtilTest { Assert.assertEquals(srcFile.length(), destFile.length()); } - @Test - @Ignore - public void copyFilesFromDirTest() { - final File srcFile = FileUtil.file("D:\\驱动"); - final File destFile = FileUtil.file("d:\\驱动备份"); - - FileUtil.copyFilesFromDir(srcFile, destFile, true); - } - @Test @Ignore public void copyDirTest() { diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java new file mode 100755 index 000000000..bd31ba3df --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java @@ -0,0 +1,79 @@ +package cn.hutool.core.io.file; + +import org.junit.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * 文件或目录拷贝测试 + */ +public class PathCopyTest { + + @Test + public void copySameFileTest() { + final Path path = Paths.get("d:/test/dir1/test1.txt"); + //src路径和target路径相同时,不执行操作 + PathUtil.copy( + path, + path); + } + + @Test + public void copySameDirTest() { + final Path path = Paths.get("d:/test/dir1"); + //src路径和target路径相同时,不执行操作 + PathUtil.copyContent( + path, + path); + } + + @Test + public void copyFileToDirTest() { + // src为文件,target为已存在目录,则拷贝到目录下,文件名不变。 + PathUtil.copy( + Paths.get("d:/test/dir1/test1.txt"), + Paths.get("d:/test/dir2")); + } + + @Test + public void copyFileToPathNotExistTest() { + // src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录) + // 相当于拷贝后重命名 + PathUtil.copy( + Paths.get("d:/test/dir1/test1.txt"), + Paths.get("d:/test/test2")); + } + + @Test + public void copyFileToFileTest() { + //src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖。 + PathUtil.copy( + Paths.get("d:/test/dir1/test1.txt"), + Paths.get("d:/test/test2")); + } + + @Test + public void copyDirToDirTest() { + //src为目录,target为已存在目录,整个src目录连同其目录拷贝到目标目录中 + PathUtil.copy( + Paths.get("d:/test/dir1/"), + Paths.get("d:/test/dir2")); + } + + @Test + public void copyDirToPathNotExistTest() { + //src为目录,target为不存在路径,则自动创建目标为新目录,整个src目录连同其目录拷贝到目标目录中 + PathUtil.copy( + Paths.get("d:/test/dir1/"), + Paths.get("d:/test/dir3")); + } + + @Test + public void copyDirToFileTest() { + //src为目录,target为文件,抛出IllegalArgumentException + PathUtil.copy( + Paths.get("d:/test/dir1/"), + Paths.get("d:/test/exist.txt")); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java index 1f960aa92..364d70051 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java @@ -13,7 +13,7 @@ public class PathUtilTest { @Test @Ignore public void copyFileTest(){ - PathUtil.copyFile( + PathUtil.copy( Paths.get("d:/test/1595232240113.jpg"), Paths.get("d:/test/1595232240113_copy.jpg"), StandardCopyOption.COPY_ATTRIBUTES, From 9eb982b7a62db673813b3c59a6705c1e61375866 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 21:08:51 +0800 Subject: [PATCH 074/125] fix code --- .../main/java/cn/hutool/core/io/FileUtil.java | 37 +++---------------- .../java/cn/hutool/core/io/file/PathUtil.java | 13 +++++++ 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 78073629d..4d56d4350 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -1,15 +1,10 @@ package cn.hutool.core.io; import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.file.FileCopier; -import cn.hutool.core.io.file.FileMode; -import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.file.FileReader; -import cn.hutool.core.io.file.FileReader.ReaderHandler; +import cn.hutool.core.io.file.*; import cn.hutool.core.io.file.FileWriter; -import cn.hutool.core.io.file.LineSeparator; -import cn.hutool.core.io.file.PathUtil; -import cn.hutool.core.io.file.Tailer; +import cn.hutool.core.io.file.FileReader.ReaderHandler; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.stream.BOMInputStream; import cn.hutool.core.io.unit.DataSizeUtil; @@ -20,37 +15,15 @@ import cn.hutool.core.reflect.ClassUtil; import cn.hutool.core.regex.ReUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.CharUtil; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.ObjUtil; -import cn.hutool.core.util.SystemUtil; +import cn.hutool.core.util.*; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileFilter; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.LineNumberReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.RandomAccessFile; -import java.io.Reader; +import java.io.*; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.file.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.Consumer; import java.util.jar.JarFile; import java.util.regex.Pattern; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index d1f6a65d8..5228ebbf1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -148,6 +148,19 @@ public class PathUtil { return true; } + /** + * 清空目录 + * + * @param path 目录路径 + */ + public static void clean(final Path path) { + try { + Files.walkFileTree(path, DelVisitor.INSTANCE); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + /** * 复制src到target中 *
      From 2ee6c0356a70369593cffa646c83a1a9b09812ca Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 5 Mar 2023 22:31:57 +0800 Subject: [PATCH 075/125] fix code --- .../java/cn/hutool/core/compress/ZipUtil.java | 5 +- .../java/cn/hutool/core/io/FileTypeUtil.java | 7 +- .../main/java/cn/hutool/core/io/FileUtil.java | 250 ++---------------- .../cn/hutool/core/io/file/PathDeleter.java | 104 ++++++++ .../cn/hutool/core/io/file/PathMover.java | 2 +- .../java/cn/hutool/core/io/file/PathUtil.java | 43 +-- .../core/io/file/visitor/DelVisitor.java | 2 + .../core/io/resource/ClassPathResource.java | 3 +- .../hutool/core/io/resource/UrlResource.java | 3 +- .../hutool/core/net/multipart/UploadFile.java | 3 +- .../java/cn/hutool/core/io/FileUtilTest.java | 47 ++-- .../cn/hutool/core/io/file/PathCopyTest.java | 9 + .../hutool/core/io/file/PathDeleterTest.java | 28 ++ .../java/cn/hutool/extra/ftp/AbstractFtp.java | 14 +- .../main/java/cn/hutool/extra/ftp/Ftp.java | 5 +- .../engine/httpclient5/HttpClient5Engine.java | 8 +- .../httpclient5/HttpClient5Response.java | 5 +- .../cn/hutool/http/webservice/SoapClient.java | 14 +- .../java/cn/hutool/json/Issue2749Test.java | 2 +- .../java/cn/hutool/poi/word/Word07Writer.java | 3 +- .../hutool/poi/excel/BigExcelWriteTest.java | 14 +- .../cn/hutool/poi/excel/ExcelWriteTest.java | 20 +- .../cn/hutool/poi/excel/Issue2307Test.java | 2 +- .../main/java/cn/hutool/setting/Setting.java | 1 + .../cn/hutool/setting/dialect/PropsUtil.java | 3 +- .../main/java/cn/hutool/swing/img/Img.java | 3 +- .../java/cn/hutool/swing/img/ImgUtil.java | 11 +- 27 files changed, 244 insertions(+), 367 deletions(-) create mode 100755 hutool-core/src/main/java/cn/hutool/core/io/file/PathDeleter.java create mode 100755 hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java b/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java index 1c77e9997..2461e57b6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.file.FileSystemUtil; import cn.hutool.core.io.file.PathUtil; import cn.hutool.core.io.resource.Resource; @@ -172,7 +173,7 @@ public class ZipUtil { * @throws UtilException IO异常 */ public static File zip(final File srcFile, final Charset charset) throws UtilException { - final File zipFile = FileUtil.file(srcFile.getParentFile(), FileUtil.mainName(srcFile) + ".zip"); + final File zipFile = FileUtil.file(srcFile.getParentFile(), FileNameUtil.mainName(srcFile) + ".zip"); zip(zipFile, charset, false, srcFile); return zipFile; } @@ -468,7 +469,7 @@ public class ZipUtil { * @since 3.2.2 */ public static File unzip(final File zipFile, final Charset charset) throws UtilException { - final File destDir = FileUtil.file(zipFile.getParentFile(), FileUtil.mainName(zipFile)); + final File destDir = FileUtil.file(zipFile.getParentFile(), FileNameUtil.mainName(zipFile)); return unzip(zipFile, destDir, charset); } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java index cb7d25f5b..1be5c63a8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java @@ -1,6 +1,7 @@ package cn.hutool.core.io; import cn.hutool.core.codec.HexUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.text.StrUtil; import java.io.File; @@ -139,10 +140,10 @@ public class FileTypeUtil { String typeName = getType(in,isExact); if (null == typeName) { // 未成功识别类型,扩展名辅助识别 - typeName = FileUtil.extName(filename); + typeName = FileNameUtil.extName(filename); } else if ("zip".equals(typeName)) { // zip可能为docx、xlsx、pptx、jar、war、ofd等格式,扩展名辅助判断 - final String extName = FileUtil.extName(filename); + final String extName = FileNameUtil.extName(filename); if ("docx".equalsIgnoreCase(extName)) { typeName = "docx"; } else if ("xlsx".equalsIgnoreCase(extName)) { @@ -160,7 +161,7 @@ public class FileTypeUtil { } } else if ("jar".equals(typeName)) { // wps编辑过的.xlsx文件与.jar的开头相同,通过扩展名判断 - final String extName = FileUtil.extName(filename); + final String extName = FileNameUtil.extName(filename); if ("xlsx".equalsIgnoreCase(extName)) { typeName = "xlsx"; } else if ("docx".equalsIgnoreCase(extName)) { diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 4d56d4350..28a890ff5 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -660,11 +660,10 @@ public class FileUtil extends PathUtil { * 某个文件删除失败会终止删除操作 * * @param fullFileOrDirPath 文件或者目录的路径 - * @return 成功与否 * @throws IORuntimeException IO异常 */ - public static boolean del(final String fullFileOrDirPath) throws IORuntimeException { - return del(file(fullFileOrDirPath)); + public static void del(final String fullFileOrDirPath) throws IORuntimeException { + del(file(fullFileOrDirPath)); } /** @@ -672,42 +671,13 @@ public class FileUtil extends PathUtil { * 注意:删除文件夹时不会判断文件夹是否为空,如果不空则递归删除子文件或文件夹
      * 某个文件删除失败会终止删除操作 * - *

      - * 从5.7.6开始,删除文件使用{@link Files#delete(Path)}代替 {@link File#delete()}
      - * 因为前者遇到文件被占用等原因时,抛出异常,而非返回false,异常会指明具体的失败原因。 - *

      - * * @param file 文件对象 - * @return 成功与否 * @throws IORuntimeException IO异常 * @see Files#delete(Path) */ - public static boolean del(final File file) throws IORuntimeException { - if (file == null || false == file.exists()) { - // 如果文件不存在或已被删除,此处返回true表示删除成功 - return true; - } - - if (file.isDirectory()) { - // 清空目录下所有文件和目录 - final boolean isOk = clean(file); - if (false == isOk) { - return false; - } - } - - // 删除文件或清空后的目录 - final Path path = file.toPath(); - try { - delFile(path); - } catch (final DirectoryNotEmptyException e) { - // 遍历清空目录没有成功,此时补充删除一次(可能存在部分软链) - del(path); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - - return true; + public static void del(final File file) throws IORuntimeException { + Assert.notNull(file, "File must be not null!"); + PathUtil.del(file.toPath()); } /** @@ -716,12 +686,10 @@ public class FileUtil extends PathUtil { * 某个文件删除失败会终止删除操作 * * @param dirPath 文件夹路径 - * @return 成功与否 * @throws IORuntimeException IO异常 - * @since 4.0.8 */ - public static boolean clean(final String dirPath) throws IORuntimeException { - return clean(file(dirPath)); + public static void clean(final String dirPath) throws IORuntimeException { + clean(file(dirPath)); } /** @@ -730,52 +698,11 @@ public class FileUtil extends PathUtil { * 某个文件删除失败会终止删除操作 * * @param directory 文件夹 - * @return 成功与否 * @throws IORuntimeException IO异常 - * @since 3.0.6 */ - public static boolean clean(final File directory) throws IORuntimeException { - if (directory == null || directory.exists() == false || false == directory.isDirectory()) { - return true; - } - - final File[] files = directory.listFiles(); - if (null != files) { - for (final File childFile : files) { - if (false == del(childFile)) { - // 删除一个出错则本次删除任务失败 - return false; - } - } - } - return true; - } - - /** - * 清理空文件夹
      - * 此方法用于递归删除空的文件夹,不删除文件
      - * 如果传入的文件夹本身就是空的,删除这个文件夹 - * - * @param directory 文件夹 - * @return 成功与否 - * @throws IORuntimeException IO异常 - * @since 4.5.5 - */ - public static boolean cleanEmpty(final File directory) throws IORuntimeException { - if (directory == null || false == directory.exists() || false == directory.isDirectory()) { - return true; - } - - final File[] files = directory.listFiles(); - if (ArrayUtil.isEmpty(files)) { - // 空文件夹则删除之 - return directory.delete(); - } - - for (final File childFile : files) { - cleanEmpty(childFile); - } - return true; + public static void clean(final File directory) throws IORuntimeException { + Assert.notNull(directory, "File must be not null!"); + PathUtil.clean(directory.toPath()); } /** @@ -978,7 +905,7 @@ public class FileUtil extends PathUtil { * * * @param src 源文件 - * @param target 目标文件或目录,目标不存在会自动创建(目录、文件都创建) + * @param target 目标文件或目录,目标不存在会自动创建(目录、文件都创建) * @param isOverride 是否覆盖目标文件 * @return 目标目录或文件 * @throws IORuntimeException IO异常 @@ -1013,9 +940,9 @@ public class FileUtil extends PathUtil { Assert.notNull(src, "Src file must be not null!"); Assert.notNull(target, "target file must be not null!"); return PathUtil.copyContent( - src.toPath(), - target.toPath(), - isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) + src.toPath(), + target.toPath(), + isOverride ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{}) .toFile(); } @@ -1086,7 +1013,7 @@ public class FileUtil extends PathUtil { */ public static File rename(final File file, String newName, final boolean isRetainExt, final boolean isOverride) { if (isRetainExt) { - final String extName = FileUtil.extName(file); + final String extName = FileNameUtil.extName(file); if (StrUtil.isNotBlank(extName)) { newName = newName.concat(".").concat(extName); } @@ -1518,129 +1445,6 @@ public class FileUtil extends PathUtil { return filePath; } - // -------------------------------------------------------------------------------------------- name start - - /** - * 返回文件名 - * - * @param file 文件 - * @return 文件名 - * @see FileNameUtil#getName(File) - * @since 4.1.13 - */ - public static String getName(final File file) { - return FileNameUtil.getName(file); - } - - /** - * 返回文件名
      - *
      -	 * "d:/test/aaa" 返回 "aaa"
      -	 * "/test/aaa.jpg" 返回 "aaa.jpg"
      -	 * 
      - * - * @param filePath 文件 - * @return 文件名 - * @see FileNameUtil#getName(String) - * @since 4.1.13 - */ - public static String getName(final String filePath) { - return FileNameUtil.getName(filePath); - } - - /** - * 获取文件后缀名,扩展名不带“.” - * - * @param file 文件 - * @return 扩展名 - * @see FileNameUtil#getSuffix(File) - * @since 5.3.8 - */ - public static String getSuffix(final File file) { - return FileNameUtil.getSuffix(file); - } - - /** - * 获得文件后缀名,扩展名不带“.” - * - * @param fileName 文件名 - * @return 扩展名 - * @see FileNameUtil#getSuffix(String) - * @since 5.3.8 - */ - public static String getSuffix(final String fileName) { - return FileNameUtil.getSuffix(fileName); - } - - /** - * 返回主文件名 - * - * @param file 文件 - * @return 主文件名 - * @see FileNameUtil#getPrefix(File) - * @since 5.3.8 - */ - public static String getPrefix(final File file) { - return FileNameUtil.getPrefix(file); - } - - /** - * 返回主文件名 - * - * @param fileName 完整文件名 - * @return 主文件名 - * @see FileNameUtil#getPrefix(String) - * @since 5.3.8 - */ - public static String getPrefix(final String fileName) { - return FileNameUtil.getPrefix(fileName); - } - - /** - * 返回主文件名 - * - * @param file 文件 - * @return 主文件名 - * @see FileNameUtil#mainName(File) - */ - public static String mainName(final File file) { - return FileNameUtil.mainName(file); - } - - /** - * 返回主文件名 - * - * @param fileName 完整文件名 - * @return 主文件名 - * @see FileNameUtil#mainName(String) - */ - public static String mainName(final String fileName) { - return FileNameUtil.mainName(fileName); - } - - /** - * 获取文件扩展名(后缀名),扩展名不带“.” - * - * @param file 文件 - * @return 扩展名 - * @see FileNameUtil#extName(File) - */ - public static String extName(final File file) { - return FileNameUtil.extName(file); - } - - /** - * 获得文件的扩展名(后缀名),扩展名不带“.” - * - * @param fileName 文件名 - * @return 扩展名 - * @see FileNameUtil#extName(String) - */ - public static String extName(final String fileName) { - return FileNameUtil.extName(fileName); - } - // -------------------------------------------------------------------------------------------- name end - /** * 判断文件路径是否有指定后缀,忽略大小写
      * 常用语判断扩展名 @@ -2918,30 +2722,6 @@ public class FileUtil extends PathUtil { return FileWriter.of(file, charset).writeLines(lines, lineSeparator, false); } - /** - * 清除文件名中的在Windows下不支持的非法字符,包括: \ / : * ? " < > | - * - * @param fileName 文件名(必须不包括路径,否则路径符将被替换) - * @return 清理后的文件名 - * @see FileNameUtil#cleanInvalid(String) - * @since 3.3.1 - */ - public static String cleanInvalid(final String fileName) { - return FileNameUtil.cleanInvalid(fileName); - } - - /** - * 文件名中是否包含在Windows下不支持的非法字符,包括: \ / : * ? " < > | - * - * @param fileName 文件名(必须不包括路径,否则路径符将被替换) - * @return 是否包含非法字符 - * @see FileNameUtil#containsInvalid(String) - * @since 3.3.1 - */ - public static boolean containsInvalid(final String fileName) { - return FileNameUtil.containsInvalid(fileName); - } - /** * 获取Web项目下的web root路径
      * 原理是首先获取ClassPath路径,由于在web项目中ClassPath位于 WEB-INF/classes/下,故向上获取两级目录即可。 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathDeleter.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathDeleter.java new file mode 100755 index 000000000..3b82b0ce1 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathDeleter.java @@ -0,0 +1,104 @@ +package cn.hutool.core.io.file; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.visitor.DelVisitor; +import cn.hutool.core.lang.Assert; + +import java.io.IOException; +import java.nio.file.*; +import java.util.stream.Stream; + +/** + * 文件删除封装 + * + * @author looly + * @since 6.0.0 + */ +public class PathDeleter { + + /** + * 创建文件或目录移动器 + * + * @param src 源文件或目录 + * @return {@code PathMover} + */ + public static PathDeleter of(final Path src) { + return new PathDeleter(src); + } + + private final Path path; + + /** + * 构造 + * + * @param path 文件或目录,不能为{@code null}且必须存在 + */ + public PathDeleter(final Path path) { + this.path = Assert.notNull(path, "Path must be not null !"); + } + + /** + * 删除文件或者文件夹,不追踪软链
      + * 注意:删除文件夹时不会判断文件夹是否为空,如果不空则递归删除子文件或文件夹
      + * 某个文件删除失败会终止删除操作 + * + * @throws IORuntimeException IO异常 + */ + public void del() throws IORuntimeException { + final Path path = this.path; + if (Files.notExists(path)) { + return; + } + + if (PathUtil.isDirectory(path)) { + _del(path); + } else { + delFile(path); + } + } + + /** + * 清空目录 + */ + public void clean() { + try (final Stream list = Files.list(this.path)){ + list.forEach(PathUtil::del); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 删除目录 + * + * @param path 目录路径 + */ + private static void _del(final Path path) { + try { + Files.walkFileTree(path, DelVisitor.INSTANCE); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 删除文件或空目录,不追踪软链 + * + * @param path 文件对象 + * @throws IORuntimeException IO异常 + * @since 5.7.7 + */ + private static void delFile(final Path path) throws IORuntimeException { + try { + Files.delete(path); + } catch (final IOException e) { + if (e instanceof AccessDeniedException) { + // 可能遇到只读文件,无法删除.使用 file 方法删除 + if (path.toFile().delete()) { + return; + } + } + throw new IORuntimeException(e); + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java index 44de9c576..1ac15cb23 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -67,7 +67,7 @@ public class PathMover { *
    • 如果src和target为同一文件或目录,直接返回target。
    • *
    • 如果src为文件,target为目录,则移动到目标目录下,存在同名文件则按照是否覆盖参数执行。
    • *
    • 如果src为文件,target为文件,则按照是否覆盖参数执行。
    • - *
    • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如moveContent("/a/b", "/c/d"), d不存在,则b变成d。
    • + *
    • 如果src为文件,target为不存在的路径,则重命名源文件到目标指定的文件,如move("/a/b", "/c/d"), d不存在,则b变成d。
    • *
    • 如果src为目录,target为文件,抛出{@link IllegalArgumentException}
    • *
    • 如果src为目录,target为目录,则将源目录及其内容移动到目标路径目录中,如move("/a/b", "/c/d"),结果为"/c/d/b"
    • *
    • 如果src为目录,target为不存在的路径,则重命名src到target,如move("/a/b", "/c/d"),结果为"/c/d/",相当于b重命名为d
    • diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java index 5228ebbf1..dcac7bcd9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathUtil.java @@ -2,7 +2,6 @@ package cn.hutool.core.io.file; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; -import cn.hutool.core.io.file.visitor.DelVisitor; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.CharsetUtil; @@ -127,25 +126,11 @@ public class PathUtil { * 某个文件删除失败会终止删除操作 * * @param path 文件对象 - * @return 成功与否 * @throws IORuntimeException IO异常 * @since 4.4.2 */ - public static boolean del(final Path path) throws IORuntimeException { - if (Files.notExists(path)) { - return true; - } - - try { - if (isDirectory(path)) { - Files.walkFileTree(path, DelVisitor.INSTANCE); - } else { - delFile(path); - } - } catch (final IOException e) { - throw new IORuntimeException(e); - } - return true; + public static void del(final Path path) throws IORuntimeException { + PathDeleter.of(path).del(); } /** @@ -154,11 +139,7 @@ public class PathUtil { * @param path 目录路径 */ public static void clean(final Path path) { - try { - Files.walkFileTree(path, DelVisitor.INSTANCE); - } catch (final IOException e) { - throw new RuntimeException(e); - } + PathDeleter.of(path).clean(); } /** @@ -617,22 +598,4 @@ public class PathUtil { } return path.getFileName().toString(); } - - /** - * 删除文件或空目录,不追踪软链 - * - * @param path 文件对象 - * @throws IOException IO异常 - * @since 5.7.7 - */ - protected static void delFile(final Path path) throws IOException { - try { - Files.delete(path); - } catch (final AccessDeniedException e) { - // 可能遇到只读文件,无法删除.使用 file 方法删除 - if (false == path.toFile().delete()) { - throw e; - } - } - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java index 09b456113..aee176854 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java @@ -1,5 +1,7 @@ package cn.hutool.core.io.file.visitor; +import cn.hutool.core.lang.Console; + import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java index deb7c2c99..d2553d510 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java @@ -2,6 +2,7 @@ package cn.hutool.core.io.resource; import cn.hutool.core.classloader.ClassLoaderUtil; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.text.StrUtil; @@ -67,7 +68,7 @@ public class ClassPathResource extends UrlResource { final String path = normalizePath(pathBaseClassLoader); this.path = path; - this.name = StrUtil.isBlank(path) ? null : FileUtil.getName(path); + this.name = StrUtil.isBlank(path) ? null : FileNameUtil.getName(path); this.classLoader = ObjUtil.defaultIfNull(classLoader, ClassLoaderUtil::getClassLoader); this.clazz = clazz; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java index d80e37958..c68159df7 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java @@ -1,6 +1,7 @@ package cn.hutool.core.io.resource; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.net.url.URLUtil; @@ -50,7 +51,7 @@ public class UrlResource implements Resource, Serializable{ if(null != url && URLUtil.URL_PROTOCOL_FILE.equals(url.getProtocol())){ this.lastModified = FileUtil.file(url).lastModified(); } - this.name = ObjUtil.defaultIfNull(name, () -> (null != url ? FileUtil.getName(url.getPath()) : null)); + this.name = ObjUtil.defaultIfNull(name, () -> (null != url ? FileNameUtil.getName(url.getPath()) : null)); } //-------------------------------------------------------------------------------------- Constructor end diff --git a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java index 97ffdc4d0..30f443e80 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java @@ -2,6 +2,7 @@ package cn.hutool.core.net.multipart; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.text.StrUtil; import java.io.BufferedOutputStream; @@ -247,7 +248,7 @@ public class UploadFile { return isAllow; } - final String fileNameExt = FileUtil.extName(this.getFileName()); + final String fileNameExt = FileNameUtil.extName(this.getFileName()); for (final String fileExtension : setting.fileExts) { if (fileNameExt.equalsIgnoreCase(fileExtension)) { return isAllow; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index 29d764e2c..0edc2f82d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -1,6 +1,7 @@ package cn.hutool.core.io; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.file.LineSeparator; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; @@ -53,22 +54,6 @@ public class FileUtilTest { FileUtil.touch("d:\\tea\\a.jpg"); } - @Test - @Ignore - public void delTest() { - // 删除一个不存在的文件,应返回true - final boolean result = FileUtil.del("e:/Hutool_test_3434543533409843.txt"); - Assert.assertTrue(result); - } - - @Test - @Ignore - public void delTest2() { - // 删除一个不存在的文件,应返回true - final boolean result = FileUtil.del(Paths.get("e:/Hutool_test_3434543533409843.txt")); - Assert.assertTrue(result); - } - @Test @Ignore public void renameTest() { @@ -317,61 +302,61 @@ public class FileUtilTest { @Test public void getNameTest() { String path = "d:\\aaa\\bbb\\cc\\ddd\\"; - String name = FileUtil.getName(path); + String name = FileNameUtil.getName(path); Assert.assertEquals("ddd", name); path = "d:\\aaa\\bbb\\cc\\ddd.jpg"; - name = FileUtil.getName(path); + name = FileNameUtil.getName(path); Assert.assertEquals("ddd.jpg", name); } @Test public void mainNameTest() { String path = "d:\\aaa\\bbb\\cc\\ddd\\"; - String mainName = FileUtil.mainName(path); + String mainName = FileNameUtil.mainName(path); Assert.assertEquals("ddd", mainName); path = "d:\\aaa\\bbb\\cc\\ddd"; - mainName = FileUtil.mainName(path); + mainName = FileNameUtil.mainName(path); Assert.assertEquals("ddd", mainName); path = "d:\\aaa\\bbb\\cc\\ddd.jpg"; - mainName = FileUtil.mainName(path); + mainName = FileNameUtil.mainName(path); Assert.assertEquals("ddd", mainName); } @Test public void extNameTest() { String path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\ddd\\" : "~/Desktop/hutool/ddd/"; - String mainName = FileUtil.extName(path); + String mainName = FileNameUtil.extName(path); Assert.assertEquals("", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\ddd" : "~/Desktop/hutool/ddd"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\ddd.jpg" : "~/Desktop/hutool/ddd.jpg"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("jpg", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\fff.xlsx" : "~/Desktop/hutool/fff.xlsx"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("xlsx", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\fff.tar.gz" : "~/Desktop/hutool/fff.tar.gz"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("tar.gz", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\fff.tar.Z" : "~/Desktop/hutool/fff.tar.Z"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("tar.Z", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\fff.tar.bz2" : "~/Desktop/hutool/fff.tar.bz2"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("tar.bz2", mainName); path = FileUtil.isWindows() ? "d:\\aaa\\bbb\\cc\\fff.tar.xz" : "~/Desktop/hutool/fff.tar.xz"; - mainName = FileUtil.extName(path); + mainName = FileNameUtil.extName(path); Assert.assertEquals("tar.xz", mainName); } @@ -445,10 +430,10 @@ public class FileUtilTest { Assert.assertTrue(nullDirTempFile.exists()); final File suffixDirTempFile = FileUtil.createTempFile(".xlsx",true); - Assert.assertEquals("xlsx", FileUtil.getSuffix(suffixDirTempFile)); + Assert.assertEquals("xlsx", FileNameUtil.getSuffix(suffixDirTempFile)); final File prefixDirTempFile = FileUtil.createTempFile("prefix",".xlsx",true); - Assert.assertTrue(FileUtil.getPrefix(prefixDirTempFile).startsWith("prefix")); + Assert.assertTrue(FileNameUtil.getPrefix(prefixDirTempFile).startsWith("prefix")); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java index bd31ba3df..cf14871f9 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathCopyTest.java @@ -1,5 +1,6 @@ package cn.hutool.core.io.file; +import org.junit.Ignore; import org.junit.Test; import java.nio.file.Path; @@ -11,6 +12,7 @@ import java.nio.file.Paths; public class PathCopyTest { @Test + @Ignore public void copySameFileTest() { final Path path = Paths.get("d:/test/dir1/test1.txt"); //src路径和target路径相同时,不执行操作 @@ -20,6 +22,7 @@ public class PathCopyTest { } @Test + @Ignore public void copySameDirTest() { final Path path = Paths.get("d:/test/dir1"); //src路径和target路径相同时,不执行操作 @@ -29,6 +32,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyFileToDirTest() { // src为文件,target为已存在目录,则拷贝到目录下,文件名不变。 PathUtil.copy( @@ -37,6 +41,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyFileToPathNotExistTest() { // src为文件,target为不存在路径,则目标以文件对待(自动创建父级目录) // 相当于拷贝后重命名 @@ -46,6 +51,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyFileToFileTest() { //src为文件,target是一个已存在的文件,则当{@link CopyOption}设为覆盖时会被覆盖,默认不覆盖。 PathUtil.copy( @@ -54,6 +60,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyDirToDirTest() { //src为目录,target为已存在目录,整个src目录连同其目录拷贝到目标目录中 PathUtil.copy( @@ -62,6 +69,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyDirToPathNotExistTest() { //src为目录,target为不存在路径,则自动创建目标为新目录,整个src目录连同其目录拷贝到目标目录中 PathUtil.copy( @@ -70,6 +78,7 @@ public class PathCopyTest { } @Test + @Ignore public void copyDirToFileTest() { //src为目录,target为文件,抛出IllegalArgumentException PathUtil.copy( diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java new file mode 100755 index 000000000..98eba2832 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java @@ -0,0 +1,28 @@ +package cn.hutool.core.io.file; + +import cn.hutool.core.io.FileUtil; +import org.junit.Ignore; +import org.junit.Test; + +import java.nio.file.Paths; + +public class PathDeleterTest { + @Test + @Ignore + public void delFileTest() { + FileUtil.touch("d:/test/exist.txt"); + PathUtil.del(Paths.get("d:/test/exist.txt")); + } + + @Test + @Ignore + public void delDirTest() { + PathUtil.del(Paths.get("d:/test/dir1")); + } + + @Test + @Ignore + public void cleanDirTest() { + PathUtil.clean(Paths.get("d:/test/dir1")); + } +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java index fbc08871a..8de423650 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java @@ -2,6 +2,7 @@ package cn.hutool.extra.ftp; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharsetUtil; @@ -19,6 +20,9 @@ import java.util.List; */ public abstract class AbstractFtp implements Closeable { + /** + * 默认编码 + */ public static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8; protected FtpConfig ftpConfig; @@ -113,7 +117,7 @@ public abstract class AbstractFtp implements Closeable { return false; } - final String fileName = FileUtil.getName(path); + final String fileName = FileNameUtil.getName(path); if (".".equals(fileName) || "..".equals(fileName)) { return false; } @@ -210,20 +214,20 @@ public abstract class AbstractFtp implements Closeable { * 来自:https://gitee.com/dromara/hutool/pulls/407
      * 此方法原理是先在目标文件同级目录下创建临时文件,下载之,等下载完毕后重命名,避免因下载错误导致的文件不完整。 * - * @param path 文件路径 - * @param outFile 输出文件或目录 + * @param path 文件路径 + * @param outFile 输出文件或目录 * @param tempFileSuffix 临时文件后缀,默认".temp" * @since 5.7.12 */ public void download(final String path, File outFile, String tempFileSuffix) { - if(StrUtil.isBlank(tempFileSuffix)){ + if (StrUtil.isBlank(tempFileSuffix)) { tempFileSuffix = ".temp"; } else { tempFileSuffix = StrUtil.addPrefixIfNot(tempFileSuffix, StrUtil.DOT); } // 目标文件真实名称 - final String fileName = outFile.isDirectory() ? FileUtil.getName(path) : outFile.getName(); + final String fileName = outFile.isDirectory() ? FileNameUtil.getName(path) : outFile.getName(); // 临时文件名称 final String tempFileName = fileName + tempFileSuffix; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 50623cc28..6092b475d 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -3,6 +3,7 @@ package cn.hutool.extra.ftp; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; @@ -440,7 +441,7 @@ public class Ftp extends AbstractFtp { @Override public boolean delFile(final String path) throws IORuntimeException { final String pwd = pwd(); - final String fileName = FileUtil.getName(path); + final String fileName = FileNameUtil.getName(path); final String dir = StrUtil.removeSuffix(path, fileName); if (false == cd(dir)) { throw new FtpException("Change dir to [{}] error, maybe dir not exist!", path); @@ -622,7 +623,7 @@ public class Ftp extends AbstractFtp { */ @Override public void download(final String path, final File outFile) { - final String fileName = FileUtil.getName(path); + final String fileName = FileNameUtil.getName(path); final String dir = StrUtil.removeSuffix(path, fileName); download(dir, fileName, outFile); } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index 8ca0babaa..bc3d3fef6 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -17,6 +17,7 @@ import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.message.BasicHeader; @@ -57,9 +58,9 @@ public class HttpClient5Engine implements ClientEngine { initEngine(); final ClassicHttpRequest request = buildRequest(message); - final CloseableHttpResponse response; + final ClassicHttpResponse response; try { - response = this.engine.execute(request); + response = this.engine.executeOpen(null, request, null); } catch (final IOException e) { throw new HttpException(e); } @@ -91,6 +92,7 @@ public class HttpClient5Engine implements ClientEngine { final int connectionTimeout = this.config.getConnectionTimeout(); if(connectionTimeout > 0){ + // TODO 细化替换 builder.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); builder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS); } @@ -103,8 +105,8 @@ public class HttpClient5Engine implements ClientEngine { } final HttpClientBuilder builder = HttpClients.custom() - // 设置默认头信息 .setDefaultRequestConfig(requestConfig) + // 设置默认头信息 .setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); // TODO 设置代理 diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Response.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Response.java index 02baef3d2..2723eb86c 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Response.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Response.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.http.HttpException; import cn.hutool.http.client.Response; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.io.entity.EntityUtils; @@ -30,7 +31,7 @@ public class HttpClient5Response implements Response { /** * HttpClient的响应对象 */ - private final CloseableHttpResponse rawRes; + private final ClassicHttpResponse rawRes; /** * 请求时的默认编码 */ @@ -43,7 +44,7 @@ public class HttpClient5Response implements Response { * @param rawRes {@link CloseableHttpResponse} * @param requestCharset 请求时的编码 */ - public HttpClient5Response(final CloseableHttpResponse rawRes, final Charset requestCharset) { + public HttpClient5Response(final ClassicHttpResponse rawRes, final Charset requestCharset) { this.rawRes = rawRes; this.requestCharset = requestCharset; } diff --git a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java index f403f8f61..f36433fdb 100644 --- a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java +++ b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java @@ -7,25 +7,13 @@ import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.XmlUtil; -import cn.hutool.http.HttpGlobalConfig; -import cn.hutool.http.HttpUtil; import cn.hutool.http.client.HeaderOperation; import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; -import cn.hutool.http.client.engine.ClientEngineFactory; -import cn.hutool.http.client.engine.jdk.HttpBase; -import cn.hutool.http.meta.Header; import javax.xml.XMLConstants; import javax.xml.namespace.QName; -import javax.xml.soap.MessageFactory; -import javax.xml.soap.MimeHeaders; -import javax.xml.soap.Name; -import javax.xml.soap.SOAPBodyElement; -import javax.xml.soap.SOAPElement; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPHeaderElement; -import javax.xml.soap.SOAPMessage; +import javax.xml.soap.*; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java index 98b9a9bfa..67b461cd4 100755 --- a/hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java +++ b/hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java @@ -14,13 +14,13 @@ import java.util.Map; */ public class Issue2749Test { + @SuppressWarnings("unchecked") @Test @Ignore public void jsonObjectTest() { final Map map = new HashMap<>(1, 1f); Map node = map; for (int i = 0; i < 1000; i++) { - //noinspection unchecked node = (Map) node.computeIfAbsent("a", k -> new HashMap(1, 1f)); } node.put("a", 1); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java index 75ed6f6db..473067d8a 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java @@ -3,6 +3,7 @@ package cn.hutool.poi.word; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.poi.exceptions.POIException; @@ -158,7 +159,7 @@ public class Word07Writer implements Closeable { */ public Word07Writer addPicture(final File picFile, final int width, final int height) { final String fileName = picFile.getName(); - final String extName = FileUtil.extName(fileName).toUpperCase(); + final String extName = FileNameUtil.extName(fileName).toUpperCase(); PicType picType; try { picType = PicType.valueOf(extName); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java index 03e4c59fa..0c8aa0700 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java @@ -52,7 +52,7 @@ public class BigExcelWriteTest { } final String filePath = "e:/bigWriteTest.xlsx"; - FileUtil.del(filePath); + FileUtil.del(FileUtil.file(filePath)); // 通过工具类创建writer final BigExcelWriter writer = ExcelUtil.getBigWriter(filePath); @@ -118,7 +118,7 @@ public class BigExcelWriteTest { // 通过工具类创建writer final String path = "e:/bigWriteMapTest.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final BigExcelWriter writer = ExcelUtil.getBigWriter(path); //设置内容字体 @@ -148,7 +148,7 @@ public class BigExcelWriteTest { // 通过工具类创建writer final String path = "e:/bigWriteMapTest2.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final BigExcelWriter writer = ExcelUtil.getBigWriter(path); // 一次性写出内容,使用默认样式 @@ -177,7 +177,7 @@ public class BigExcelWriteTest { final List rows = ListUtil.of(bean1, bean2); // 通过工具类创建writer final String file = "e:/bigWriteBeanTest.xlsx"; - FileUtil.del(file); + FileUtil.del(FileUtil.file(file)); final BigExcelWriter writer = ExcelUtil.getBigWriter(file); //自定义标题 writer.addHeaderAlias("name", "姓名"); @@ -197,7 +197,7 @@ public class BigExcelWriteTest { @Ignore public void writeCellValueTest() { final String path = "d:/test/cellValueTest.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final BigExcelWriter writer = new BigExcelWriter(path); writer.writeCellValue(3, 5, "aaa"); writer.close(); @@ -210,7 +210,7 @@ public class BigExcelWriteTest { final Map map2 = MapUtil.of("id", "123457"); final List data = Arrays.asList(map1, map2); final String destFilePath = "d:/test/closeTest.xlsx";//略 - FileUtil.del(destFilePath); + FileUtil.del(FileUtil.file(destFilePath)); try (final ExcelWriter writer = ExcelUtil.getBigWriter(destFilePath)) { writer.write(data).flush(); } @@ -221,7 +221,7 @@ public class BigExcelWriteTest { public void issue1210() { // 通过工具类创建writer final String path = "d:/test/issue1210.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final BigExcelWriter writer = ExcelUtil.getBigWriter(path); writer.addHeaderAlias("id", "SN"); writer.addHeaderAlias("userName", "User Name"); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java index 4be34f44b..930747589 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java @@ -147,7 +147,7 @@ public class ExcelWriteTest { } final String filePath = "d:/test/writeTest.xlsx"; - FileUtil.del(filePath); + FileUtil.del(FileUtil.file(filePath)); // 通过工具类创建writer final ExcelWriter writer = ExcelUtil.getWriter(filePath); // 通过构造方法创建writer @@ -294,7 +294,7 @@ public class ExcelWriteTest { // 通过工具类创建writer final String path = "f:/test/writeMapWithStyleTest.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final ExcelWriter writer = ExcelUtil.getWriter(path); writer.setStyleSet(null); @@ -328,7 +328,7 @@ public class ExcelWriteTest { final List> rows = ListUtil.of(row1, row2); // 通过工具类创建writer final String file = "d:/test/writeMapAlias.xlsx"; - FileUtil.del(file); + FileUtil.del(FileUtil.file(file)); final ExcelWriter writer = ExcelUtil.getWriter(file); // 自定义标题 writer.addHeaderAlias("name", "姓名"); @@ -363,7 +363,7 @@ public class ExcelWriteTest { final List> rows = ListUtil.of(row1, row2); // 通过工具类创建writer final String file = "f:/test/test_alias.xlsx"; - FileUtil.del(file); + FileUtil.del(FileUtil.file(file)); final ExcelWriter writer = ExcelUtil.getWriter(file); writer.setOnlyAlias(true); // 自定义标题 @@ -461,7 +461,7 @@ public class ExcelWriteTest { final List rows = ListUtil.of(bean1, bean2); // 通过工具类创建writer final String file = "e:/writeBeanTest.xlsx"; - FileUtil.del(file); + FileUtil.del(FileUtil.file(file)); final ExcelWriter writer = ExcelUtil.getWriter(file); // 自定义标题 writer.addHeaderAlias("name", "姓名"); @@ -493,7 +493,7 @@ public class ExcelWriteTest { final List rows = ListUtil.of(order1, order2); // 通过工具类创建writer final String file = "f:/test/writeBeanTest2.xlsx"; - FileUtil.del(file); + FileUtil.del(FileUtil.file(file)); final ExcelWriter writer = ExcelUtil.getWriter(file); // 自定义标题 writer.addHeaderAlias("id", "编号"); @@ -772,7 +772,7 @@ public class ExcelWriteTest { list.add(map2); //通过工具类创建writer - FileUtil.del("d:/test/writeTest2123.xlsx"); + FileUtil.del(FileUtil.file("d:/test/writeTest2123.xlsx")); final ExcelWriter writer = ExcelUtil.getWriter("d:/test/writeTest2123.xlsx"); writer.addHeaderAlias("xmnf", "项目年份");//1 @@ -790,7 +790,7 @@ public class ExcelWriteTest { //通过工具类创建writer final String path = "d:/test/mergeForDate.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final ExcelWriter writer = ExcelUtil.getWriter(path); writer.merge(0, 3, 0, 2, DateUtil.now(), false); writer.close(); @@ -813,7 +813,7 @@ public class ExcelWriteTest { public void writeFloatTest() { //issue https://gitee.com/dromara/hutool/issues/I43U9G final String path = "d:/test/floatTest.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final ExcelWriter writer = ExcelUtil.getWriter(path); writer.writeRow(ListUtil.view(22.9f)); @@ -825,7 +825,7 @@ public class ExcelWriteTest { public void writeDoubleTest() { // https://gitee.com/dromara/hutool/issues/I5PI5C final String path = "d:/test/doubleTest.xlsx"; - FileUtil.del(path); + FileUtil.del(FileUtil.file(path)); final ExcelWriter writer = ExcelUtil.getWriter(path); writer.disableDefaultStyle(); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java index 2d06a5e00..35c30d41e 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java @@ -16,7 +16,7 @@ public class Issue2307Test { @Ignore public void writeTest(){ final String filePath = "d:/test/issue2307.xlsx"; - FileUtil.del(filePath); + FileUtil.del(FileUtil.file(filePath)); final List row1 = ListUtil.of("设备1", 11, 111, 1111.444, 1111.444, 1111.444, 1111.444, 119999999999999999999999999999999999999999911.444); final List row2 = ListUtil.of("设备2", 22, 222, 2222.555, 2222.555, 2222.555, 2222.555, 2222.555); diff --git a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java index ec5161eb5..3aad945c7 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java @@ -591,6 +591,7 @@ public class Setting extends AbsSetting implements Map { * @param fields lambda,不能为空 * @return this */ + @SuppressWarnings("unchecked") public Setting setFields(final SerSupplier... fields) { Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get())); return this; diff --git a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java index 745842ecf..0c1c2f80d 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java @@ -1,6 +1,7 @@ package cn.hutool.setting.dialect; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.resource.NoResourceException; import cn.hutool.core.map.SafeConcurrentHashMap; import cn.hutool.core.text.StrUtil; @@ -30,7 +31,7 @@ public class PropsUtil { */ public static Props get(final String name) { return propsMap.computeIfAbsent(name, (filePath)->{ - final String extName = FileUtil.extName(filePath); + final String extName = FileNameUtil.extName(filePath); if (StrUtil.isEmpty(extName)) { filePath = filePath + "." + Props.EXT_NAME; } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java index 6520e75a6..6654f759d 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java @@ -3,6 +3,7 @@ package cn.hutool.swing.img; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.resource.Resource; import cn.hutool.core.lang.Assert; import cn.hutool.core.math.NumberUtil; @@ -724,7 +725,7 @@ public class Img implements Serializable { * @throws IORuntimeException IO异常 */ public boolean write(final File targetFile) throws IORuntimeException { - final String formatName = FileUtil.extName(targetFile); + final String formatName = FileNameUtil.extName(targetFile); if (StrUtil.isNotBlank(formatName)) { this.targetImageType = formatName; } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index 1ab5ab80b..e2b0ab457 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -4,6 +4,7 @@ import cn.hutool.core.codec.BaseN.Base64; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.resource.Resource; import cn.hutool.core.lang.Assert; import cn.hutool.core.math.NumberUtil; @@ -119,7 +120,7 @@ public class ImgUtil { * @since 3.2.2 */ public static void scale(final Image srcImg, final File destFile, final float scale) throws IORuntimeException { - Img.from(srcImg).setTargetImageType(FileUtil.extName(destFile)).scale(scale).write(destFile); + Img.from(srcImg).setTargetImageType(FileNameUtil.extName(destFile)).scale(scale).write(destFile); } /** @@ -189,7 +190,7 @@ public class ImgUtil { */ public static void scale(final File srcImageFile, final File destImageFile, final int width, final int height, final Color fixedColor) throws IORuntimeException { Img.from(srcImageFile)// - .setTargetImageType(FileUtil.extName(destImageFile))// + .setTargetImageType(FileNameUtil.extName(destImageFile))// .scale(width, height, fixedColor)// .write(destImageFile); } @@ -507,8 +508,8 @@ public class ImgUtil { Assert.notNull(destImageFile); Assert.isFalse(srcImageFile.equals(destImageFile), "Src file is equals to dest file!"); - final String srcExtName = FileUtil.extName(srcImageFile); - final String destExtName = FileUtil.extName(destImageFile); + final String srcExtName = FileNameUtil.extName(srcImageFile); + final String destExtName = FileNameUtil.extName(destImageFile); if (StrUtil.equalsIgnoreCase(srcExtName, destExtName)) { // 扩展名相同直接复制文件 FileUtil.copy(srcImageFile, destImageFile, true); @@ -1546,7 +1547,7 @@ public class ImgUtil { ImageOutputStream out = null; try { out = getImageOutputStream(targetFile); - write(image, FileUtil.extName(targetFile), out); + write(image, FileNameUtil.extName(targetFile), out); } finally { IoUtil.close(out); } From f7b59ac7443efabbe15a33bf6fc417f3302c3b27 Mon Sep 17 00:00:00 2001 From: huangxingming Date: Mon, 6 Mar 2023 23:16:40 +0800 Subject: [PATCH 076/125] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=98=AF=E5=90=A6=E6=9C=89=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/util/ArrayUtil.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 068e8ddda..a5f8b34fc 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -13,16 +13,7 @@ import cn.hutool.core.text.StrUtil; import java.lang.reflect.Array; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -2088,4 +2079,23 @@ public class ArrayUtil extends PrimitiveArrayUtil { return true; } + + /** + * 判断数组中是否有相同元素 + *

      若传入空数组,则返回{@code false}

      + * @param 数组元素类型 + * @param array 数组 + * @return 数组是否有相同元素 + * @since 6.0.0 + */ + public static Boolean hasSameElement(final T[] array) { + if (isEmpty(array)) { + return false; + } + Set elementSet = new HashSet<>(); + for (T element : array) { + elementSet.add(element); + } + return !(elementSet.size() == array.length); + } } From f79e1e31fbb73956a5efe7c451b5b640f83413d5 Mon Sep 17 00:00:00 2001 From: huangxingming Date: Mon, 6 Mar 2023 23:31:28 +0800 Subject: [PATCH 077/125] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=98=AF=E5=90=A6=E6=9C=89=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/util/ArrayUtilTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index d2223bbb2..4e0c9e6f3 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -673,4 +673,23 @@ public class ArrayUtilTest { Assert.assertTrue(ArrayUtil.isSorted(f, Integer::compareTo)); Assert.assertFalse(ArrayUtil.isSorted(f, null)); } + + @Test + public void hasSameElementTest() { + final Integer[] a = {1, 1}; + Assert.assertTrue(ArrayUtil.hasSameElement(a)); + + final String[] b = {"a", "b", "c"}; + Assert.assertFalse(ArrayUtil.hasSameElement(b)); + + final Object[] c = new Object[]{"1", "2", 2, 4D}; + Assert.assertFalse(ArrayUtil.hasSameElement(c)); + + final Object[] d = new Object[]{"1", "2", "2", 4D}; + Assert.assertTrue(ArrayUtil.hasSameElement(d)); + + final Object[] e = new Object[]{"1", 2, 2, 4D}; + Assert.assertTrue(ArrayUtil.hasSameElement(e)); + + } } From 94e6be4bf04c1b2f6fb7c0b4b79a11ff45571303 Mon Sep 17 00:00:00 2001 From: huangxingming Date: Tue, 7 Mar 2023 13:49:42 +0800 Subject: [PATCH 078/125] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dcomment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index a5f8b34fc..6b97fb320 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -2092,10 +2092,10 @@ public class ArrayUtil extends PrimitiveArrayUtil { if (isEmpty(array)) { return false; } - Set elementSet = new HashSet<>(); + Set elementSet = new HashSet<>(Arrays.asList(array)); for (T element : array) { elementSet.add(element); } - return !(elementSet.size() == array.length); + return elementSet.size() != array.length; } } From 00b064ba4686a07e8a189f027e7a0dff526d9851 Mon Sep 17 00:00:00 2001 From: huangxingming Date: Tue, 7 Mar 2023 13:50:41 +0800 Subject: [PATCH 079/125] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dcomment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 6b97fb320..adb152907 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -2093,9 +2093,6 @@ public class ArrayUtil extends PrimitiveArrayUtil { return false; } Set elementSet = new HashSet<>(Arrays.asList(array)); - for (T element : array) { - elementSet.add(element); - } return elementSet.size() != array.length; } } From ececce7c5285fa6f192bf5dd722227fd4a925cab Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 7 Mar 2023 16:12:48 +0800 Subject: [PATCH 080/125] fix code --- .../cn/hutool/core/collection/ListUtil.java | 4 +- .../core/io/watch/watchers/WatcherChain.java | 3 +- .../java/cn/hutool/core/util/ArrayUtil.java | 19 ++-- .../hutool/core/collection/CollUtilTest.java | 90 +++++++++---------- .../hutool/core/collection/IterUtilTest.java | 14 +-- .../collection/partition/PartitionTest.java | 2 +- .../java/cn/hutool/core/io/IoUtilTest.java | 3 +- .../cn/hutool/core/stream/StreamUtilTest.java | 7 +- .../cn/hutool/core/util/ArrayUtilTest.java | 7 +- .../java/cn/hutool/core/util/ReUtilTest.java | 2 +- .../main/java/cn/hutool/db/AbstractDb.java | 3 +- .../java/cn/hutool/setting/GroupedSet.java | 8 +- 12 files changed, 79 insertions(+), 83 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index c59a9dae7..d2cb0d700 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -34,7 +34,7 @@ import java.util.function.Predicate; public class ListUtil { /** - * 新建一个List
      + * 新建一个{@link ArrayList}
      * 如果提供的初始化数组为空,新建默认初始长度的List * * @param 集合元素类型 @@ -178,7 +178,7 @@ public class ListUtil { /** * 数组转为一个不可变List
      * 类似于Java9中的List.of
      - * 不同于Arrays.asList,此方法的原数组修改时,并不会影响List。 + * 不同于Arrays.asList,此方法不允许修改数组 * * @param ts 对象 * @param 对象类型 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java index f94024469..0e572b261 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java @@ -6,6 +6,7 @@ import cn.hutool.core.lang.Chain; import java.nio.file.Path; import java.nio.file.WatchEvent; +import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -35,7 +36,7 @@ public class WatcherChain implements Watcher, Chain{ * @param watchers 观察者列表 */ public WatcherChain(final Watcher... watchers) { - chain = ListUtil.of(watchers); + chain = Arrays.asList(watchers); } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index adb152907..c7a152e22 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -1,6 +1,7 @@ package cn.hutool.core.util; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.collection.SetUtil; import cn.hutool.core.collection.UniqueKeySet; import cn.hutool.core.collection.iter.IterUtil; import cn.hutool.core.comparator.CompareUtil; @@ -620,7 +621,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { * 包装 {@link System#arraycopy(Object, int, Object, int, int)}
      * 数组复制,源数组和目标数组都是从位置0开始复制
      * - * @param 目标数组类型 + * @param 目标数组类型 * @param src 源数组 * @param dest 目标数组 * @param length 拷贝数组长度 @@ -635,7 +636,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { * 包装 {@link System#arraycopy(Object, int, Object, int, int)}
      * 数组复制 * - * @param 目标数组类型 + * @param 目标数组类型 * @param src 源数组 * @param srcPos 源数组开始位置 * @param dest 目标数组 @@ -1956,8 +1957,8 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @param 数组元素类型,该类型需要实现Comparable接口 * @param array 数组 * @return 数组是否有序 - * @since 6.0.0 * @throws NullPointerException 如果数组元素含有null值 + * @since 6.0.0 */ public static > boolean isSorted(final T[] array) { if (isEmpty(array)) { @@ -1985,9 +1986,9 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @param 数组元素类型,该类型需要实现Comparable接口 * @param array 数组 * @return 数组是否升序 + * @throws NullPointerException 如果数组元素含有null值 * @author FengBaoheng * @since 5.5.2 - * @throws NullPointerException 如果数组元素含有null值 */ public static > boolean isSortedASC(final T[] array) { if (isEmpty(array)) { @@ -2011,9 +2012,9 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @param 数组元素类型,该类型需要实现Comparable接口 * @param array 数组 * @return 数组是否降序 + * @throws NullPointerException 如果数组元素含有null值 * @author FengBaoheng * @since 5.5.2 - * @throws NullPointerException 如果数组元素含有null值 */ public static > boolean isSortedDESC(final T[] array) { if (isEmpty(array)) { @@ -2083,8 +2084,9 @@ public class ArrayUtil extends PrimitiveArrayUtil { /** * 判断数组中是否有相同元素 *

      若传入空数组,则返回{@code false}

      - * @param 数组元素类型 - * @param array 数组 + * + * @param 数组元素类型 + * @param array 数组 * @return 数组是否有相同元素 * @since 6.0.0 */ @@ -2092,7 +2094,8 @@ public class ArrayUtil extends PrimitiveArrayUtil { if (isEmpty(array)) { return false; } - Set elementSet = new HashSet<>(Arrays.asList(array)); + + final Set elementSet = SetUtil.of(Arrays.asList(array)); return elementSet.size() != array.length; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index 546c25adf..fc5f4a2b4 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -57,7 +57,7 @@ public class CollUtilTest { @SuppressWarnings("ConstantConditions") @Test public void hasNullTest() { - ArrayList list = null; + List list = null; Assert.assertTrue(CollUtil.hasNull(list)); list = ListUtil.of(); @@ -72,7 +72,7 @@ public class CollUtilTest { @Test public void defaultIfEmpty() { - ArrayList strings = CollUtil.defaultIfEmpty(ListUtil.of(), ListUtil.of("1")); + List strings = CollUtil.defaultIfEmpty(ListUtil.of(), ListUtil.of("1")); Assert.assertEquals(ListUtil.of("1"), strings); strings = CollUtil.defaultIfEmpty(null, ListUtil.of("1")); @@ -81,22 +81,22 @@ public class CollUtilTest { @Test public void defaultIfEmpty2() { - final ArrayList strings = CollUtil.defaultIfEmpty(ListUtil.of(), Function.identity(), () -> ListUtil.of("1")); + final List strings = CollUtil.defaultIfEmpty(ListUtil.of(), Function.identity(), () -> ListUtil.of("1")); Assert.assertEquals(ListUtil.of("1"), strings); } @Test public void testPredicateContains() { - final ArrayList list = ListUtil.of("bbbbb", "aaaaa", "ccccc"); + final List list = ListUtil.of("bbbbb", "aaaaa", "ccccc"); Assert.assertTrue(CollUtil.contains(list, s -> s.startsWith("a"))); Assert.assertFalse(CollUtil.contains(list, s -> s.startsWith("d"))); } @Test public void testRemoveWithAddIf() { - ArrayList list = ListUtil.of(1, 2, 3); - final ArrayList exceptRemovedList = ListUtil.of(2, 3); - final ArrayList exceptResultList = ListUtil.of(1); + List list = ListUtil.of(1, 2, 3); + final List exceptRemovedList = ListUtil.of(2, 3); + final List exceptResultList = ListUtil.of(1); List resultList = CollUtil.removeWithAddIf(list, ele -> 1 == ele); Assert.assertEquals(list, exceptRemovedList); @@ -149,8 +149,8 @@ public class CollUtilTest { @Test public void unionTest() { - final ArrayList list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); - final ArrayList list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); + final List list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); + final List list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); final Collection union = CollUtil.union(list1, list2); @@ -159,8 +159,8 @@ public class CollUtilTest { @Test public void intersectionTest() { - final ArrayList list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); - final ArrayList list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); + final List list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); + final List list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); final Collection intersection = CollUtil.intersection(list1, list2); Assert.assertEquals(2, CollUtil.count(intersection, "b"::equals)); @@ -169,9 +169,9 @@ public class CollUtilTest { @Test public void intersectionDistinctTest() { - final ArrayList list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); - final ArrayList list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); - final ArrayList list3 = ListUtil.of(); + final List list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); + final List list2 = ListUtil.of("a", "b", "b", "b", "c", "d"); + final List list3 = ListUtil.of(); final Collection intersectionDistinct = CollUtil.intersectionDistinct(list1, list2); Assert.assertEquals(SetUtil.ofLinked("a", "b", "c", "d"), intersectionDistinct); @@ -183,8 +183,8 @@ public class CollUtilTest { @Test public void disjunctionTest() { - final ArrayList list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); - final ArrayList list2 = ListUtil.of("a", "b", "b", "b", "c", "d", "x2"); + final List list1 = ListUtil.of("a", "b", "b", "c", "d", "x"); + final List list2 = ListUtil.of("a", "b", "b", "b", "c", "d", "x2"); final Collection disjunction = CollUtil.disjunction(list1, list2); Assert.assertTrue(disjunction.contains("b")); @@ -200,8 +200,8 @@ public class CollUtilTest { @Test public void disjunctionTest2() { // 任意一个集合为空,差集为另一个集合 - final ArrayList list1 = ListUtil.of(); - final ArrayList list2 = ListUtil.of("a", "b", "b", "b", "c", "d", "x2"); + final List list1 = ListUtil.of(); + final List list2 = ListUtil.of("a", "b", "b", "b", "c", "d", "x2"); final Collection disjunction = CollUtil.disjunction(list1, list2); Assert.assertEquals(list2, disjunction); @@ -212,8 +212,8 @@ public class CollUtilTest { @Test public void disjunctionTest3() { // 无交集下返回共同的元素 - final ArrayList list1 = ListUtil.of("1", "2", "3"); - final ArrayList list2 = ListUtil.of("a", "b", "c"); + final List list1 = ListUtil.of("1", "2", "3"); + final List list2 = ListUtil.of("a", "b", "c"); final Collection disjunction = CollUtil.disjunction(list1, list2); Assert.assertTrue(disjunction.contains("1")); @@ -273,7 +273,7 @@ public class CollUtilTest { map2.put("c", "值3"); // ---------------------------------------------------------------------------------------- - final ArrayList> list = ListUtil.of(map1, map2); + final List> list = ListUtil.of(map1, map2); final Map> map = CollUtil.toListMap(list); Assert.assertEquals("值1", map.get("a").get(0)); Assert.assertEquals("值2", map.get("a").get(1)); @@ -288,7 +288,7 @@ public class CollUtilTest { public void getFieldValuesTest() { final Dict v1 = Dict.of().set("id", 12).set("name", "张三").set("age", 23); final Dict v2 = Dict.of().set("age", 13).set("id", 15).set("name", "李四"); - final ArrayList list = ListUtil.of(v1, v2); + final List list = ListUtil.of(v1, v2); final List fieldValues = (List) CollUtil.getFieldValues(list, "name"); @@ -298,7 +298,7 @@ public class CollUtilTest { @Test public void splitTest() { - final ArrayList list = ListUtil.of(1, 2, 3, 4, 5, 6, 7, 8, 9); + final List list = ListUtil.of(1, 2, 3, 4, 5, 6, 7, 8, 9); final List> split = CollUtil.split(list, 3); Assert.assertEquals(3, split.size()); Assert.assertEquals(3, split.get(0).size()); @@ -323,7 +323,7 @@ public class CollUtilTest { @Test public void editTest() { - final ArrayList list = ListUtil.of("a", "b", "c"); + final List list = ListUtil.of("a", "b", "c"); final Collection filtered = CollUtil.edit(list, t -> t + 1); @@ -332,9 +332,9 @@ public class CollUtilTest { @Test public void removeTest() { - final ArrayList list = ListUtil.of("a", "b", "c"); + final List list = ListUtil.of("a", "b", "c"); - final ArrayList filtered = CollUtil.remove(list, "a"::equals); + final List filtered = CollUtil.remove(list, "a"::equals); // 原地过滤 Assert.assertSame(list, filtered); @@ -351,10 +351,10 @@ public class CollUtilTest { @Test public void filterRemoveTest() { - final ArrayList list = ListUtil.of("a", "b", "c"); + final List list = ListUtil.of("a", "b", "c"); final List removed = new ArrayList<>(); - final ArrayList filtered = CollUtil.remove(list, t -> { + final List filtered = CollUtil.remove(list, t -> { if ("a".equals(t)) { removed.add(t); return true; @@ -372,9 +372,9 @@ public class CollUtilTest { @Test public void removeNullTest() { - final ArrayList list = ListUtil.of("a", "b", "c", null, "", " "); + final List list = ListUtil.of("a", "b", "c", null, "", " "); - final ArrayList filtered = CollUtil.removeNull(list); + final List filtered = CollUtil.removeNull(list); // 原地过滤 Assert.assertSame(list, filtered); @@ -383,9 +383,9 @@ public class CollUtilTest { @Test public void removeEmptyTest() { - final ArrayList list = ListUtil.of("a", "b", "c", null, "", " "); + final List list = ListUtil.of("a", "b", "c", null, "", " "); - final ArrayList filtered = CollUtil.removeEmpty(list); + final List filtered = CollUtil.removeEmpty(list); // 原地过滤 Assert.assertSame(list, filtered); @@ -394,9 +394,9 @@ public class CollUtilTest { @Test public void removeBlankTest() { - final ArrayList list = ListUtil.of("a", "b", "c", null, "", " "); + final List list = ListUtil.of("a", "b", "c", null, "", " "); - final ArrayList filtered = CollUtil.removeBlank(list); + final List filtered = CollUtil.removeBlank(list); // 原地过滤 Assert.assertSame(list, filtered); @@ -731,20 +731,20 @@ public class CollUtilTest { @Test public void containsAnyTest() { - final ArrayList list1 = ListUtil.of(1, 2, 3, 4, 5); - final ArrayList list2 = ListUtil.of(5, 3, 1, 9, 11); + final List list1 = ListUtil.of(1, 2, 3, 4, 5); + final List list2 = ListUtil.of(5, 3, 1, 9, 11); Assert.assertTrue(CollUtil.containsAny(list1, list2)); } @Test public void containsAllTest() { - final ArrayList list1 = ListUtil.of(1, 2, 3, 4, 5); - final ArrayList list2 = ListUtil.of(5, 3, 1); + final List list1 = ListUtil.of(1, 2, 3, 4, 5); + final List list2 = ListUtil.of(5, 3, 1); Assert.assertTrue(CollUtil.containsAll(list1, list2)); - final ArrayList list3 = ListUtil.of(1); - final ArrayList list4 = ListUtil.of(); + final List list3 = ListUtil.of(1); + final List list4 = ListUtil.of(); Assert.assertTrue(CollUtil.containsAll(list3, list4)); } @@ -799,7 +799,7 @@ public class CollUtilTest { @Test public void countMapTest() { - final ArrayList list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); + final List list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); final Map countMap = CollUtil.countMap(list); Assert.assertEquals(Integer.valueOf(2), countMap.get("a")); @@ -810,7 +810,7 @@ public class CollUtilTest { @Test public void indexOfTest() { - final ArrayList list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); + final List list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); final int i = CollUtil.indexOf(list, (str) -> str.charAt(0) == 'c'); Assert.assertEquals(2, i); } @@ -818,7 +818,7 @@ public class CollUtilTest { @Test public void lastIndexOfTest() { // List有优化 - final ArrayList list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); + final List list = ListUtil.of("a", "b", "c", "c", "a", "b", "d"); final int i = CollUtil.lastIndexOf(list, (str) -> str.charAt(0) == 'a'); Assert.assertEquals(4, i); @@ -907,7 +907,7 @@ public class CollUtilTest { @Test public void distinctTest() { - final ArrayList distinct = CollUtil.distinct(ListUtil.view(5, 3, 10, 9, 0, 5, 10, 9)); + final List distinct = CollUtil.distinct(ListUtil.view(5, 3, 10, 9, 0, 5, 10, 9)); Assert.assertEquals(ListUtil.view(5, 3, 10, 9, 0), distinct); } @@ -946,7 +946,7 @@ public class CollUtilTest { @Test public void mapTest() { - final ArrayList list = ListUtil.of("a", "b", "c"); + final List list = ListUtil.of("a", "b", "c"); final List extract = CollUtil.map(list, (e) -> e + "_1"); Assert.assertEquals(ListUtil.of("a_1", "b_1", "c_1"), extract); } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java index 52b59ab41..8dd8414e6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java @@ -24,13 +24,13 @@ public class IterUtilTest { @Test public void getFirstNonNullTest() { - final ArrayList strings = ListUtil.of(null, null, "123", "456", null); + final List strings = ListUtil.of(null, null, "123", "456", null); Assert.assertEquals("123", CollUtil.getFirstNoneNull(strings)); } @Test public void fieldValueMapTest() { - final ArrayList carList = ListUtil.of(new Car("123", "大众"), new Car("345", "奔驰"), new Car("567", "路虎")); + final List carList = ListUtil.of(new Car("123", "大众"), new Car("345", "奔驰"), new Car("567", "路虎")); final Map carNameMap = IterUtil.fieldValueMap(carList.iterator(), "carNumber"); Assert.assertEquals("大众", carNameMap.get("123").getCarName()); @@ -40,30 +40,30 @@ public class IterUtilTest { @Test public void joinTest() { - final ArrayList list = ListUtil.of("1", "2", "3", "4"); + final List list = ListUtil.of("1", "2", "3", "4"); final String join = IterUtil.join(list.iterator(), ":"); Assert.assertEquals("1:2:3:4", join); - final ArrayList list1 = ListUtil.of(1, 2, 3, 4); + final List list1 = ListUtil.of(1, 2, 3, 4); final String join1 = IterUtil.join(list1.iterator(), ":"); Assert.assertEquals("1:2:3:4", join1); // 包装每个节点 - final ArrayList list2 = ListUtil.of("1", "2", "3", "4"); + final List list2 = ListUtil.of("1", "2", "3", "4"); final String join2 = IterUtil.join(list2.iterator(), ":", "\"", "\""); Assert.assertEquals("\"1\":\"2\":\"3\":\"4\"", join2); } @Test public void joinWithFuncTest() { - final ArrayList list = ListUtil.of("1", "2", "3", "4"); + final List list = ListUtil.of("1", "2", "3", "4"); final String join = IterUtil.join(list.iterator(), ":", String::valueOf); Assert.assertEquals("1:2:3:4", join); } @Test public void joinWithNullTest() { - final ArrayList list = ListUtil.of("1", null, "3", "4"); + final List list = ListUtil.of("1", null, "3", "4"); final String join = IterUtil.join(list.iterator(), ":", String::valueOf); Assert.assertEquals("1:null:3:4", join); } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java index df5072bc5..e3dbf228a 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java @@ -11,7 +11,7 @@ import java.util.List; public class PartitionTest { @Test public void sizeTest() { - final ArrayList list = ListUtil.of(1, 2, 3, 4, 5); + final List list = ListUtil.of(1, 2, 3, 4, 5); final Partition partition = new Partition<>(list, 4); Assert.assertEquals(2, partition.size()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java index dee7b2806..dd9ece7f6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java @@ -22,6 +22,7 @@ import java.io.PushbackReader; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; +import java.util.List; public class IoUtilTest { @@ -50,7 +51,7 @@ public class IoUtilTest { @Test public void readUtf8LinesTest() { - final ArrayList strings = IoUtil.readUtf8Lines(ResourceUtil.getStream("text.txt"), ListUtil.of()); + final List strings = IoUtil.readUtf8Lines(ResourceUtil.getStream("text.txt"), ListUtil.of()); Assert.assertEquals(3, strings.size()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/StreamUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/StreamUtilTest.java index 153081c59..41c352989 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/StreamUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/StreamUtilTest.java @@ -5,10 +5,7 @@ import cn.hutool.core.collection.SetUtil; import org.junit.Assert; import org.junit.Test; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -40,7 +37,7 @@ public class StreamUtilTest { @Test public void streamTestOrdinaryIterator() { - final ArrayList arrayList = ListUtil.of(1, 2, 3); + final List arrayList = ListUtil.of(1, 2, 3); Assert.assertArrayEquals(new Integer[]{1, 2, 3}, StreamUtil.ofIter(arrayList.iterator()).toArray()); final HashSet hashSet = SetUtil.of(1, 2, 3); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 4e0c9e6f3..5bad7fd2b 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -5,10 +5,7 @@ import org.junit.Assert; import org.junit.Test; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * {@link ArrayUtil} 数组工具单元测试 @@ -305,7 +302,7 @@ public class ArrayUtilTest { @Test public void toArrayTest() { - final ArrayList list = ListUtil.of("A", "B", "C", "D"); + final List list = ListUtil.of("A", "B", "C", "D"); final String[] array = ArrayUtil.toArray(list, String.class); Assert.assertEquals("A", array[0]); Assert.assertEquals("B", array[1]); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java index 1635d2ad2..0a2e43a72 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ReUtilTest.java @@ -85,7 +85,7 @@ public class ReUtilTest { public void findAllTest() { // 查找所有匹配文本 final List resultFindAll = ReUtil.findAll("\\w{2}", content, 0, new ArrayList<>()); - final ArrayList expected = ListUtil.of("ZZ", "Za", "aa", "bb", "bc", "cc", "12", "34"); + final List expected = ListUtil.of("ZZ", "Za", "aa", "bb", "bc", "cc", "12", "34"); Assert.assertEquals(expected, resultFindAll); } diff --git a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java index e06c206c8..87056c748 100755 --- a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java +++ b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java @@ -24,6 +24,7 @@ import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -555,7 +556,7 @@ public abstract class AbstractDb> extends DefaultConnect * @throws DbRuntimeException SQL执行异常 */ public T find(final Entity where, final RsHandler rsh, final String... fields) throws DbRuntimeException { - return find(ListUtil.of(fields), where, rsh); + return find(Arrays.asList(fields), where, rsh); } /** diff --git a/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java b/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java index 40d595e2a..011b54d43 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java @@ -14,11 +14,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.charset.Charset; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * 分组化的Set集合类
      @@ -279,7 +275,7 @@ public class GroupedSet extends HashMap> { public boolean contains(final String group, final String value, final String... otherValues) { if (ArrayUtil.isNotEmpty(otherValues)) { // 需要测试多个值的情况 - final List valueList = ListUtil.of(otherValues); + final List valueList = Arrays.asList(otherValues); valueList.add(value); return contains(group, valueList); } else { From c8f71a4bd25de204263fdb6f8d0532eb2ebd8f89 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 7 Mar 2023 18:25:14 +0800 Subject: [PATCH 081/125] fix doc --- hutool-core/src/main/java/cn/hutool/core/lang/Opt.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java index 66a46269b..acc77e781 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java @@ -237,8 +237,8 @@ public class Opt { * 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt} * * @param predicate 给定的条件 - * @return 如果满足条件则返回本身, 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt} - * @throws NullPointerException 如果给定的条件为 {@code null},抛出{@code NPE} + * @return 如果满足条件则返回本身, 不满足条件或者元素本身为空时返回一个空的{@code Opt} + * @throws NullPointerException 如果给定的条件为 {@code null}抛出{@code NPE} */ public Opt filter(final Predicate predicate) { Objects.requireNonNull(predicate); From b67464e6c1f2c5e507dda3b90c9a8f62998d1739 Mon Sep 17 00:00:00 2001 From: liupeng Date: Tue, 7 Mar 2023 18:29:26 +0800 Subject: [PATCH 082/125] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E5=BC=8F=E7=9A=84=E6=97=A5=E6=9C=9F=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/date/TimeUtil.java | 38 +++++++++++-------- .../cn/hutool/core/date/TimeUtilTest.java | 24 ++++++++++++ 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java index fbc0a95c0..19b729ada 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java @@ -4,27 +4,14 @@ import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; -import java.time.DayOfWeek; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.*; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoField; -import java.time.temporal.ChronoUnit; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdjusters; -import java.time.temporal.TemporalUnit; -import java.time.temporal.WeekFields; +import java.time.temporal.*; import java.util.Date; import java.util.TimeZone; +import java.util.function.Function; /** * JDK8+中的{@link java.time} 工具类封装 @@ -355,6 +342,25 @@ public class TimeUtil extends TemporalAccessorUtil { return format(date, DatePattern.NORM_DATE_FORMATTER); } + + /** + * 格式化时间函数 + * + * @return 格式化时间的函数 + */ + public static Function formatTimeFunction(DateTimeFormatter dateTimeFormatter) { + return time -> format(time, dateTimeFormatter); + } + + /** + * 格式化日期函数 + * + * @return 格式化时间的函数 + */ + public static Function formatDateFunction(DateTimeFormatter dateTimeFormatter) { + return date -> format(date, dateTimeFormatter); + } + /** * 日期偏移,根据field不同加不同值(偏移会修改传入的对象) * diff --git a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java index dcb304acc..7a825c4de 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java @@ -10,7 +10,10 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; +import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class TimeUtilTest { @@ -319,4 +322,25 @@ public class TimeUtilTest { Assert.assertThrows(IllegalArgumentException.class, () -> TimeUtil.isIn(begin, null, end, false, false)); Assert.assertThrows(IllegalArgumentException.class, () -> TimeUtil.isIn(begin, begin, null, false, false)); } + + + @Test + public void formatDateFunctionTest() { + List dateStrList = Stream.of("2023-03-01", "2023-03-02") + .map(LocalDate::parse) + .map(TimeUtil.formatDateFunction(DatePattern.CHINESE_DATE_FORMATTER)) + .collect(Collectors.toList()); + Assert.assertEquals("2023年03月01日", dateStrList.get(0)); + Assert.assertEquals("2023年03月02日", dateStrList.get(1)); + } + + @Test + public void formatTimeFunctionTest() { + List dateStrList = Stream.of("2023-03-01T12:23:56", "2023-03-02T12:23:56") + .map(LocalDateTime::parse) + .map(TimeUtil.formatTimeFunction(DatePattern.CHINESE_DATE_FORMATTER)) + .collect(Collectors.toList()); + Assert.assertEquals("2023年03月01日", dateStrList.get(0)); + Assert.assertEquals("2023年03月02日", dateStrList.get(1)); + } } From 5ac1c818126d4440d42ddd6f93a0e681f902bb0b Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 8 Mar 2023 23:10:05 +0800 Subject: [PATCH 083/125] add test --- .../cn/hutool/core/lang/func/LambdaUtilTest.java | 13 +++++++++++++ .../test/java/cn/hutool/json/jwt/JWTTest.java | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java index c525fad3f..1014d9780 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaUtilTest.java @@ -282,4 +282,17 @@ public class LambdaUtilTest { REF_invokeSpecial, REF_newInvokeSpecial, } + + @Test + public void lambdaClassNameTest() { + final String lambdaClassName1 = LambdaUtilTestHelper.getLambdaClassName(MyTeacher::getAge); + final String lambdaClassName2 = LambdaUtilTestHelper.getLambdaClassName(MyTeacher::getAge); + Assert.assertNotEquals(lambdaClassName1, lambdaClassName2); + } + + static class LambdaUtilTestHelper { + public static

      String getLambdaClassName(final Function func) { + return func.getClass().getName(); + } + } } diff --git a/hutool-json/src/test/java/cn/hutool/json/jwt/JWTTest.java b/hutool-json/src/test/java/cn/hutool/json/jwt/JWTTest.java index 0d2808651..6028bdd72 100755 --- a/hutool-json/src/test/java/cn/hutool/json/jwt/JWTTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/jwt/JWTTest.java @@ -172,4 +172,20 @@ public class JWTTest { final Object test2 = JWT.of(sign).getPayload().getClaim("test2"); Assert.assertEquals(Long.class, test2.getClass()); } + + @Test + public void getLongTest(){ + final String rightToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" + + ".eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJhZG1pbiIsImRldmljZSI6ImRlZmF1bHQtZGV2aWNlIiwiZWZmIjoxNjc4Mjg1NzEzOTM1LCJyblN0ciI6IkVuMTczWFhvWUNaaVZUWFNGOTNsN1pabGtOalNTd0pmIn0" + + ".wRe2soTaWYPhwcjxdzesDi1BgEm9D61K-mMT3fPc4YM" + + ""; + + final JWT jwt = JWTUtil.parseToken(rightToken); + + Assert.assertEquals( + "{\"loginType\":\"login\",\"loginId\":\"admin\",\"device\":\"default-device\"," + + "\"eff\":1678285713935,\"rnStr\":\"En173XXoYCZiVTXSF93l7ZZlkNjSSwJf\"}", + jwt.getPayloads().toString()); + Assert.assertEquals(Long.valueOf(1678285713935L), jwt.getPayloads().getLong("eff")); + } } From e215f22292c06f4a2ed34a444e0439a4917a7a42 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 8 Mar 2023 23:36:21 +0800 Subject: [PATCH 084/125] fix code --- .../java/cn/hutool/core/date/TimeUtil.java | 15 +--- .../cn/hutool/core/lang/func/LambdaUtil.java | 80 ++++++++++++++----- .../hutool/core/lang/func/PredicateUtil.java | 7 ++ .../core/lang/func/SerBinaryOperator.java | 8 +- .../cn/hutool/core/lang/func/SerConsumer.java | 2 +- .../hutool/core/lang/func/SerConsumer3.java | 8 +- .../cn/hutool/core/date/TimeUtilTest.java | 8 +- 7 files changed, 85 insertions(+), 43 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java index 19b729ada..b045f2838 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java @@ -1,6 +1,7 @@ package cn.hutool.core.date; import cn.hutool.core.date.format.GlobalCustomFormat; +import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; @@ -346,19 +347,11 @@ public class TimeUtil extends TemporalAccessorUtil { /** * 格式化时间函数 * + * @param dateTimeFormatter {@link DateTimeFormatter} * @return 格式化时间的函数 */ - public static Function formatTimeFunction(DateTimeFormatter dateTimeFormatter) { - return time -> format(time, dateTimeFormatter); - } - - /** - * 格式化日期函数 - * - * @return 格式化时间的函数 - */ - public static Function formatDateFunction(DateTimeFormatter dateTimeFormatter) { - return date -> format(date, dateTimeFormatter); + public static Function formatFunc(final DateTimeFormatter dateTimeFormatter) { + return LambdaUtil.toFunction(TimeUtil::format, dateTimeFormatter); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java index 43bb2733b..19ccd47d2 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java @@ -13,8 +13,7 @@ import java.lang.invoke.SerializedLambda; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.function.BiConsumer; -import java.util.function.Function; +import java.util.function.*; /** * Lambda相关工具类 @@ -34,12 +33,12 @@ public class LambdaUtil { * MyTeacher myTeacher = new MyTeacher(); * Class supplierClass = LambdaUtil.getRealClass(myTeacher::getAge); * Assert.assertEquals(MyTeacher.class, supplierClass); - * } + * } * *

    • 引用静态无参方法:
      {@code
       	 * 			Class staticSupplierClass = LambdaUtil.getRealClass(MyTeacher::takeAge);
       	 * 			Assert.assertEquals(MyTeacher.class, staticSupplierClass);
      -	 * 			}
      + * } *
    • * * 在以下场景无法获取到正确类型 @@ -123,7 +122,7 @@ public class LambdaUtil { * * * @param func 函数 - * @param lambda的类型 + * @param lambda的类型 * @return 方法名称 * @throws IllegalArgumentException 非Getter或Setter方法 * @since 5.7.23 @@ -136,8 +135,8 @@ public class LambdaUtil { * 等效于 Obj::getXxx * * @param getMethod getter方法 - * @param 调用getter方法对象类型 - * @param getter方法返回值类型 + * @param 调用getter方法对象类型 + * @param getter方法返回值类型 * @return Obj::getXxx */ @SuppressWarnings("unchecked") @@ -148,10 +147,10 @@ public class LambdaUtil { /** * 等效于 Obj::getXxx * - * @param clazz 调用getter方法对象类 + * @param clazz 调用getter方法对象类 * @param fieldName 字段名称 - * @param 调用getter方法对象类型 - * @param getter方法返回值类型 + * @param 调用getter方法对象类型 + * @param getter方法返回值类型 * @return Obj::getXxx */ @SuppressWarnings("unchecked") @@ -163,8 +162,8 @@ public class LambdaUtil { * 等效于 Obj::setXxx * * @param setMethod setter方法 - * @param 调用setter方法对象类型 - * @param

      setter方法返回的值类型 + * @param 调用setter方法对象类型 + * @param

      setter方法返回的值类型 * @return Obj::setXxx */ @SuppressWarnings("unchecked") @@ -175,10 +174,10 @@ public class LambdaUtil { /** * Obj::setXxx * - * @param clazz 调用setter方法对象类 + * @param clazz 调用setter方法对象类 * @param fieldName 字段名称 - * @param 调用setter方法对象类型 - * @param

      setter方法返回的值类型 + * @param 调用setter方法对象类型 + * @param

      setter方法返回的值类型 * @return Obj::setXxx */ @SuppressWarnings("unchecked") @@ -189,17 +188,60 @@ public class LambdaUtil { /** * 等效于 Obj::method * - * @param lambdaType 接受lambda的函数式接口类型 - * @param clazz 调用类 - * @param methodName 方法名 + * @param lambdaType 接受lambda的函数式接口类型 + * @param clazz 调用类 + * @param methodName 方法名 * @param paramsTypes 方法参数类型数组 - * @param 函数式接口类型 + * @param 函数式接口类型 * @return Obj::method */ public static F build(final Class lambdaType, final Class clazz, final String methodName, final Class... paramsTypes) { return LambdaFactory.build(lambdaType, clazz, methodName, paramsTypes); } + /** + * 通过自定义固定参数,将{@link BiFunction}转换为{@link Function} + * + * @param biFunction {@link BiFunction} + * @param param 参数 + * @param 参数类型 + * @param 参数2类型 + * @param 返回值类型 + * @return {@link Function} + * @since 6.0.0 + */ + public static Function toFunction(final BiFunction biFunction, final U param) { + return (t) -> biFunction.apply(t, param); + } + + /** + * 通过自定义固定参数,将{@link BiPredicate}转换为{@link Predicate} + * + * @param biPredicate {@link BiFunction} + * @param param 参数 + * @param 参数类型 + * @param 参数2类型 + * @return {@link Predicate} + * @since 6.0.0 + */ + public static Predicate toPredicate(final BiPredicate biPredicate, final U param) { + return (t) -> biPredicate.test(t, param); + } + + /** + * 通过自定义固定参数,将{@link BiConsumer}转换为{@link Consumer} + * + * @param biConsumer {@link BiConsumer} + * @param param 参数 + * @param 参数类型 + * @param 参数2类型 + * @return {@link Consumer} + * @since 6.0.0 + */ + public static Consumer toPredicate(final BiConsumer biConsumer, final U param) { + return (t) -> biConsumer.accept(t, param); + } + //region Private methods /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/PredicateUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/PredicateUtil.java index 580150885..153ddf980 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/PredicateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/PredicateUtil.java @@ -12,6 +12,13 @@ import java.util.function.Predicate; */ public class PredicateUtil { + /** + * 反向条件 + * + * @param predicate 条件 + * @param 参数类型 + * @return 反向条件 {@link Predicate} + */ public static Predicate negate(final Predicate predicate) { return predicate.negate(); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java index 50d1f6d6c..31f737aa3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java @@ -10,9 +10,9 @@ import java.util.function.BinaryOperator; /** * SerBinaryOperator * - * @author VampireAchao - * @since 2022/6/8 * @param 参数和返回值类型 + * @author VampireAchao + * @see BinaryOperator */ @FunctionalInterface public interface SerBinaryOperator extends BinaryOperator, Serializable { @@ -44,7 +44,7 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { } /** - * Returns a {@link SerBinaryOperator} which returns the lesser of two elements + * Returns a {@code SerBinaryOperator} which returns the lesser of two elements * according to the specified {@code Comparator}. * * @param the type of the input arguments of the comparator @@ -59,7 +59,7 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { } /** - * Returns a {@link SerBinaryOperator} which returns the greater of two elements + * Returns a {@code SerBinaryOperator} which returns the greater of two elements * according to the specified {@code Comparator}. * * @param the type of the input arguments of the comparator diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java index e9380ea0f..b4d798ddc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java @@ -66,7 +66,7 @@ public interface SerConsumer extends Consumer, Serializable { */ default SerConsumer andThen(final SerConsumer after) { Objects.requireNonNull(after); - return (T t) -> { + return (final T t) -> { accept(t); after.accept(t); }; diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java index 888d503d1..dd1200c62 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java @@ -34,10 +34,10 @@ public interface SerConsumer3 extends Serializable { * @param p2 参数二 * @param p3 参数三 */ - default void accept(P1 p1, P2 p2, P3 p3) { + default void accept(final P1 p1, final P2 p2, final P3 p3) { try { accepting(p1, p2, p3); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -54,9 +54,9 @@ public interface SerConsumer3 extends Serializable { * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ - default SerConsumer3 andThen(SerConsumer3 after) { + default SerConsumer3 andThen(final SerConsumer3 after) { Objects.requireNonNull(after); - return (P1 p1, P2 p2, P3 p3) -> { + return (final P1 p1, final P2 p2, final P3 p3) -> { accept(p1, p2, p3); after.accept(p1, p2, p3); }; diff --git a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java index 7a825c4de..75f8f8aa1 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java @@ -326,9 +326,9 @@ public class TimeUtilTest { @Test public void formatDateFunctionTest() { - List dateStrList = Stream.of("2023-03-01", "2023-03-02") + final List dateStrList = Stream.of("2023-03-01", "2023-03-02") .map(LocalDate::parse) - .map(TimeUtil.formatDateFunction(DatePattern.CHINESE_DATE_FORMATTER)) + .map(TimeUtil.formatFunc(DatePattern.CHINESE_DATE_FORMATTER)) .collect(Collectors.toList()); Assert.assertEquals("2023年03月01日", dateStrList.get(0)); Assert.assertEquals("2023年03月02日", dateStrList.get(1)); @@ -336,9 +336,9 @@ public class TimeUtilTest { @Test public void formatTimeFunctionTest() { - List dateStrList = Stream.of("2023-03-01T12:23:56", "2023-03-02T12:23:56") + final List dateStrList = Stream.of("2023-03-01T12:23:56", "2023-03-02T12:23:56") .map(LocalDateTime::parse) - .map(TimeUtil.formatTimeFunction(DatePattern.CHINESE_DATE_FORMATTER)) + .map(TimeUtil.formatFunc(DatePattern.CHINESE_DATE_FORMATTER)) .collect(Collectors.toList()); Assert.assertEquals("2023年03月01日", dateStrList.get(0)); Assert.assertEquals("2023年03月02日", dateStrList.get(1)); From 09b5cc671e7ed2a6cde3ef09c3768180a209eaa3 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 8 Mar 2023 23:51:29 +0800 Subject: [PATCH 085/125] add test --- .../main/java/cn/hutool/http/HttpConfig.java | 278 ------------------ .../http/server/RedirectServerTest.java | 27 ++ 2 files changed, 27 insertions(+), 278 deletions(-) delete mode 100755 hutool-http/src/main/java/cn/hutool/http/HttpConfig.java create mode 100644 hutool-http/src/test/java/cn/hutool/http/server/RedirectServerTest.java diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpConfig.java b/hutool-http/src/main/java/cn/hutool/http/HttpConfig.java deleted file mode 100755 index 36cc0af66..000000000 --- a/hutool-http/src/main/java/cn/hutool/http/HttpConfig.java +++ /dev/null @@ -1,278 +0,0 @@ -package cn.hutool.http; - -import cn.hutool.core.lang.Assert; -import cn.hutool.core.net.ssl.SSLUtil; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLSocketFactory; -import java.net.InetSocketAddress; -import java.net.Proxy; - -/** - * Http配置项 - * - * @author looly - * @since 5.8.0 - */ -public class HttpConfig { - - /** - * 创建默认Http配置信息 - * - * @return HttpConfig - */ - public static HttpConfig of() { - return new HttpConfig(); - } - - /** - * 默认连接超时 - */ - public int connectionTimeout = HttpGlobalConfig.getTimeout(); - /** - * 默认读取超时 - */ - public int readTimeout = HttpGlobalConfig.getTimeout(); - - /** - * 是否禁用缓存 - */ - public boolean isDisableCache; - - /** - * 最大重定向次数 - */ - public int maxRedirectCount = HttpGlobalConfig.getMaxRedirectCount(); - - /** - * 代理 - */ - public Proxy proxy; - - /** - * HostnameVerifier,用于HTTPS安全连接 - */ - public HostnameVerifier hostnameVerifier; - /** - * SSLSocketFactory,用于HTTPS安全连接 - */ - public SSLSocketFactory ssf; - - /** - * Chuncked块大小,0或小于0表示不设置Chuncked模式 - */ - public int blockSize; - - /** - * 获取是否忽略响应读取时可能的EOF异常。
      - * 在Http协议中,对于Transfer-Encoding: Chunked在正常情况下末尾会写入一个Length为0的的chunk标识完整结束。
      - * 如果服务端未遵循这个规范或响应没有正常结束,会报EOF异常,此选项用于是否忽略这个异常。 - */ - boolean ignoreEOFError = HttpGlobalConfig.isIgnoreEOFError(); - /** - * 获取是否忽略解码URL,包括URL中的Path部分和Param部分。
      - * 在构建Http请求时,用户传入的URL可能有编码后和未编码的内容混合在一起,如果此参数为{@code true},则会统一解码编码后的参数,
      - * 按照RFC3986规范,在发送请求时,全部编码之。如果为{@code false},则不会解码已经编码的内容,在请求时只编码需要编码的部分。 - */ - boolean decodeUrl = HttpGlobalConfig.isDecodeUrl(); - - /** - * 重定向时是否使用拦截器 - */ - public boolean interceptorOnRedirect; - - /** - * 设置超时,单位:毫秒
      - * 超时包括: - * - *

      -	 * 1. 连接超时
      -	 * 2. 读取响应超时
      -	 * 
      - * - * @param milliseconds 超时毫秒数 - * @return this - * @see #setConnectionTimeout(int) - * @see #setReadTimeout(int) - */ - public HttpConfig timeout(final int milliseconds) { - setConnectionTimeout(milliseconds); - setReadTimeout(milliseconds); - return this; - } - - /** - * 设置连接超时,单位:毫秒 - * - * @param milliseconds 超时毫秒数 - * @return this - */ - public HttpConfig setConnectionTimeout(final int milliseconds) { - this.connectionTimeout = milliseconds; - return this; - } - - /** - * 设置读取超时,单位:毫秒 - * - * @param milliseconds 超时毫秒数 - * @return this - */ - public HttpConfig setReadTimeout(final int milliseconds) { - this.readTimeout = milliseconds; - return this; - } - - /** - * 禁用缓存 - * - * @return this - */ - public HttpConfig disableCache() { - this.isDisableCache = true; - return this; - } - - /** - * 设置最大重定向次数
      - * 如果次数小于1则表示不重定向,大于等于1表示打开重定向 - * - * @param maxRedirectCount 最大重定向次数 - * @return this - */ - public HttpConfig setMaxRedirectCount(final int maxRedirectCount) { - this.maxRedirectCount = Math.max(maxRedirectCount, 0); - return this; - } - - /** - * 设置域名验证器
      - * 只针对HTTPS请求,如果不设置,不做验证,所有域名被信任 - * - * @param hostnameVerifier HostnameVerifier - * @return this - */ - public HttpConfig setHostnameVerifier(final HostnameVerifier hostnameVerifier) { - // 验证域 - this.hostnameVerifier = hostnameVerifier; - return this; - } - - /** - * 设置Http代理 - * - * @param host 代理 主机 - * @param port 代理 端口 - * @return this - */ - public HttpConfig setHttpProxy(final String host, final int port) { - final Proxy proxy = new Proxy(Proxy.Type.HTTP, - new InetSocketAddress(host, port)); - return setProxy(proxy); - } - - /** - * 设置代理 - * - * @param proxy 代理 {@link Proxy} - * @return this - */ - public HttpConfig setProxy(final Proxy proxy) { - this.proxy = proxy; - return this; - } - - /** - * 设置SSLSocketFactory
      - * 只针对HTTPS请求,如果不设置,使用默认的SSLSocketFactory
      - * 默认SSLSocketFactory为:SSLSocketFactoryBuilder.create().build(); - * - * @param ssf SSLScketFactory - * @return this - */ - public HttpConfig setSSLSocketFactory(final SSLSocketFactory ssf) { - this.ssf = ssf; - return this; - } - - /** - * 设置HTTPS安全连接协议,只针对HTTPS请求,可以使用的协议包括:
      - * 此方法调用后{@link #setSSLSocketFactory(SSLSocketFactory)} 将被覆盖。 - * - *
      -	 * 1. TLSv1.2
      -	 * 2. TLSv1.1
      -	 * 3. SSLv3
      -	 * ...
      -	 * 
      - * - * @param protocol 协议 - * @return this - * @see SSLUtil#createSSLContext(String) - * @see #setSSLSocketFactory(SSLSocketFactory) - */ - public HttpConfig setSSLProtocol(final String protocol) { - Assert.notBlank(protocol, "protocol must be not blank!"); - setSSLSocketFactory(SSLUtil.createSSLContext(protocol).getSocketFactory()); - return this; - } - - /** - * 采用流方式上传数据,无需本地缓存数据。
      - * HttpUrlConnection默认是将所有数据读到本地缓存,然后再发送给服务器,这样上传大文件时就会导致内存溢出。 - * - * @param blockSize 块大小(bytes数),0或小于0表示不设置Chuncked模式 - * @return this - */ - public HttpConfig setBlockSize(final int blockSize) { - this.blockSize = blockSize; - return this; - } - - /** - * 设置是否忽略响应读取时可能的EOF异常。
      - * 在Http协议中,对于Transfer-Encoding: Chunked在正常情况下末尾会写入一个Length为0的的chunk标识完整结束。
      - * 如果服务端未遵循这个规范或响应没有正常结束,会报EOF异常,此选项用于是否忽略这个异常。 - * - * @param ignoreEOFError 是否忽略响应读取时可能的EOF异常。 - * @return this - * @since 5.7.20 - */ - public HttpConfig setIgnoreEOFError(final boolean ignoreEOFError) { - this.ignoreEOFError = ignoreEOFError; - return this; - } - - /** - * 设置是否忽略解码URL,包括URL中的Path部分和Param部分。
      - * 在构建Http请求时,用户传入的URL可能有编码后和未编码的内容混合在一起,如果此参数为{@code true},则会统一解码编码后的参数,
      - * 按照RFC3986规范,在发送请求时,全部编码之。如果为{@code false},则不会解码已经编码的内容,在请求时只编码需要编码的部分。 - * - * @param decodeUrl 是否忽略解码URL - * @return this - */ - public HttpConfig setDecodeUrl(final boolean decodeUrl) { - this.decodeUrl = decodeUrl; - return this; - } - - /** - * 重定向时是否使用拦截器 - * - * @param interceptorOnRedirect 重定向时是否使用拦截器 - * @return this - */ - public HttpConfig setInterceptorOnRedirect(final boolean interceptorOnRedirect) { - this.interceptorOnRedirect = interceptorOnRedirect; - return this; - } - - /** - * 获取是否忽略响应读取时可能的EOF异常。 - * - * @return 是否忽略响应读取时可能的EOF异常。 - */ - public boolean isIgnoreEOFError() { - return ignoreEOFError; - } -} diff --git a/hutool-http/src/test/java/cn/hutool/http/server/RedirectServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/RedirectServerTest.java new file mode 100644 index 000000000..2e1896ede --- /dev/null +++ b/hutool-http/src/test/java/cn/hutool/http/server/RedirectServerTest.java @@ -0,0 +1,27 @@ +package cn.hutool.http.server; + +import cn.hutool.core.lang.Console; +import cn.hutool.http.HttpUtil; +import cn.hutool.http.meta.Header; + +public class RedirectServerTest { + public static void main(final String[] args) { + HttpUtil.createServer(8888).addAction("/redirect1", (request, response) -> { + response.addHeader(Header.LOCATION.getValue(),"http://localhost:8888/redirect2"); + response.addHeader(Header.SET_COOKIE.getValue(),"redirect1=1; path=/; HttpOnly"); + response.send(301); + }).addAction("/redirect2", (request, response) -> { + response.addHeader(Header.LOCATION.getValue(),"http://localhost:8888/redirect3"); + response.addHeader(Header.SET_COOKIE.getValue(), "redirect2=2; path=/; HttpOnly"); + response.send(301); + }).addAction("/redirect3", (request, response) -> { + response.addHeader(Header.LOCATION.getValue(),"http://localhost:8888/redirect4"); + response.addHeader(Header.SET_COOKIE.getValue(),"redirect3=3; path=/; HttpOnly"); + response.send(301); + }).addAction("/redirect4", (request, response) -> { + final String cookie = request.getHeader(Header.COOKIE); + Console.log(cookie); + response.sendOk(); + }).start(); + } +} From 9fb3a0dba48c20314d5d52c789f24f3ef5cfeed8 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 11:58:37 +0800 Subject: [PATCH 086/125] fix code --- hutool-log/pom.xml | 5 +- .../hutool/log/dialect/tinylog/TinyLog.java | 67 +++++++++++-------- .../services/cn.hutool.log.LogFactory | 2 +- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index c3a2f0430..851b85afd 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -26,6 +26,7 @@ 2.19.0 1.2 1.3.6 + 2.6.0 3.4.3.Final 0.44.3 @@ -78,7 +79,7 @@ org.tinylog tinylog-api - 2.5.0 + ${tinylog2.version} true @@ -104,7 +105,7 @@ org.tinylog tinylog-impl - 2.5.0 + ${tinylog2.version} test diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog.java b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog.java index 50313054c..8334d4045 100644 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog.java @@ -12,22 +12,33 @@ import cn.hutool.log.AbstractLog; * tinylog log.
      * * @author Looly - * */ public class TinyLog extends AbstractLog { private static final long serialVersionUID = -4848042277045993735L; - /** 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 */ + /** + * 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 + */ private static final int DEPTH = 4; private final int level; private final String name; + /** + * 构造 + * + * @param clazz 类 + */ // ------------------------------------------------------------------------- Constructor public TinyLog(final Class clazz) { this(null == clazz ? StrUtil.NULL : clazz.getName()); } + /** + * 构造 + * + * @param name 日志名 + */ public TinyLog(final String name) { this.name = name; this.level = Logger.getLevel(name).ordinal(); @@ -59,6 +70,7 @@ public class TinyLog extends AbstractLog { public void debug(final String fqcn, final Throwable t, final String format, final Object... arguments) { logIfEnabled(fqcn, Level.DEBUG, t, format, arguments); } + // ------------------------------------------------------------------------- Info @Override public boolean isInfoEnabled() { @@ -105,15 +117,16 @@ public class TinyLog extends AbstractLog { /** * 在对应日志级别打开情况下打印日志 - * @param fqcn 完全限定类名(Fully Qualified Class Name),用于定位日志位置 - * @param level 日志级别 - * @param t 异常,null则检查最后一个参数是否为Throwable类型,是则取之,否则不打印堆栈 - * @param format 日志消息模板 + * + * @param fqcn 完全限定类名(Fully Qualified Class Name),用于定位日志位置 + * @param level 日志级别 + * @param t 异常,null则检查最后一个参数是否为Throwable类型,是则取之,否则不打印堆栈 + * @param format 日志消息模板 * @param arguments 日志消息参数 */ private void logIfEnabled(final String fqcn, final Level level, Throwable t, final String format, final Object... arguments) { // fqcn 无效 - if(null == t){ + if (null == t) { t = getLastArgumentIfThrowable(arguments); } LogEntryForwarder.forward(DEPTH, level, t, StrUtil.toString(format), arguments); @@ -129,26 +142,26 @@ public class TinyLog extends AbstractLog { private Level toTinyLevel(final cn.hutool.log.level.Level level) { final Level tinyLevel; switch (level) { - case TRACE: - tinyLevel = Level.TRACE; - break; - case DEBUG: - tinyLevel = Level.DEBUG; - break; - case INFO: - tinyLevel = Level.INFO; - break; - case WARN: - tinyLevel = Level.WARNING; - break; - case ERROR: - tinyLevel = Level.ERROR; - break; - case OFF: - tinyLevel = Level.OFF; - break; - default: - throw new Error(StrUtil.format("Can not identify level: {}", level)); + case TRACE: + tinyLevel = Level.TRACE; + break; + case DEBUG: + tinyLevel = Level.DEBUG; + break; + case INFO: + tinyLevel = Level.INFO; + break; + case WARN: + tinyLevel = Level.WARNING; + break; + case ERROR: + tinyLevel = Level.ERROR; + break; + case OFF: + tinyLevel = Level.OFF; + break; + default: + throw new Error(StrUtil.format("Can not identify level: {}", level)); } return tinyLevel; } diff --git a/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory b/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory index b0bec7baa..eb6ad17c6 100644 --- a/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory +++ b/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory @@ -3,6 +3,6 @@ cn.hutool.log.dialect.slf4j.Slf4jLogFactory cn.hutool.log.dialect.log4j2.Log4j2LogFactory cn.hutool.log.dialect.log4j.Log4jLogFactory cn.hutool.log.dialect.commons.ApacheCommonsLogFactory -cn.hutool.log.dialect.tinylog.TinyLogFactory cn.hutool.log.dialect.tinylog.TinyLog2Factory +cn.hutool.log.dialect.tinylog.TinyLogFactory cn.hutool.log.dialect.jboss.JbossLogFactory From 728957baa3718121d434bb82cd4a343cf795bbc6 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 20:48:37 +0800 Subject: [PATCH 087/125] fix code --- .../src/main/java/cn/hutool/core/math/Calculator.java | 5 ++++- .../src/test/java/cn/hutool/core/math/CalculatorTest.java | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/math/Calculator.java b/hutool-core/src/main/java/cn/hutool/core/math/Calculator.java index bf54ed668..3657c72d6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/Calculator.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/Calculator.java @@ -56,7 +56,10 @@ public class Calculator { resultStack.push(tempResult.toString()); } } - return Double.parseDouble(resultStack.pop()); + + // 当结果集中有多个数字时,可能是省略*,类似(1+2)3 + return NumberUtil.mul(resultStack.toArray(new String[0])).doubleValue(); + //return Double.parseDouble(resultStack.pop()); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/math/CalculatorTest.java b/hutool-core/src/test/java/cn/hutool/core/math/CalculatorTest.java index 58068831e..9ad352fc9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/math/CalculatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/math/CalculatorTest.java @@ -48,4 +48,12 @@ public class CalculatorTest { final double conversion = Calculator.conversion("((-2395+0) * 0.3+140.24+35+90)/30"); Assert.assertEquals(-15.11D, conversion, 0.01); } + + @Test + public void issue2964Test() { + // 忽略数字之间的运算符,按照乘法对待。 + // https://github.com/dromara/hutool/issues/2964 + final double calcValue = Calculator.conversion("(11+2)12"); + Assert.assertEquals(156D, calcValue, 0.001); + } } From 8eb7352d14decc0c34d427c5391a604f5acbbb1f Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 20:49:30 +0800 Subject: [PATCH 088/125] add test --- .../src/test/java/cn/hutool/json/Issue2953Test.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 hutool-json/src/test/java/cn/hutool/json/Issue2953Test.java diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue2953Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue2953Test.java new file mode 100755 index 000000000..f997d7eb9 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/Issue2953Test.java @@ -0,0 +1,13 @@ +package cn.hutool.json; + +import org.junit.Assert; +import org.junit.Test; + +public class Issue2953Test { + @Test + public void parseObjWithBigNumberTest() { + final String a = "{\"a\": 114793903847679990000000000000000000000}"; + final JSONObject jsonObject = JSONUtil.parseObj(a, JSONConfig.of()); + Assert.assertEquals("{\"a\":\"114793903847679990000000000000000000000\"}", jsonObject.toString()); + } +} From 1a8a97e7b8f2857df6ec15614bbdba6795b6eae7 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 20:51:23 +0800 Subject: [PATCH 089/125] fix code --- .../cn/hutool/crypto/GlobalBouncyCastleProvider.java | 2 +- .../src/main/java/cn/hutool/db/ds/DSFactory.java | 12 ++++++------ .../src/main/java/cn/hutool/poi/PoiChecker.java | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/GlobalBouncyCastleProvider.java b/hutool-crypto/src/main/java/cn/hutool/crypto/GlobalBouncyCastleProvider.java index 7c8d872b1..500b2558c 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/GlobalBouncyCastleProvider.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/GlobalBouncyCastleProvider.java @@ -19,7 +19,7 @@ public enum GlobalBouncyCastleProvider { GlobalBouncyCastleProvider() { try { this.provider = ProviderFactory.createBouncyCastleProvider(); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } } diff --git a/hutool-db/src/main/java/cn/hutool/db/ds/DSFactory.java b/hutool-db/src/main/java/cn/hutool/db/ds/DSFactory.java index 36d518ab5..18a3a8656 100644 --- a/hutool-db/src/main/java/cn/hutool/db/ds/DSFactory.java +++ b/hutool-db/src/main/java/cn/hutool/db/ds/DSFactory.java @@ -154,34 +154,34 @@ public abstract class DSFactory implements Closeable, Serializable{ private static DSFactory doCreate(final Setting setting) { try { return new HikariDSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } try { return new DruidDSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } try { return new TomcatDSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { //如果未引入包,此处会报org.apache.tomcat.jdbc.pool.PoolConfiguration未找到错误 //因为org.apache.tomcat.jdbc.pool.DataSource实现了此接口,会首先检查接口的存在与否 // ignore } try { return new BeeDSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } try { return new DbcpDSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } try { return new C3p0DSFactory(setting); - } catch (final NoClassDefFoundError e) { + } catch (final NoClassDefFoundError | NoSuchMethodError e) { // ignore } return new PooledDSFactory(setting); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/PoiChecker.java b/hutool-poi/src/main/java/cn/hutool/poi/PoiChecker.java index e93df4768..8c56b46a0 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/PoiChecker.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/PoiChecker.java @@ -20,7 +20,7 @@ public class PoiChecker { public static void checkPoiImport() { try { Class.forName("org.apache.poi.ss.usermodel.Workbook", false, ClassLoaderUtil.getClassLoader()); - } catch (final ClassNotFoundException | NoClassDefFoundError e) { + } catch (final ClassNotFoundException | NoClassDefFoundError | NoSuchMethodError e) { throw new DependencyException(e, NO_POI_ERROR_MSG); } } From 0af9f4b5d8e957dcf34f4347212e399b6bd4880e Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 22:32:54 +0800 Subject: [PATCH 090/125] fix code --- hutool-json/pom.xml | 6 ++ .../java/cn/hutool/json/InternalJSONUtil.java | 12 +-- .../main/java/cn/hutool/json/JSONNumber.java | 81 +++++++++++++++++++ .../main/java/cn/hutool/json/JSONString.java | 76 +++++++++++++++++ .../main/java/cn/hutool/json/JSONSupport.java | 4 +- .../cn/hutool/json/convert/JSONConverter.java | 30 ++++--- .../hutool/json/serialize/DateJSONString.java | 2 +- .../{JSONString.java => JSONStringer.java} | 2 +- .../json/writer/JSONStringValueWriter.java | 16 ++-- .../cn/hutool/json/writer/JSONWriter.java | 6 +- .../java/cn/hutool/json/IssueI6LBZATest.java | 34 ++++++++ .../java/cn/hutool/json/JSONUtilTest.java | 4 +- .../hutool/log/{test => }/CustomLogTest.java | 4 +- .../cn/hutool/log/{test => }/LogTest.java | 7 +- .../cn/hutool/log/{test => }/LogTubeTest.java | 4 +- .../hutool/log/{test => }/StaticLogTest.java | 4 +- 16 files changed, 244 insertions(+), 48 deletions(-) create mode 100755 hutool-json/src/main/java/cn/hutool/json/JSONNumber.java create mode 100755 hutool-json/src/main/java/cn/hutool/json/JSONString.java rename hutool-json/src/main/java/cn/hutool/json/serialize/{JSONString.java => JSONStringer.java} (90%) create mode 100755 hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java rename hutool-log/src/test/java/cn/hutool/log/{test => }/CustomLogTest.java (97%) rename hutool-log/src/test/java/cn/hutool/log/{test => }/LogTest.java (91%) rename hutool-log/src/test/java/cn/hutool/log/{test => }/LogTubeTest.java (78%) rename hutool-log/src/test/java/cn/hutool/log/{test => }/StaticLogTest.java (88%) diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 5c1d63446..34a39eb72 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -41,6 +41,12 @@ ${bouncycastle.version} test
      + + com.alibaba.fastjson2 + fastjson2 + 2.0.24 + test + diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index a8931d3ad..26da40e64 100755 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -17,7 +17,7 @@ import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.json.serialize.GlobalSerializeMapping; import cn.hutool.json.serialize.JSONDeserializer; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; import cn.hutool.json.writer.GlobalValueWriterMapping; import cn.hutool.json.writer.JSONValueWriter; @@ -63,7 +63,7 @@ public final class InternalJSONUtil { } if (object instanceof JSON // - || object instanceof JSONString // + || object instanceof JSONStringer // || object instanceof CharSequence // || object instanceof Number // || ObjUtil.isBasicType(object) // @@ -117,8 +117,8 @@ public final class InternalJSONUtil { /** * 值转为String,用于JSON中。规则为: *
        - *
      • 对象如果实现了{@link JSONString}接口,调用{@link JSONString#toJSONString()}方法
      • - *
      • 对象如果实现了{@link JSONString}接口,调用{@link JSONString#toJSONString()}方法
      • + *
      • 对象如果实现了{@link JSONStringer}接口,调用{@link JSONStringer#toJSONString()}方法
      • + *
      • 对象如果实现了{@link JSONStringer}接口,调用{@link JSONStringer#toJSONString()}方法
      • *
      • 对象如果是数组或Collection,包装为{@link JSONArray}
      • *
      • 对象如果是Map,包装为{@link JSONObject}
      • *
      • 对象如果是数字,使用{@link NumberUtil#toStr(Number)}转换为字符串
      • @@ -133,9 +133,9 @@ public final class InternalJSONUtil { if (value == null) { return StrUtil.NULL; } - if (value instanceof JSONString) { + if (value instanceof JSONStringer) { try { - return ((JSONString) value).toJSONString(); + return ((JSONStringer) value).toJSONString(); } catch (final Exception e) { throw new JSONException(e); } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java b/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java new file mode 100755 index 000000000..fd70a85c6 --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java @@ -0,0 +1,81 @@ +package cn.hutool.json; + +import cn.hutool.core.lang.mutable.MutableEntry; +import cn.hutool.core.math.NumberUtil; + +import java.io.IOException; +import java.io.Writer; +import java.util.function.Predicate; + +/** + * JSON数字表示 + * + * @author looly + * @since 6.0.0 + */ +public class JSONNumber extends Number implements JSON { + private static final long serialVersionUID = 1L; + + private final Number value; + /** + * 配置项 + */ + private final JSONConfig config; + + /** + * 构造 + * + * @param value 值 + * @param config JSON配置 + */ + public JSONNumber(final Number value, final JSONConfig config) { + this.value = value; + this.config = config; + } + + @Override + public JSONConfig getConfig() { + return this.config; + } + + @Override + public int size() { + return 1; + } + + @Override + public Writer write(final Writer writer, final int indentFactor, final int indent, + final Predicate> predicate) throws JSONException { + try { + writer.write(toString()); + } catch (final IOException e) { + throw new RuntimeException(e); + } + return writer; + } + + @Override + public int intValue() { + return this.value.intValue(); + } + + @Override + public long longValue() { + return this.value.longValue(); + } + + @Override + public float floatValue() { + return this.value.floatValue(); + } + + @Override + public double doubleValue() { + return this.value.doubleValue(); + } + + @Override + public String toString() { + return NumberUtil.toStr(this.value); + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONString.java b/hutool-json/src/main/java/cn/hutool/json/JSONString.java new file mode 100755 index 000000000..435947307 --- /dev/null +++ b/hutool-json/src/main/java/cn/hutool/json/JSONString.java @@ -0,0 +1,76 @@ +package cn.hutool.json; + +import cn.hutool.core.lang.mutable.MutableEntry; + +import java.io.IOException; +import java.io.Writer; +import java.util.function.Predicate; + +/** + * JSON字符串,表示一个字符串 + * + * @author looly + * @since 6.0.0 + */ +public class JSONString implements JSON, CharSequence { + private static final long serialVersionUID = 1L; + + private final char[] value; + /** + * 配置项 + */ + private final JSONConfig config; + + /** + * 构造 + * + * @param value char数组 + * @param config 配置项 + */ + public JSONString(final char[] value, final JSONConfig config) { + this.value = value; + this.config = config; + } + + @Override + public JSONConfig getConfig() { + return this.config; + } + + @Override + public int size() { + return length(); + } + + @Override + public Writer write(final Writer writer, final int indentFactor, final int indent, + final Predicate> predicate) throws JSONException { + try { + writer.write(this.value); + } catch (final IOException e) { + throw new RuntimeException(e); + } + return writer; + } + + @Override + public int length() { + return this.value.length; + } + + @Override + public char charAt(final int index) { + return this.value[index]; + } + + @Override + public CharSequence subSequence(final int start, final int end) { + return ((start == 0) && (end == this.value.length)) ? this + : new String(this.value, start, end); + } + + @Override + public String toString() { + return String.valueOf(this.value); + } +} diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java index 2f6ea18a2..7733f5dfb 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java @@ -2,7 +2,7 @@ package cn.hutool.json; import cn.hutool.core.bean.copier.BeanCopier; import cn.hutool.json.serialize.JSONDeserializer; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; /** * JSON支持
        @@ -10,7 +10,7 @@ import cn.hutool.json.serialize.JSONString; * * @author Looly */ -public class JSONSupport implements JSONString, JSONDeserializer { +public class JSONSupport implements JSONStringer, JSONDeserializer { /** * JSON String转Bean diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java index 5e82f329a..0aea0ed49 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java @@ -12,20 +12,15 @@ import cn.hutool.core.convert.impl.DateConverter; import cn.hutool.core.convert.impl.MapConverter; import cn.hutool.core.convert.impl.TemporalAccessorConverter; import cn.hutool.core.map.MapWrapper; +import cn.hutool.core.math.NumberUtil; import cn.hutool.core.reflect.ConstructorUtil; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.reflect.TypeUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ArrayUtil; -import cn.hutool.json.InternalJSONUtil; -import cn.hutool.json.JSON; -import cn.hutool.json.JSONArray; -import cn.hutool.json.JSONConfig; -import cn.hutool.json.JSONException; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; +import cn.hutool.json.*; import cn.hutool.json.serialize.JSONDeserializer; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; import java.lang.reflect.Type; import java.time.temporal.TemporalAccessor; @@ -81,9 +76,9 @@ public class JSONConverter implements Converter { if (null == value) { return null; } - if (value instanceof JSONString) { + if (value instanceof JSONStringer) { // 被JSONString包装的对象,获取其原始类型 - value = ((JSONString) value).getRaw(); + value = ((JSONStringer) value).getRaw(); } // JSON转对象 @@ -131,7 +126,20 @@ public class JSONConverter implements Converter { json = (JSON) obj; } else if (obj instanceof CharSequence) { final String jsonStr = StrUtil.trim((CharSequence) obj); - json = JSONUtil.isTypeJSONArray(jsonStr) ? new JSONArray(jsonStr, config) : new JSONObject(jsonStr, config); + switch (jsonStr.charAt(0)){ + case '"': + case '\'': + return new JSONString(jsonStr.toCharArray(), config); + case '[': + return new JSONArray(jsonStr, config); + case '{': + return new JSONObject(jsonStr, config); + default: + if(NumberUtil.isNumber(jsonStr)){ + return new JSONNumber(NumberUtil.toBigDecimal(jsonStr), config); + } + throw new JSONException("Unsupported String to JSON: {}", jsonStr); + } } else if (obj instanceof MapWrapper) { // MapWrapper实现了Iterable会被当作JSONArray,此处做修正 json = new JSONObject(obj, config); diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/DateJSONString.java b/hutool-json/src/main/java/cn/hutool/json/serialize/DateJSONString.java index 3b67b80b4..be08a72d1 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/DateJSONString.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/DateJSONString.java @@ -20,7 +20,7 @@ import java.util.Date; * @author looly * @since 6.0.0 */ -public class DateJSONString implements JSONString { +public class DateJSONString implements JSONStringer { final Object dateObj; final JSONConfig jsonConfig; diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONString.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONStringer.java similarity index 90% rename from hutool-json/src/main/java/cn/hutool/json/serialize/JSONString.java rename to hutool-json/src/main/java/cn/hutool/json/serialize/JSONStringer.java index e3e639b51..ac0d8d241 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONString.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONStringer.java @@ -10,7 +10,7 @@ import cn.hutool.core.lang.func.Wrapper; * */ @FunctionalInterface -public interface JSONString extends Wrapper { +public interface JSONStringer extends Wrapper { /** * 自定义转JSON字符串的方法 diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java index dab0aa9fb..68b897bb3 100755 --- a/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/writer/JSONStringValueWriter.java @@ -1,7 +1,7 @@ package cn.hutool.json.writer; import cn.hutool.json.JSONException; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; import java.time.temporal.TemporalAccessor; import java.util.Calendar; @@ -14,32 +14,32 @@ import java.util.Date; * @author looly * @since 6.0.0 */ -public class JSONStringValueWriter implements JSONValueWriter { +public class JSONStringValueWriter implements JSONValueWriter { /** * 单例对象 */ public static final JSONStringValueWriter INSTANCE = new JSONStringValueWriter(); /** - * 输出实现了{@link JSONString}接口的对象,通过调用{@link JSONString#toJSONString()}获取JSON字符串
        - * {@link JSONString}按照JSON对象对待,此方法输出的JSON字符串不包装引号。
        + * 输出实现了{@link JSONStringer}接口的对象,通过调用{@link JSONStringer#toJSONString()}获取JSON字符串
        + * {@link JSONStringer}按照JSON对象对待,此方法输出的JSON字符串不包装引号。
        * 如果toJSONString()返回null,调用toString()方法并使用双引号包装。 * * @param writer {@link JSONWriter} - * @param jsonString {@link JSONString} + * @param jsonStringer {@link JSONStringer} */ @Override - public void write(final JSONWriter writer, final JSONString jsonString) { + public void write(final JSONWriter writer, final JSONStringer jsonStringer) { final String valueStr; try { - valueStr = jsonString.toJSONString(); + valueStr = jsonStringer.toJSONString(); } catch (final Exception e) { throw new JSONException(e); } if (null != valueStr) { writer.writeRaw(valueStr); } else { - writer.writeQuoteStrValue(jsonString.toString()); + writer.writeQuoteStrValue(jsonStringer.toString()); } } } diff --git a/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java b/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java index b3b99d021..5f020ba4e 100755 --- a/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/writer/JSONWriter.java @@ -8,7 +8,7 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.json.InternalJSONUtil; import cn.hutool.json.JSON; import cn.hutool.json.JSONConfig; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; import java.io.IOException; import java.io.Writer; @@ -321,8 +321,8 @@ public class JSONWriter extends Writer { DateValueWriter.INSTANCE.write(this, value); } else if (value instanceof Boolean) { BooleanValueWriter.INSTANCE.write(this, (Boolean) value); - } else if (value instanceof JSONString) { - JSONStringValueWriter.INSTANCE.write(this, (JSONString) value); + } else if (value instanceof JSONStringer) { + JSONStringValueWriter.INSTANCE.write(this, (JSONStringer) value); } else { writeQuoteStrValue(value.toString()); } diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java b/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java new file mode 100755 index 000000000..b38e5232f --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java @@ -0,0 +1,34 @@ +package cn.hutool.json; + +import org.junit.Assert; +import org.junit.Test; + +public class IssueI6LBZATest { + @Test + public void parseJSONStringTest() { + final String a = "\"a\""; + final JSON parse = JSONUtil.parse(a); + Assert.assertEquals(JSONString.class, parse.getClass()); + } + + @Test + public void parseJSONStringTest2() { + final String a = "'a'"; + final JSON parse = JSONUtil.parse(a); + Assert.assertEquals(JSONString.class, parse.getClass()); + } + + @Test(expected = JSONException.class) + public void parseJSONErrorTest() { + final String a = "a"; + final JSON parse = JSONUtil.parse(a); + Assert.assertEquals(JSONString.class, parse.getClass()); + } + + @Test + public void parseJSONNumberTest() { + final String a = "123"; + final JSON parse = JSONUtil.parse(a); + Assert.assertEquals(JSONNumber.class, parse.getClass()); + } +} diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index c1683ba49..fcfeeb590 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.math.NumberUtil; -import cn.hutool.json.serialize.JSONString; +import cn.hutool.json.serialize.JSONStringer; import cn.hutool.json.test.bean.Price; import cn.hutool.json.test.bean.UserA; import cn.hutool.json.test.bean.UserC; @@ -179,7 +179,7 @@ public class JSONUtilTest { @Test public void customValueTest() { final JSONObject jsonObject = JSONUtil.ofObj() - .set("test2", (JSONString) () -> NumberUtil.format("#.0", 12.00D)); + .set("test2", (JSONStringer) () -> NumberUtil.format("#.0", 12.00D)); Assert.assertEquals("{\"test2\":12.0}", jsonObject.toString()); } diff --git a/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java b/hutool-log/src/test/java/cn/hutool/log/CustomLogTest.java similarity index 97% rename from hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java rename to hutool-log/src/test/java/cn/hutool/log/CustomLogTest.java index d16270303..398581a52 100644 --- a/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java +++ b/hutool-log/src/test/java/cn/hutool/log/CustomLogTest.java @@ -1,7 +1,5 @@ -package cn.hutool.log.test; +package cn.hutool.log; -import cn.hutool.log.Log; -import cn.hutool.log.LogFactory; import cn.hutool.log.dialect.commons.ApacheCommonsLogFactory; import cn.hutool.log.dialect.console.ConsoleLogFactory; import cn.hutool.log.dialect.jboss.JbossLogFactory; diff --git a/hutool-log/src/test/java/cn/hutool/log/test/LogTest.java b/hutool-log/src/test/java/cn/hutool/log/LogTest.java similarity index 91% rename from hutool-log/src/test/java/cn/hutool/log/test/LogTest.java rename to hutool-log/src/test/java/cn/hutool/log/LogTest.java index 588ea7035..c6977d4cf 100644 --- a/hutool-log/src/test/java/cn/hutool/log/test/LogTest.java +++ b/hutool-log/src/test/java/cn/hutool/log/LogTest.java @@ -1,12 +1,9 @@ -package cn.hutool.log.test; +package cn.hutool.log; +import cn.hutool.log.level.Level; import org.junit.Ignore; import org.junit.Test; -import cn.hutool.log.Log; -import cn.hutool.log.LogFactory; -import cn.hutool.log.level.Level; - /** * 日志门面单元测试 * @author Looly diff --git a/hutool-log/src/test/java/cn/hutool/log/test/LogTubeTest.java b/hutool-log/src/test/java/cn/hutool/log/LogTubeTest.java similarity index 78% rename from hutool-log/src/test/java/cn/hutool/log/test/LogTubeTest.java rename to hutool-log/src/test/java/cn/hutool/log/LogTubeTest.java index 85a43bc2b..3fbf51d4b 100644 --- a/hutool-log/src/test/java/cn/hutool/log/test/LogTubeTest.java +++ b/hutool-log/src/test/java/cn/hutool/log/LogTubeTest.java @@ -1,7 +1,5 @@ -package cn.hutool.log.test; +package cn.hutool.log; -import cn.hutool.log.Log; -import cn.hutool.log.LogFactory; import cn.hutool.log.dialect.logtube.LogTubeLogFactory; import org.junit.Test; diff --git a/hutool-log/src/test/java/cn/hutool/log/test/StaticLogTest.java b/hutool-log/src/test/java/cn/hutool/log/StaticLogTest.java similarity index 88% rename from hutool-log/src/test/java/cn/hutool/log/test/StaticLogTest.java rename to hutool-log/src/test/java/cn/hutool/log/StaticLogTest.java index aeac9854f..7256f9af2 100755 --- a/hutool-log/src/test/java/cn/hutool/log/test/StaticLogTest.java +++ b/hutool-log/src/test/java/cn/hutool/log/StaticLogTest.java @@ -1,7 +1,5 @@ -package cn.hutool.log.test; +package cn.hutool.log; -import cn.hutool.log.LogFactory; -import cn.hutool.log.StaticLog; import cn.hutool.log.dialect.console.ConsoleColorLogFactory; import cn.hutool.log.dialect.console.ConsoleLogFactory; import org.junit.Test; From b17cd4abb19fe4c30611ccf2bf31900ebd51af46 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 22:37:33 +0800 Subject: [PATCH 091/125] fix coder --- hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java index 5ffccf534..73d09596b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java @@ -226,8 +226,8 @@ public class PropDesc { */ public PropDesc setValue(final Object bean, final Object value) { if (null != this.setter) { - //MethodUtil.invoke(bean, this.setter, value); - LambdaUtil.buildSetter(this.setter).accept(bean, value); + MethodUtil.invoke(bean, this.setter, value); + //LambdaUtil.buildSetter(this.setter).accept(bean, value); } else if (ModifierUtil.isPublic(this.field)) { FieldUtil.setFieldValue(bean, this.field, value); } From b3ddbcba23ee83fc03c6c5973beba45ed3c9acbc Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Mar 2023 23:33:09 +0800 Subject: [PATCH 092/125] fix code --- .../java/cn/hutool/core/bean/PropDesc.java | 5 ++-- .../cn/hutool/core/lang/func/LambdaUtil.java | 9 +++++- .../core/bean/BeanWithReturnThisTest.java | 30 +++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 hutool-core/src/test/java/cn/hutool/core/bean/BeanWithReturnThisTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java index 73d09596b..1b745c1e0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java @@ -5,7 +5,6 @@ import cn.hutool.core.annotation.PropIgnore; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.reflect.FieldUtil; -import cn.hutool.core.reflect.MethodUtil; import cn.hutool.core.reflect.ModifierUtil; import cn.hutool.core.reflect.ReflectUtil; import cn.hutool.core.reflect.TypeUtil; @@ -226,8 +225,8 @@ public class PropDesc { */ public PropDesc setValue(final Object bean, final Object value) { if (null != this.setter) { - MethodUtil.invoke(bean, this.setter, value); - //LambdaUtil.buildSetter(this.setter).accept(bean, value); + //MethodUtil.invoke(bean, this.setter, value); + LambdaUtil.buildSetter(this.setter).accept(bean, value); } else if (ModifierUtil.isPublic(this.field)) { FieldUtil.setFieldValue(bean, this.field, value); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java index 19ccd47d2..77d70a246 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java @@ -168,7 +168,14 @@ public class LambdaUtil { */ @SuppressWarnings("unchecked") public static BiConsumer buildSetter(final Method setMethod) { - return LambdaFactory.build(BiConsumer.class, setMethod); + final Class returnType = setMethod.getReturnType(); + if(Void.class == returnType){ + return LambdaFactory.build(BiConsumer.class, setMethod); + } + + // 返回this的setter + final BiFunction biFunction = LambdaFactory.build(BiFunction.class, setMethod); + return biFunction::apply; } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanWithReturnThisTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanWithReturnThisTest.java new file mode 100644 index 000000000..acec2d47c --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanWithReturnThisTest.java @@ -0,0 +1,30 @@ +package cn.hutool.core.bean; + +import org.junit.Assert; +import org.junit.Test; + +public class BeanWithReturnThisTest { + + @Test + public void setValueTest() { + final BeanWithRetuenThis bean = new BeanWithRetuenThis(); + final BeanDesc beanDesc = BeanUtil.getBeanDesc(BeanWithRetuenThis.class); + final PropDesc prop = beanDesc.getProp("a"); + prop.setValue(bean, "123"); + + Assert.assertEquals("123", bean.getA()); + } + + static class BeanWithRetuenThis{ + public String getA() { + return a; + } + + public BeanWithRetuenThis setA(final String a) { + this.a = a; + return this; + } + + private String a; + } +} From 17e9cd97acb6b61ae376b7af33a24a163a6b2629 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 00:51:16 +0800 Subject: [PATCH 093/125] fix code --- .../core/net/ssl/SSLContextBuilder.java | 4 +-- .../java/cn/hutool/core/net/ssl/SSLUtil.java | 30 ++++++++++++++----- ...Manager.java => TrustAnyTrustManager.java} | 12 ++++---- .../cn/hutool/http/client/ClientConfig.java | 10 +++---- .../engine/httpclient5/HttpClient5Engine.java | 20 ++++++++++--- .../client/engine/jdk/HttpConnection.java | 6 ++-- .../http/ssl/CustomProtocolsSSLFactory.java | 2 +- .../http/ssl/TrustAnyHostnameVerifier.java | 2 +- ...faultSSLInfo.java => TrustAnySSLInfo.java} | 5 ++-- 9 files changed, 59 insertions(+), 32 deletions(-) rename hutool-core/src/main/java/cn/hutool/core/net/ssl/{DefaultTrustManager.java => TrustAnyTrustManager.java} (71%) rename hutool-http/src/main/java/cn/hutool/http/ssl/{DefaultSSLInfo.java => TrustAnySSLInfo.java} (80%) diff --git a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java index fe62c62e5..62975599f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java @@ -18,7 +18,7 @@ import java.security.SecureRandom; *
          *
        • 协议(protocol),默认TLS
        • *
        • {@link KeyManager},默认空
        • - *
        • {@link TrustManager},默认{@link DefaultTrustManager},即信任全部
        • + *
        • {@link TrustManager},默认{@link TrustAnyTrustManager},即信任全部
        • *
        • {@link SecureRandom}
        • *
        *

        @@ -32,7 +32,7 @@ public class SSLContextBuilder implements SSLProtocols, Builder { private String protocol = TLS; private KeyManager[] keyManagers; - private TrustManager[] trustManagers = {DefaultTrustManager.INSTANCE}; + private TrustManager[] trustManagers = {TrustAnyTrustManager.INSTANCE}; private SecureRandom secureRandom = new SecureRandom(); diff --git a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLUtil.java index ecd1f2ac5..e8b56dfd0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLUtil.java @@ -15,23 +15,37 @@ import javax.net.ssl.TrustManager; public class SSLUtil { /** - * 创建{@link SSLContext},默认新人全部 + * 创建{@link SSLContext},信任全部,协议为TLS * - * @param protocol SSL协议,例如TLS等 + * @return {@link SSLContext} + * @throws IORuntimeException 包装 GeneralSecurityException异常 + */ + public static SSLContext createTrustAnySSLContext() throws IORuntimeException { + return createTrustAnySSLContext(null); + } + + /** + * 创建{@link SSLContext},信任全部 + * + * @param protocol SSL协议,例如TLS等,{@code null}表示默认TLS * @return {@link SSLContext} * @throws IORuntimeException 包装 GeneralSecurityException异常 * @since 5.7.8 */ - public static SSLContext createSSLContext(final String protocol) throws IORuntimeException{ - return SSLContextBuilder.of().setProtocol(protocol).build(); + public static SSLContext createTrustAnySSLContext(final String protocol) throws IORuntimeException { + return SSLContextBuilder.of() + .setProtocol(protocol) + // 信任所有服务端 + .setTrustManagers(new TrustManager[]{TrustAnyTrustManager.INSTANCE}) + .build(); } /** * 创建{@link SSLContext} * * @param protocol SSL协议,例如TLS等 - * @param keyManager 密钥管理器,{@code null}表示无 - * @param trustManager 信任管理器, {@code null}表示无 + * @param keyManager 密钥管理器,{@code null}表示默认 + * @param trustManager 信任管理器, {@code null}表示默认 * @return {@link SSLContext} * @throws IORuntimeException 包装 GeneralSecurityException异常 */ @@ -46,8 +60,8 @@ public class SSLUtil { * 创建和初始化{@link SSLContext} * * @param protocol SSL协议,例如TLS等 - * @param keyManagers 密钥管理器,{@code null}表示无 - * @param trustManagers 信任管理器, {@code null}表示无 + * @param keyManagers 密钥管理器,{@code null}表示默认 + * @param trustManagers 信任管理器, {@code null}表示默认 * @return {@link SSLContext} * @throws IORuntimeException 包装 GeneralSecurityException异常 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/net/ssl/DefaultTrustManager.java b/hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyTrustManager.java similarity index 71% rename from hutool-core/src/main/java/cn/hutool/core/net/ssl/DefaultTrustManager.java rename to hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyTrustManager.java index 1f0903fdb..13fe0f137 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/ssl/DefaultTrustManager.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyTrustManager.java @@ -6,19 +6,21 @@ import java.net.Socket; import java.security.cert.X509Certificate; /** - * 默认信任管理器,默认信任所有客户端和服务端证书
        - * 继承{@link X509ExtendedTrustManager}的原因见:https://blog.csdn.net/ghaohao/article/details/79454913 + * 新任所有信任管理器,默认信任所有客户端和服务端证书
        + * 继承{@link X509ExtendedTrustManager}的原因见:
        + * https://blog.csdn.net/ghaohao/article/details/79454913 * * @author Looly * @since 5.5.7 */ -public class DefaultTrustManager extends X509ExtendedTrustManager { +public class TrustAnyTrustManager extends X509ExtendedTrustManager { /** - * 默认的全局单例默认信任管理器,默认信任所有客户端和服务端证书 + * 全局单例信任管理器,默认信任所有客户端和服务端证书 + * * @since 5.7.8 */ - public static DefaultTrustManager INSTANCE = new DefaultTrustManager(); + public static TrustAnyTrustManager INSTANCE = new TrustAnyTrustManager(); @Override public X509Certificate[] getAcceptedIssuers() { diff --git a/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java b/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java index d07d27a40..95fc4ea0f 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java @@ -3,7 +3,7 @@ package cn.hutool.http.client; import cn.hutool.core.lang.Assert; import cn.hutool.core.net.ssl.SSLUtil; import cn.hutool.http.HttpGlobalConfig; -import cn.hutool.http.ssl.DefaultSSLInfo; +import cn.hutool.http.ssl.TrustAnySSLInfo; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSocketFactory; @@ -58,8 +58,8 @@ public class ClientConfig { public ClientConfig() { connectionTimeout = HttpGlobalConfig.getTimeout(); readTimeout = HttpGlobalConfig.getTimeout(); - hostnameVerifier = DefaultSSLInfo.TRUST_ANY_HOSTNAME_VERIFIER; - socketFactory = DefaultSSLInfo.DEFAULT_SSF; + hostnameVerifier = TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER; + socketFactory = TrustAnySSLInfo.DEFAULT_SSF; } /** @@ -179,12 +179,12 @@ public class ClientConfig { * * @param protocol 协议 * @return this - * @see SSLUtil#createSSLContext(String) + * @see SSLUtil#createTrustAnySSLContext(String) * @see #setSocketFactory(SSLSocketFactory) */ public ClientConfig setSSLProtocol(final String protocol) { Assert.notBlank(protocol, "protocol must be not blank!"); - setSocketFactory(SSLUtil.createSSLContext(protocol).getSocketFactory()); + setSocketFactory(SSLUtil.createTrustAnySSLContext(protocol).getSocketFactory()); return this; } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index bc3d3fef6..5b3557ca4 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -2,6 +2,7 @@ package cn.hutool.http.client.engine.httpclient5; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.net.ssl.SSLUtil; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.http.GlobalHeaders; import cn.hutool.http.HttpException; @@ -11,11 +12,13 @@ import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; import cn.hutool.http.client.body.HttpBody; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; @@ -86,14 +89,22 @@ public class HttpClient5Engine implements ClientEngine { return; } + // 连接配置 + final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create() + .setSslContext(SSLUtil.createTrustAnySSLContext()).build()); + final int connectionTimeout = this.config.getConnectionTimeout(); + if(connectionTimeout > 0){ + connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); + } + + // 请求配置 RequestConfig requestConfig = null; if(null != this.config){ final RequestConfig.Builder builder = RequestConfig.custom(); - final int connectionTimeout = this.config.getConnectionTimeout(); if(connectionTimeout > 0){ - // TODO 细化替换 - builder.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); builder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS); } final int readTimeout = this.config.getReadTimeout(); @@ -105,6 +116,7 @@ public class HttpClient5Engine implements ClientEngine { } final HttpClientBuilder builder = HttpClients.custom() + .setConnectionManager(connectionManagerBuilder.build()) .setDefaultRequestConfig(requestConfig) // 设置默认头信息 .setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java index 6d4072780..302046572 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java @@ -7,7 +7,7 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.http.HttpException; import cn.hutool.http.client.HeaderOperation; import cn.hutool.http.meta.Method; -import cn.hutool.http.ssl.DefaultSSLInfo; +import cn.hutool.http.ssl.TrustAnySSLInfo; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -211,8 +211,8 @@ public class HttpConnection implements HeaderOperation { // Https请求 final HttpsURLConnection httpsConn = (HttpsURLConnection) conn; // 验证域 - httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(hostnameVerifier, DefaultSSLInfo.TRUST_ANY_HOSTNAME_VERIFIER)); - httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(ssf, DefaultSSLInfo.DEFAULT_SSF)); + httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(hostnameVerifier, TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER)); + httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(ssf, TrustAnySSLInfo.DEFAULT_SSF)); } return this; diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java index c7cbc3332..4433c766a 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java @@ -28,7 +28,7 @@ public class CustomProtocolsSSLFactory extends SSLSocketFactory { */ public CustomProtocolsSSLFactory(final String... protocols) throws IORuntimeException { this.protocols = protocols; - this.base = SSLUtil.createSSLContext(null).getSocketFactory(); + this.base = SSLUtil.createTrustAnySSLContext(null).getSocketFactory(); } @Override diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java b/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java index 75d04730d..e10eb6d6e 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java @@ -4,7 +4,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; /** - * https 域名校验 + * https 域名校验,信任所有域名 * * @author Looly */ diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLInfo.java b/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java similarity index 80% rename from hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLInfo.java rename to hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java index fad532a73..699c2c64a 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLInfo.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java @@ -5,12 +5,11 @@ import cn.hutool.core.text.StrUtil; import javax.net.ssl.SSLSocketFactory; /** - * 默认的全局SSL配置,当用户未设置相关信息时,使用默认设置,默认设置为单例模式。 + * 新任所有SSL配置 * * @author looly - * @since 5.1.2 */ -public class DefaultSSLInfo { +public class TrustAnySSLInfo { /** * 默认信任全部的域名校验器 */ From 58c6fed95030ee4a1d90b1fc38831d347285d754 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 01:06:23 +0800 Subject: [PATCH 094/125] fix code --- .../src/main/java/cn/hutool/core/lang/func/LambdaUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java index 77d70a246..26d6bad8f 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java @@ -169,7 +169,7 @@ public class LambdaUtil { @SuppressWarnings("unchecked") public static BiConsumer buildSetter(final Method setMethod) { final Class returnType = setMethod.getReturnType(); - if(Void.class == returnType){ + if(Void.TYPE == returnType){ return LambdaFactory.build(BiConsumer.class, setMethod); } From 869b12000debeaa8abbf4af364cfd24fb4a90f6f Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 01:32:27 +0800 Subject: [PATCH 095/125] fix code --- .../client/engine/httpclient5/HttpClient5Engine.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index 5b3557ca4..33690ec10 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -93,15 +93,16 @@ public class HttpClient5Engine implements ClientEngine { final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create() .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create() .setSslContext(SSLUtil.createTrustAnySSLContext()).build()); - final int connectionTimeout = this.config.getConnectionTimeout(); - if(connectionTimeout > 0){ - connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); - } // 请求配置 RequestConfig requestConfig = null; + if(null != this.config){ + final int connectionTimeout = this.config.getConnectionTimeout(); + if(connectionTimeout > 0){ + connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); + } final RequestConfig.Builder builder = RequestConfig.custom(); if(connectionTimeout > 0){ From 35feac4eaef1dd85feb0bd8878479fa8e5845210 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 13:07:05 +0800 Subject: [PATCH 096/125] fix code --- .../main/java/cn/hutool/core/io/FileUtil.java | 32 +--- .../cn/hutool/core/io/file/FileReader.java | 30 ++-- .../java/cn/hutool/core/util/XmlUtil.java | 11 +- .../core/lang/func/LambdaFactoryTest.java | 4 + .../java/cn/hutool/core/util/XmlUtilTest.java | 19 ++ .../main/java/cn/hutool/json/JSONNumber.java | 81 --------- .../main/java/cn/hutool/json/JSONString.java | 76 -------- .../main/java/cn/hutool/json/JSONUtil.java | 164 ++++++------------ .../cn/hutool/json/convert/JSONConverter.java | 14 +- .../java/cn/hutool/json/IssueI6LBZATest.java | 18 +- .../java/cn/hutool/json/JSONArrayTest.java | 3 +- .../java/cn/hutool/json/JSONPathTest.java | 2 +- .../java/cn/hutool/json/JSONUtilTest.java | 5 +- 13 files changed, 123 insertions(+), 336 deletions(-) delete mode 100755 hutool-json/src/main/java/cn/hutool/json/JSONNumber.java delete mode 100755 hutool-json/src/main/java/cn/hutool/json/JSONString.java diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 28a890ff5..d284e6a07 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -4,12 +4,12 @@ import cn.hutool.core.compress.ZipUtil; import cn.hutool.core.io.file.FileReader; import cn.hutool.core.io.file.*; import cn.hutool.core.io.file.FileWriter; -import cn.hutool.core.io.file.FileReader.ReaderHandler; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.stream.BOMInputStream; import cn.hutool.core.io.unit.DataSizeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.func.SerConsumer; +import cn.hutool.core.lang.func.SerFunction; import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.reflect.ClassUtil; import cn.hutool.core.regex.ReUtil; @@ -1976,10 +1976,9 @@ public class FileUtil extends PathUtil { * @param path 文件的绝对路径 * @return 从文件中load出的数据 * @throws IORuntimeException IO异常 - * @since 3.1.1 */ - public static T loadUtf8(final String path, final ReaderHandler readerHandler) throws IORuntimeException { - return load(path, CharsetUtil.UTF_8, readerHandler); + public static T readUtf8(final String path, final SerFunction readerHandler) throws IORuntimeException { + return read(path, CharsetUtil.UTF_8, readerHandler); } /** @@ -1993,23 +1992,8 @@ public class FileUtil extends PathUtil { * @throws IORuntimeException IO异常 * @since 3.1.1 */ - public static T load(final String path, final String charset, final ReaderHandler readerHandler) throws IORuntimeException { - return FileReader.of(file(path), CharsetUtil.charset(charset)).read(readerHandler); - } - - /** - * 按照给定的readerHandler读取文件中的数据 - * - * @param 集合类型 - * @param readerHandler Reader处理类 - * @param path 文件的绝对路径 - * @param charset 字符集 - * @return 从文件中load出的数据 - * @throws IORuntimeException IO异常 - * @since 3.1.1 - */ - public static T load(final String path, final Charset charset, final ReaderHandler readerHandler) throws IORuntimeException { - return FileReader.of(file(path), charset).read(readerHandler); + public static T read(final String path, final Charset charset, final SerFunction readerHandler) throws IORuntimeException { + return read(file(path), charset, readerHandler); } /** @@ -2022,8 +2006,8 @@ public class FileUtil extends PathUtil { * @throws IORuntimeException IO异常 * @since 3.1.1 */ - public static T loadUtf8(final File file, final ReaderHandler readerHandler) throws IORuntimeException { - return load(file, CharsetUtil.UTF_8, readerHandler); + public static T readUtf8(final File file, final SerFunction readerHandler) throws IORuntimeException { + return read(file, CharsetUtil.UTF_8, readerHandler); } /** @@ -2037,7 +2021,7 @@ public class FileUtil extends PathUtil { * @throws IORuntimeException IO异常 * @since 3.1.1 */ - public static T load(final File file, final Charset charset, final ReaderHandler readerHandler) throws IORuntimeException { + public static T read(final File file, final Charset charset, final SerFunction readerHandler) throws IORuntimeException { return FileReader.of(file, charset).read(readerHandler); } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java index 0b73ad6a4..5590b81f7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java @@ -1,9 +1,11 @@ package cn.hutool.core.io.file; +import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.func.SerConsumer; +import cn.hutool.core.lang.func.SerFunction; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharsetUtil; @@ -17,6 +19,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; /** * 文件读取器 @@ -207,14 +210,20 @@ public class FileReader extends FileWrapper { * @return 从文件中read出的数据 * @throws IORuntimeException IO异常 */ - public T read(final ReaderHandler readerHandler) throws IORuntimeException { + public T read(final SerFunction readerHandler) throws IORuntimeException { BufferedReader reader = null; T result; try { reader = FileUtil.getReader(this.file, charset); - result = readerHandler.handle(reader); - } catch (final IOException e) { - throw new IORuntimeException(e); + result = readerHandler.applying(reader); + } catch (final Exception e) { + if(e instanceof IOException){ + throw new IORuntimeException(e); + } else if(e instanceof RuntimeException){ + throw (RuntimeException)e; + } else{ + throw new UtilException(e); + } } finally { IoUtil.close(reader); } @@ -277,19 +286,6 @@ public class FileReader extends FileWrapper { } } - // -------------------------------------------------------------------------- Interface start - /** - * Reader处理接口 - * - * @author Luxiaolei - * - * @param Reader处理返回结果类型 - */ - public interface ReaderHandler { - T handle(BufferedReader reader) throws IOException; - } - // -------------------------------------------------------------------------- Interface end - /** * 检查文件 * diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index 42d56fb77..450f94688 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -1,12 +1,14 @@ package cn.hutool.core.util; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Console; import cn.hutool.core.map.BiMap; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrUtil; @@ -181,7 +183,8 @@ public class XmlUtil { * @return XML文档对象 * @since 3.0.9 */ - public static Document readXML(final String pathOrContent) { + public static Document readXML(String pathOrContent) { + pathOrContent = StrUtil.trim(pathOrContent); if (StrUtil.startWith(pathOrContent, '<')) { return parseXml(pathOrContent); } @@ -985,11 +988,7 @@ public class XmlUtil { public static T xmlToBean(final Node node, final Class bean) { final Map map = xmlToMap(node); if (null != map && map.size() == 1) { - final String simpleName = bean.getSimpleName(); - if (map.containsKey(simpleName)) { - // 只有key和bean的名称匹配时才做单一对象转换 - return BeanUtil.toBean(map.get(simpleName), bean); - } + return BeanUtil.toBean(CollUtil.get(map.values(), 0), bean); } return BeanUtil.toBean(map, bean); } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java index 233153b44..83f65ee41 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/func/LambdaFactoryTest.java @@ -7,6 +7,7 @@ import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -71,6 +72,7 @@ public class LambdaFactoryTest { * @author nasodaengineer */ @RunWith(Parameterized.class) + @Ignore public static class PerformanceTest { @Parameterized.Parameter @@ -140,6 +142,7 @@ public class LambdaFactoryTest { @SuppressWarnings({"rawtypes", "unchecked", "Convert2MethodRef"}) @Test @SneakyThrows + @Ignore public void lambdaGetPerformanceTest() { final Something something = new Something(); something.setId(1L); @@ -216,6 +219,7 @@ public class LambdaFactoryTest { @SuppressWarnings({"rawtypes", "unchecked"}) @Test @SneakyThrows + @Ignore public void lambdaSetPerformanceTest() { final Something something = new Something(); something.setId(1L); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index f14e98859..595b457dd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -348,4 +348,23 @@ public class XmlUtilTest { Console.log(XmlUtil.format(doc)); } + + @Test + public void xmlStrToBeanTest(){ + final String xml = "张三20zhangsan@example.com"; + final Document document = XmlUtil.readXML(xml); + final UserInfo userInfo = XmlUtil.xmlToBean(document, UserInfo.class); + Assert.assertEquals("张三", userInfo.getName()); + Assert.assertEquals("20", userInfo.getAge()); + Assert.assertEquals("zhangsan@example.com", userInfo.getEmail()); + } + + @Data + static class UserInfo { + + private String id; + private String name; + private String age; + private String email; + } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java b/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java deleted file mode 100755 index fd70a85c6..000000000 --- a/hutool-json/src/main/java/cn/hutool/json/JSONNumber.java +++ /dev/null @@ -1,81 +0,0 @@ -package cn.hutool.json; - -import cn.hutool.core.lang.mutable.MutableEntry; -import cn.hutool.core.math.NumberUtil; - -import java.io.IOException; -import java.io.Writer; -import java.util.function.Predicate; - -/** - * JSON数字表示 - * - * @author looly - * @since 6.0.0 - */ -public class JSONNumber extends Number implements JSON { - private static final long serialVersionUID = 1L; - - private final Number value; - /** - * 配置项 - */ - private final JSONConfig config; - - /** - * 构造 - * - * @param value 值 - * @param config JSON配置 - */ - public JSONNumber(final Number value, final JSONConfig config) { - this.value = value; - this.config = config; - } - - @Override - public JSONConfig getConfig() { - return this.config; - } - - @Override - public int size() { - return 1; - } - - @Override - public Writer write(final Writer writer, final int indentFactor, final int indent, - final Predicate> predicate) throws JSONException { - try { - writer.write(toString()); - } catch (final IOException e) { - throw new RuntimeException(e); - } - return writer; - } - - @Override - public int intValue() { - return this.value.intValue(); - } - - @Override - public long longValue() { - return this.value.longValue(); - } - - @Override - public float floatValue() { - return this.value.floatValue(); - } - - @Override - public double doubleValue() { - return this.value.doubleValue(); - } - - @Override - public String toString() { - return NumberUtil.toStr(this.value); - } -} diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONString.java b/hutool-json/src/main/java/cn/hutool/json/JSONString.java deleted file mode 100755 index 435947307..000000000 --- a/hutool-json/src/main/java/cn/hutool/json/JSONString.java +++ /dev/null @@ -1,76 +0,0 @@ -package cn.hutool.json; - -import cn.hutool.core.lang.mutable.MutableEntry; - -import java.io.IOException; -import java.io.Writer; -import java.util.function.Predicate; - -/** - * JSON字符串,表示一个字符串 - * - * @author looly - * @since 6.0.0 - */ -public class JSONString implements JSON, CharSequence { - private static final long serialVersionUID = 1L; - - private final char[] value; - /** - * 配置项 - */ - private final JSONConfig config; - - /** - * 构造 - * - * @param value char数组 - * @param config 配置项 - */ - public JSONString(final char[] value, final JSONConfig config) { - this.value = value; - this.config = config; - } - - @Override - public JSONConfig getConfig() { - return this.config; - } - - @Override - public int size() { - return length(); - } - - @Override - public Writer write(final Writer writer, final int indentFactor, final int indent, - final Predicate> predicate) throws JSONException { - try { - writer.write(this.value); - } catch (final IOException e) { - throw new RuntimeException(e); - } - return writer; - } - - @Override - public int length() { - return this.value.length; - } - - @Override - public char charAt(final int index) { - return this.value[index]; - } - - @Override - public CharSequence subSequence(final int start, final int end) { - return ((start == 0) && (end == this.value.length)) ? this - : new String(this.value, start, end); - } - - @Override - public String toString() { - return String.valueOf(this.value); - } -} diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index 55d71d46b..7863af839 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -2,6 +2,7 @@ package cn.hutool.json; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.FileReader; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; @@ -27,7 +28,6 @@ import java.util.List; public class JSONUtil { // -------------------------------------------------------------------- Pause start - /** * 创建JSONObject * @@ -139,8 +139,8 @@ public class JSONUtil { * @param obj 对象 * @return JSON */ - public static JSON parse(final Object obj) { - return JSONConverter.INSTANCE.toJSON(obj); + public static Object parse(final Object obj) { + return parse(obj, null); } /** @@ -154,10 +154,12 @@ public class JSONUtil { * * @param obj 对象 * @param config JSON配置,{@code null}使用默认配置 - * @return JSON - * @since 5.3.1 + * @return JSON(JSONObject or JSONArray) */ - public static JSON parse(final Object obj, final JSONConfig config) { + public static Object parse(final Object obj, final JSONConfig config) { + if(null == config){ + return JSONConverter.INSTANCE.toJSON(obj); + } return JSONConverter.of(config).toJSON(obj); } @@ -173,6 +175,7 @@ public class JSONUtil { // -------------------------------------------------------------------- Parse end // -------------------------------------------------------------------- Read start + /** * 读取JSON * @@ -182,11 +185,7 @@ public class JSONUtil { * @throws IORuntimeException IO异常 */ public static JSON readJSON(final File file, final Charset charset) throws IORuntimeException { - try (final Reader reader = FileUtil.getReader(file, charset)) { - return parse(reader); - } catch (final IOException e) { - throw new IORuntimeException(e); - } + return (JSON) FileUtil.read(file, charset, JSONUtil::parse); } /** @@ -198,11 +197,7 @@ public class JSONUtil { * @throws IORuntimeException IO异常 */ public static JSONObject readJSONObject(final File file, final Charset charset) throws IORuntimeException { - try (final Reader reader = FileUtil.getReader(file, charset)) { - return parseObj(reader); - } catch (final IOException e) { - throw new IORuntimeException(e); - } + return FileUtil.read(file, charset, JSONUtil::parseObj); } /** @@ -214,67 +209,23 @@ public class JSONUtil { * @throws IORuntimeException IO异常 */ public static JSONArray readJSONArray(final File file, final Charset charset) throws IORuntimeException { - try (final Reader reader = FileUtil.getReader(file, charset)) { - return parseArray(reader); - } catch (final IOException e) { - throw new IORuntimeException(e); - } + return FileUtil.read(file, charset, JSONUtil::parseArray); } // -------------------------------------------------------------------- Read end // -------------------------------------------------------------------- toString start - /** - * 转为JSON字符串 + * 转换为格式化后的JSON字符串 * - * @param json JSON - * @param indentFactor 每一级别的缩进 + * @param obj Bean对象 * @return JSON字符串 */ - public static String toJsonStr(final JSON json, final int indentFactor) { - if (null == json) { - return null; + public static String toJsonPrettyStr(Object obj) { + obj = parse(obj); + if (obj instanceof JSON) { + return ((JSON) obj).toStringPretty(); } - return json.toJSONString(indentFactor); - } - - /** - * 转为JSON字符串 - * - * @param json JSON - * @return JSON字符串 - */ - public static String toJsonStr(final JSON json) { - if (null == json) { - return null; - } - return json.toJSONString(0); - } - - /** - * 转为JSON字符串,并写出到write - * - * @param json JSON - * @param writer Writer - * @since 5.3.3 - */ - public static void toJsonStr(final JSON json, final Writer writer) { - if (null != json) { - json.write(writer); - } - } - - /** - * 转为JSON字符串 - * - * @param json JSON - * @return JSON字符串 - */ - public static String toJsonPrettyStr(final JSON json) { - if (null == json) { - return null; - } - return json.toStringPretty(); + return StrUtil.toStringOrNull(obj); } /** @@ -299,7 +250,7 @@ public class JSONUtil { public static String toJsonStr(final Object obj, final JSONConfig jsonConfig) { // 自定义规则,优先级高于全局规则 final JSONValueWriter valueWriter = InternalJSONUtil.getValueWriter(obj); - if(null != valueWriter){ + if (null != valueWriter) { final StringWriter stringWriter = new StringWriter(); final JSONWriter jsonWriter = JSONWriter.of(stringWriter, 0, 0, null); // 用户对象自定义实现了JSONValueWriter接口,理解为需要自定义输出 @@ -307,17 +258,10 @@ public class JSONUtil { return stringWriter.toString(); } - if (null == obj) { + if(null == obj){ return null; } - if (obj instanceof CharSequence) { - return StrUtil.str((CharSequence) obj); - } - - if (obj instanceof Number) { - return obj.toString(); - } - return toJsonStr(parse(obj, jsonConfig)); + return parse(obj, jsonConfig).toString(); } /** @@ -327,20 +271,20 @@ public class JSONUtil { * @param writer Writer * @since 5.3.3 */ - public static void toJsonStr(final Object obj, final Writer writer) { + public static void toJsonStr(Object obj, final Writer writer) { if (null != obj) { - toJsonStr(parse(obj), writer); - } - } + obj = parse(obj); + if (obj instanceof JSON) { + ((JSON) obj).write(writer); + } - /** - * 转换为格式化后的JSON字符串 - * - * @param obj Bean对象 - * @return JSON字符串 - */ - public static String toJsonPrettyStr(final Object obj) { - return toJsonPrettyStr(parse(obj)); + // 普通值 + try { + writer.write(obj.toString()); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } } /** @@ -393,7 +337,7 @@ public class JSONUtil { * @since 5.8.0 */ public static T toBean(final String jsonString, final JSONConfig config, final Class beanClass) { - return toBean(parse(jsonString, config), beanClass); + return toBean(jsonString, config, (Type) beanClass); } /** @@ -405,23 +349,12 @@ public class JSONUtil { * @param config JSON配置 * @param type Bean类型 * @return 实体类对象 + * @throws JSONException 提供的JSON字符串不支持转Bean或字符串错误 */ - public static T toBean(final String jsonString, final JSONConfig config, final Type type) { + public static T toBean(final String jsonString, final JSONConfig config, final Type type) throws JSONException { return toBean(parse(jsonString, config), type); } - /** - * 转为实体类对象,转换异常将被抛出 - * - * @param Bean类型 - * @param json JSONObject - * @param beanClass 实体类对象 - * @return 实体类对象 - */ - public static T toBean(final JSONObject json, final Class beanClass) { - return null == json ? null : json.toBean(beanClass); - } - /** * 转为实体类对象 * @@ -431,24 +364,27 @@ public class JSONUtil { * @return 实体类对象 * @since 4.6.2 */ - public static T toBean(final JSON json, final TypeReference typeReference) { + public static T toBean(final Object json, final TypeReference typeReference) { return toBean(json, typeReference.getType()); } /** * 转为实体类对象 * - * @param Bean类型 - * @param json JSONObject - * @param beanType 实体类对象类型 + * @param Bean类型 + * @param json JSONObject + * @param type 实体类对象类型 * @return 实体类对象 * @since 4.3.2 */ - public static T toBean(final JSON json, final Type beanType) { + public static T toBean(final Object json, final Type type) { if (null == json) { return null; } - return json.toBean(beanType); + if (json instanceof JSON) { + return ((JSON) json).toBean(type); + } + throw new JSONException("Unsupported json string to bean : {}", json); } // -------------------------------------------------------------------- toBean end @@ -562,13 +498,13 @@ public class JSONUtil { * @param json JSONObject或JSONArray * @return 是否为空 */ - public static boolean isEmpty(final JSON json){ - if(null == json){ + public static boolean isEmpty(final JSON json) { + if (null == json) { return true; } - if(json instanceof JSONObject){ + if (json instanceof JSONObject) { return ((JSONObject) json).isEmpty(); - } else if(json instanceof JSONArray){ + } else if (json instanceof JSONArray) { return ((JSONArray) json).isEmpty(); } return false; diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java index 0aea0ed49..5792475b9 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java @@ -111,32 +111,34 @@ public class JSONConverter implements Converter { /** * 实现Object对象转换为{@link JSON},支持的对象: *

          - *
        • String: 转换为相应的对象
        • + *
        • String: 转换为相应的对象,
        • *
        • Array、Iterable、Iterator:转换为JSONArray
        • *
        • Bean对象:转为JSONObject
        • + *
        • Number:返回原对象
        • *
        * * @param obj 被转换的对象 * @return 转换后的对象 * @throws JSONException 转换异常 */ - public JSON toJSON(final Object obj) throws JSONException { + public Object toJSON(final Object obj) throws JSONException { final JSON json; - if (obj instanceof JSON) { - json = (JSON) obj; + if (obj instanceof JSON || obj instanceof Number) { + return obj; } else if (obj instanceof CharSequence) { final String jsonStr = StrUtil.trim((CharSequence) obj); switch (jsonStr.charAt(0)){ case '"': case '\'': - return new JSONString(jsonStr.toCharArray(), config); + // JSON字符串值 + return jsonStr; case '[': return new JSONArray(jsonStr, config); case '{': return new JSONObject(jsonStr, config); default: if(NumberUtil.isNumber(jsonStr)){ - return new JSONNumber(NumberUtil.toBigDecimal(jsonStr), config); + return NumberUtil.toBigDecimal(jsonStr); } throw new JSONException("Unsupported String to JSON: {}", jsonStr); } diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java b/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java index b38e5232f..161ec6f7f 100755 --- a/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI6LBZATest.java @@ -3,32 +3,34 @@ package cn.hutool.json; import org.junit.Assert; import org.junit.Test; +import java.math.BigDecimal; + public class IssueI6LBZATest { @Test public void parseJSONStringTest() { final String a = "\"a\""; - final JSON parse = JSONUtil.parse(a); - Assert.assertEquals(JSONString.class, parse.getClass()); + final Object parse = JSONUtil.parse(a); + Assert.assertEquals(String.class, parse.getClass()); } @Test public void parseJSONStringTest2() { final String a = "'a'"; - final JSON parse = JSONUtil.parse(a); - Assert.assertEquals(JSONString.class, parse.getClass()); + final Object parse = JSONUtil.parse(a); + Assert.assertEquals(String.class, parse.getClass()); } @Test(expected = JSONException.class) public void parseJSONErrorTest() { final String a = "a"; - final JSON parse = JSONUtil.parse(a); - Assert.assertEquals(JSONString.class, parse.getClass()); + final Object parse = JSONUtil.parse(a); + Assert.assertEquals(String.class, parse.getClass()); } @Test public void parseJSONNumberTest() { final String a = "123"; - final JSON parse = JSONUtil.parse(a); - Assert.assertEquals(JSONNumber.class, parse.getClass()); + final Object parse = JSONUtil.parse(a); + Assert.assertEquals(BigDecimal.class, parse.getClass()); } } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java index 4e366e50b..97a3ca581 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java @@ -42,8 +42,7 @@ public class JSONArrayTest { @Test public void addNullTest() { final List aaa = ListUtil.view("aaa", null); - final String jsonStr = JSONUtil.toJsonStr(JSONUtil.parse(aaa, - JSONConfig.of().setIgnoreNullValue(false))); + final String jsonStr = JSONUtil.toJsonStr(JSONUtil.parse(aaa, JSONConfig.of().setIgnoreNullValue(false))); Assert.assertEquals("[\"aaa\",null]", jsonStr); } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONPathTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONPathTest.java index 2e0c88d11..9765ca509 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONPathTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONPathTest.java @@ -23,7 +23,7 @@ public class JSONPathTest { @Test public void getByPathTest2(){ final String str = "{'accountId':111}"; - final JSON json = JSONUtil.parse(str); + final JSON json = (JSON) JSONUtil.parse(str); final Long accountId = JSONUtil.getByPath(json, "$.accountId", 0L); Assert.assertEquals(111L, accountId.longValue()); } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index fcfeeb590..6ad70ddb2 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -2,6 +2,7 @@ package cn.hutool.json; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import cn.hutool.core.math.NumberUtil; import cn.hutool.json.serialize.JSONStringer; @@ -235,9 +236,11 @@ public class JSONUtilTest { Assert.assertEquals("v1abc", xmlStr); } - @Test + @Test(expected = JSONException.class) public void toJsonStrOfStringTest(){ final String a = "a"; + + // 普通字符串不能解析为JSON字符串,必须由双引号或者单引号包裹 final String s = JSONUtil.toJsonStr(a); Assert.assertEquals(a, s); } From 8a154315fe85e544374363e5d7f4318e8aa9c5d3 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 13:23:59 +0800 Subject: [PATCH 097/125] fix code --- CHANGELOG.md | 5 ++--- hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java | 6 +++++- .../src/test/java/cn/hutool/core/util/XmlUtilTest.java | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a90222b..48e6feefe 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,13 @@ ------------------------------------------------------------------------------------------------------------- -# 6.0.0.M1 (2022-10-09) +# 6.0.0.M1 (2023-03-10) ### 计划实现 -* 【poi 】 PDF相关(基于PdfBox) -* 【poi 】 HTML、DOCX转换相关 * 【poi 】 Markdown相关(如HTML转换等),基于commonmark-java * 【db 】 增加DDL封装 * 【poi 】 CellUtil.getCellIfMergedRegion考虑添加缓存支持,增加最大和最小范围判断,减少遍历 +* 【http 】 公共代理和SSL验证 ### ❌不兼容特性 diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index 450f94688..65d66f91a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -988,7 +988,11 @@ public class XmlUtil { public static T xmlToBean(final Node node, final Class bean) { final Map map = xmlToMap(node); if (null != map && map.size() == 1) { - return BeanUtil.toBean(CollUtil.get(map.values(), 0), bean); + final String nodeName = CollUtil.getFirst(map.keySet()); + if (bean.getSimpleName().equalsIgnoreCase(nodeName)) { + // 只有key和bean的名称匹配时才做单一对象转换 + return BeanUtil.toBean(CollUtil.get(map.values(), 0), bean); + } } return BeanUtil.toBean(map, bean); } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index 595b457dd..99d1666f4 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -351,7 +351,7 @@ public class XmlUtilTest { @Test public void xmlStrToBeanTest(){ - final String xml = "张三20zhangsan@example.com"; + final String xml = "张三20zhangsan@example.com"; final Document document = XmlUtil.readXML(xml); final UserInfo userInfo = XmlUtil.xmlToBean(document, UserInfo.class); Assert.assertEquals("张三", userInfo.getName()); From 84448ffd8429656708374ffc4bff3a866ec141c3 Mon Sep 17 00:00:00 2001 From: LuisStruggle <18300767078@163.com> Date: Fri, 10 Mar 2023 13:43:50 +0800 Subject: [PATCH 098/125] =?UTF-8?q?fix=EF=BC=9AArrayUtil.addAll()=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=88=A4=E6=96=AD=E7=A9=BA=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/util/ArrayUtil.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index c7a152e22..6c572a5ee 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -588,15 +588,19 @@ public class ArrayUtil extends PrimitiveArrayUtil { int length = 0; for (final T[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } + final T[] result = newArray(arrays.getClass().getComponentType().getComponentType(), length); + if (length == 0) { + return result; + } length = 0; for (final T[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } From 75d7a98cccacbf4111a4f22b7df777f8c5f7d251 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Mar 2023 22:14:54 +0800 Subject: [PATCH 099/125] fix code --- .../hutool/core/util/PrimitiveArrayUtil.java | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java index 6e6fa42a2..2f446e5fd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java @@ -222,7 +222,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final byte[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -230,7 +230,7 @@ public class PrimitiveArrayUtil { final byte[] result = new byte[length]; length = 0; for (final byte[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -254,7 +254,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final int[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -262,7 +262,7 @@ public class PrimitiveArrayUtil { final int[] result = new int[length]; length = 0; for (final int[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -286,7 +286,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final long[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -294,7 +294,7 @@ public class PrimitiveArrayUtil { final long[] result = new long[length]; length = 0; for (final long[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -318,7 +318,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final double[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -326,7 +326,7 @@ public class PrimitiveArrayUtil { final double[] result = new double[length]; length = 0; for (final double[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -350,7 +350,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final float[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -358,7 +358,7 @@ public class PrimitiveArrayUtil { final float[] result = new float[length]; length = 0; for (final float[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -382,7 +382,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final char[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -390,7 +390,7 @@ public class PrimitiveArrayUtil { final char[] result = new char[length]; length = 0; for (final char[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -414,7 +414,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final boolean[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -422,7 +422,7 @@ public class PrimitiveArrayUtil { final boolean[] result = new boolean[length]; length = 0; for (final boolean[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -446,7 +446,7 @@ public class PrimitiveArrayUtil { // 计算总长度 int length = 0; for (final short[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { length += array.length; } } @@ -454,7 +454,7 @@ public class PrimitiveArrayUtil { final short[] result = new short[length]; length = 0; for (final short[] array : arrays) { - if (null != array) { + if (isNotEmpty(array)) { System.arraycopy(array, 0, result, length, array.length); length += array.length; } @@ -505,7 +505,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final long[] array, final long value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -524,7 +524,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final long[] array, final long value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; @@ -555,7 +555,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final int[] array, final int value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -574,7 +574,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final int[] array, final int value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; @@ -605,7 +605,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final short[] array, final short value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -624,7 +624,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final short[] array, final short value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; @@ -655,7 +655,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final char[] array, final char value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -674,7 +674,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final char[] array, final char value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; @@ -705,7 +705,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final byte[] array, final byte value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -724,7 +724,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final byte[] array, final byte value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; @@ -755,7 +755,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final double[] array, final double value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (NumberUtil.equals(value, array[i])) { return i; @@ -774,7 +774,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final double[] array, final double value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (NumberUtil.equals(value, array[i])) { return i; @@ -805,7 +805,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final float[] array, final float value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (NumberUtil.equals(value, array[i])) { return i; @@ -824,7 +824,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final float[] array, final float value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (NumberUtil.equals(value, array[i])) { return i; @@ -855,7 +855,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int indexOf(final boolean[] array, final boolean value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = 0; i < array.length; i++) { if (value == array[i]) { return i; @@ -874,7 +874,7 @@ public class PrimitiveArrayUtil { * @since 3.0.7 */ public static int lastIndexOf(final boolean[] array, final boolean value) { - if (null != array) { + if (isNotEmpty(array)) { for (int i = array.length - 1; i >= 0; i--) { if (value == array[i]) { return i; From 0bdeb7a17b27f74f5554265183f396b69b9dc1dd Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 11 Mar 2023 00:39:56 +0800 Subject: [PATCH 100/125] fix code --- .../main/java/cn/hutool/swing/img/Img.java | 53 +- .../java/cn/hutool/swing/img/ImgUtil.java | 320 ++++++---- .../swing/img/RenderingHintsBuilder.java | 566 ++++++++++++++++++ .../java/cn/hutool/swing/img/ImgTest.java | 9 + 4 files changed, 803 insertions(+), 145 deletions(-) create mode 100644 hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java index 6654f759d..1f25d955a 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java @@ -1,29 +1,18 @@ package cn.hutool.swing.img; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.resource.Resource; import cn.hutool.core.lang.Assert; import cn.hutool.core.math.NumberUtil; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ObjUtil; import javax.imageio.ImageIO; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; -import java.awt.AlphaComposite; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Stroke; +import java.awt.*; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; @@ -61,6 +50,10 @@ public class Img implements Serializable { * 图片输出质量,用于压缩 */ private float quality = -1; + /** + * 图片背景色 + */ + private Color backgroundColor; /** * 从Path读取图片并开始处理 @@ -217,6 +210,17 @@ public class Img implements Serializable { return this; } + /** + * 设置图片的背景色 + * + * @param backgroundColor{@link Color} 背景色 + * @return this + */ + public Img setBackgroundColor(final Color backgroundColor) { + this.backgroundColor = backgroundColor; + return this; + } + /** * 缩放图像(按比例缩放) * @@ -598,7 +602,7 @@ public class Img implements Serializable { * @since 3.2.2 */ public Img rotate(final int degree) { - if(0 == degree){ + if (0 == degree) { // 不旋转 return this; } @@ -606,13 +610,28 @@ public class Img implements Serializable { final int width = image.getWidth(null); final int height = image.getHeight(null); final Rectangle rectangle = calcRotatedSize(width, height, degree); + + // 目标图像 final BufferedImage targetImg = new BufferedImage(rectangle.width, rectangle.height, getTypeInt()); final Graphics2D graphics2d = targetImg.createGraphics(); - // 抗锯齿 - graphics2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + // 填充背景色 + if(null != this.backgroundColor){ + graphics2d.setColor(this.backgroundColor); + graphics2d.fill(rectangle); + } + + graphics2d.setRenderingHints( + RenderingHintsBuilder.of() + // 抗锯齿 + .setAntialiasing(RenderingHintsBuilder.Antialias.ON) + // 双线性插值 + .setInterpolation(RenderingHintsBuilder.Interpolation.BILINEAR).build()); + // 从中心旋转 graphics2d.translate((rectangle.width - width) / 2D, (rectangle.height - height) / 2D); graphics2d.rotate(Math.toRadians(degree), width / 2D, height / 2D); + graphics2d.drawImage(image, 0, 0, null); graphics2d.dispose(); this.targetImage = targetImg; @@ -714,7 +733,7 @@ public class Img implements Serializable { final Image targetImage = (null == this.targetImage) ? this.srcImage : this.targetImage; Assert.notNull(targetImage, "Target image is null !"); - return ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality); + return ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor); } /** diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index e2b0ab457..6a30272c2 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -12,45 +12,17 @@ import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; -import javax.imageio.IIOImage; -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.ImageWriteParam; -import javax.imageio.ImageWriter; +import javax.imageio.*; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import javax.swing.ImageIcon; -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.HeadlessException; -import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; +import java.awt.*; import java.awt.color.ColorSpace; import java.awt.font.FontRenderContext; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ColorConvertOp; -import java.awt.image.ColorModel; -import java.awt.image.FilteredImageSource; -import java.awt.image.ImageFilter; -import java.awt.image.RenderedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.awt.image.*; +import java.io.*; import java.net.URL; import java.util.Iterator; @@ -63,14 +35,34 @@ import java.util.Iterator; */ public class ImgUtil { + // region ----- [const] image type + /** + * GIF + */ public static final String IMAGE_TYPE_GIF = "gif";// 图形交换格式 + /** + * JPG + */ public static final String IMAGE_TYPE_JPG = "jpg";// 联合照片专家组 + /** + * JPEG + */ public static final String IMAGE_TYPE_JPEG = "jpeg";// 联合照片专家组 + /** + * BMP + */ public static final String IMAGE_TYPE_BMP = "bmp";// 英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式 + /** + * PNG + */ public static final String IMAGE_TYPE_PNG = "png";// 可移植网络图形 + /** + * PSD + */ public static final String IMAGE_TYPE_PSD = "psd";// Photoshop的专用格式Photoshop + // endregion - // ---------------------------------------------------------------------------------------------------------------------- scale + // region ----- scale /** * 缩放图像(按比例缩放),目标文件的扩展名决定目标文件类型 @@ -253,8 +245,9 @@ public class ImgUtil { public static Image scale(final Image srcImage, final int width, final int height, final Color fixedColor) { return Img.from(srcImage).scale(width, height, fixedColor).getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- cut + // region ----- cut and slice /** * 图像切割(按指定起点坐标和宽高切割) @@ -494,8 +487,9 @@ public class ImgUtil { throw new IORuntimeException(e); } } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- convert + // region ----- convert /** * 图像类型转换:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG @@ -554,8 +548,9 @@ public class ImgUtil { throw new IORuntimeException(e); } } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- grey + // region ----- grey /** * 彩色转为黑白 @@ -637,8 +632,9 @@ public class ImgUtil { public static Image gray(final Image srcImage) { return Img.from(srcImage).gray().getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- binary + // region ----- binary /** * 彩色转为黑白二值化图片,根据目标文件扩展名确定转换后的格式 @@ -724,8 +720,9 @@ public class ImgUtil { public static Image binary(final Image srcImage) { return Img.from(srcImage).binary().getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- press + // region ----- press /** * 给图片添加文字水印 @@ -975,8 +972,9 @@ public class ImgUtil { public static Image pressImage(final Image srcImage, final Image pressImg, final Rectangle rectangle, final float alpha) { return Img.from(srcImage).pressImage(pressImg, rectangle, alpha).getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- rotate + // region ----- rotate /** * 旋转图片为指定角度
        @@ -1046,8 +1044,9 @@ public class ImgUtil { public static Image rotate(final Image image, final int degree) { return Img.from(image).rotate(degree).getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- flip + // region ----- flip /** * 水平翻转图像 @@ -1107,8 +1106,9 @@ public class ImgUtil { public static Image flip(final Image image) { return Img.from(image).flip().getImg(); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- compress + // region ----- compress /** * 压缩图像,输出图像只支持jpg文件 @@ -1122,8 +1122,10 @@ public class ImgUtil { public static void compress(final File imageFile, final File outFile, final float quality) throws IORuntimeException { Img.from(imageFile).setQuality(quality).write(outFile); } + // endregion - // ---------------------------------------------------------------------------------------------------------------------- other + + // region ------ toImage /** * {@link Image} 转 {@link RenderedImage}
        @@ -1167,10 +1169,25 @@ public class ImgUtil { * @since 4.3.2 */ public static BufferedImage toBufferedImage(final Image image, final String imageType) { + return toBufferedImage(image, imageType, null); + } + + /** + * {@link Image} 转 {@link BufferedImage}
        + * 如果源图片的RGB模式与目标模式一致,则直接转换,否则重新绘制
        + * 默认的,png图片使用 {@link BufferedImage#TYPE_INT_ARGB}模式,其它使用 {@link BufferedImage#TYPE_INT_RGB} 模式 + * + * @param image {@link Image} + * @param imageType 目标图片类型,例如jpg或png等 + * @param backgroundColor 背景色{@link Color},{@code null} 表示默认背景色(黑色或者透明) + * @return {@link BufferedImage} + * @since 4.3.2 + */ + public static BufferedImage toBufferedImage(final Image image, final String imageType, final Color backgroundColor) { final int type = IMAGE_TYPE_PNG.equalsIgnoreCase(imageType) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB; - return toBufferedImage(image, type); + return toBufferedImage(image, type, backgroundColor); } /** @@ -1183,18 +1200,33 @@ public class ImgUtil { * @since 5.4.7 */ public static BufferedImage toBufferedImage(final Image image, final int imageType) { + return toBufferedImage(image, imageType, null); + } + + /** + * {@link Image} 转 {@link BufferedImage}
        + * 如果源图片的RGB模式与目标模式一致,则直接转换,否则重新绘制 + * + * @param image {@link Image} + * @param imageType 目标图片类型,{@link BufferedImage}中的常量,例如黑白等 + * @param backgroundColor 背景色{@link Color},{@code null} 表示默认背景色(黑色或者透明) + * @return {@link BufferedImage} + * @since 5.4.7 + */ + public static BufferedImage toBufferedImage(final Image image, final int imageType, final Color backgroundColor) { BufferedImage bufferedImage; if (image instanceof BufferedImage) { bufferedImage = (BufferedImage) image; if (imageType != bufferedImage.getType()) { - bufferedImage = copyImage(image, imageType); + bufferedImage = copyImage(image, imageType, backgroundColor); } return bufferedImage; } - bufferedImage = copyImage(image, imageType); + bufferedImage = copyImage(image, imageType, backgroundColor); return bufferedImage; } + // endregion /** * 将已有Image复制新的一份出来 @@ -1256,22 +1288,6 @@ public class ImgUtil { return bimage; } - /** - * 创建与当前设备颜色模式兼容的 {@link BufferedImage} - * - * @param width 宽度 - * @param height 高度 - * @param transparency 透明模式,见 {@link java.awt.Transparency} - * @return {@link BufferedImage} - * @since 5.7.13 - */ - public static BufferedImage createCompatibleImage(final int width, final int height, final int transparency) throws HeadlessException { - final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - final GraphicsDevice gs = ge.getDefaultScreenDevice(); - final GraphicsConfiguration gc = gs.getDefaultConfiguration(); - return gc.createCompatibleImage(width, height, transparency); - } - /** * 将Base64编码的图像信息转为 {@link BufferedImage} * @@ -1346,6 +1362,24 @@ public class ImgUtil { return out.toByteArray(); } + // region ----- createImage + + /** + * 创建与当前设备颜色模式兼容的 {@link BufferedImage} + * + * @param width 宽度 + * @param height 高度 + * @param transparency 透明模式,见 {@link java.awt.Transparency} + * @return {@link BufferedImage} + * @since 5.7.13 + */ + public static BufferedImage createCompatibleImage(final int width, final int height, final int transparency) { + final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice gs = ge.getDefaultScreenDevice(); + final GraphicsConfiguration gc = gs.getDefaultConfiguration(); + return gc.createCompatibleImage(width, height, transparency); + } + /** * 根据文字创建透明背景的PNG图片 * @@ -1355,7 +1389,7 @@ public class ImgUtil { * @param out 图片输出地 * @throws IORuntimeException IO异常 */ - public static void createTransparentImage(String str, Font font, Color fontColor, ImageOutputStream out) throws IORuntimeException { + public static void createTransparentImage(final String str, final Font font, final Color fontColor, final ImageOutputStream out) throws IORuntimeException { writePng(createImage(str, font, null, fontColor, BufferedImage.TYPE_INT_ARGB), out); } @@ -1409,6 +1443,7 @@ public class ImgUtil { return image; } + // endregion /** * 获取font的样式应用在str上的整个矩形 @@ -1425,6 +1460,8 @@ public class ImgUtil { false)); } + // region ----- write + /** * 写出图像为JPG格式 * @@ -1516,20 +1553,38 @@ public class ImgUtil { /** * 写出图像为指定格式 * - * @param image {@link Image} - * @param imageType 图片类型(图片扩展名) - * @param destImageStream 写出到的目标流 - * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 + * @param image {@link Image} + * @param imageType 图片类型(图片扩展名) + * @param targetImageStream 写出到的目标流 + * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 * @since 4.3.2 */ - public static boolean write(final Image image, String imageType, final ImageOutputStream destImageStream, final float quality) throws IORuntimeException { + public static boolean write(final Image image, final String imageType, final ImageOutputStream targetImageStream, + final float quality) throws IORuntimeException { + return write(image, imageType, targetImageStream, quality, null); + } + + /** + * 写出图像为指定格式 + * + * @param image {@link Image} + * @param imageType 图片类型(图片扩展名) + * @param destImageStream 写出到的目标流 + * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 + * @param backgroundColor 背景色{@link Color} + * @return 是否成功写出,如果返回false表示未找到合适的Writer + * @throws IORuntimeException IO异常 + * @since 4.3.2 + */ + public static boolean write(final Image image, String imageType, final ImageOutputStream destImageStream, + final float quality, final Color backgroundColor) throws IORuntimeException { if (StrUtil.isBlank(imageType)) { imageType = IMAGE_TYPE_JPG; } - final BufferedImage bufferedImage = toBufferedImage(image, imageType); + final BufferedImage bufferedImage = toBufferedImage(image, imageType, backgroundColor); final ImageWriter writer = getWriter(bufferedImage, imageType); return write(bufferedImage, writer, destImageStream, quality); } @@ -1598,19 +1653,45 @@ public class ImgUtil { } /** - * 获得{@link ImageReader} + * 根据给定的Image对象和格式获取对应的{@link ImageWriter},如果未找到合适的Writer,返回null * - * @param type 图片文件类型,例如 "jpeg" 或 "tiff" - * @return {@link ImageReader} + * @param img {@link Image} + * @param formatName 图片格式,例如"jpg"、"png" + * @return {@link ImageWriter} + * @since 4.3.2 */ - public static ImageReader getReader(final String type) { - final Iterator iterator = ImageIO.getImageReadersByFormatName(type); - if (iterator.hasNext()) { - return iterator.next(); - } - return null; + public static ImageWriter getWriter(final Image img, final String formatName) { + final ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(toBufferedImage(img, formatName)); + final Iterator iter = ImageIO.getImageWriters(type, formatName); + return iter.hasNext() ? iter.next() : null; } + /** + * 根据给定的图片格式或者扩展名获取{@link ImageWriter},如果未找到合适的Writer,返回null + * + * @param formatName 图片格式或扩展名,例如"jpg"、"png" + * @return {@link ImageWriter} + * @since 4.3.2 + */ + public static ImageWriter getWriter(final String formatName) { + ImageWriter writer = null; + Iterator iter = ImageIO.getImageWritersByFormatName(formatName); + if (iter.hasNext()) { + writer = iter.next(); + } + if (null == writer) { + // 尝试扩展名获取 + iter = ImageIO.getImageWritersBySuffix(formatName); + if (iter.hasNext()) { + writer = iter.next(); + } + } + return writer; + } + // endregion + + // region ----- read + /** * 从文件中读取图片,请使用绝对路径,使用相对路径会相对于ClassPath * @@ -1644,17 +1725,6 @@ public class ImgUtil { return result; } - /** - * 从URL中获取或读取图片对象 - * - * @param url URL - * @return {@link Image} - * @since 5.5.8 - */ - public static Image getImage(final URL url) { - return Toolkit.getDefaultToolkit().getImage(url); - } - /** * 从{@link Resource}中读取图片 * @@ -1732,6 +1802,34 @@ public class ImgUtil { return result; } + /** + * 获得{@link ImageReader} + * + * @param type 图片文件类型,例如 "jpeg" 或 "tiff" + * @return {@link ImageReader} + */ + public static ImageReader getReader(final String type) { + final Iterator iterator = ImageIO.getImageReadersByFormatName(type); + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + // endregion + + // region ----- getImage and getPoint + + /** + * 从URL中获取或读取图片对象 + * + * @param url URL + * @return {@link Image} + * @since 5.5.8 + */ + public static Image getImage(final URL url) { + return Toolkit.getDefaultToolkit().getImage(url); + } + /** * 获取{@link ImageOutputStream} * @@ -1801,45 +1899,6 @@ public class ImgUtil { return result; } - /** - * 根据给定的Image对象和格式获取对应的{@link ImageWriter},如果未找到合适的Writer,返回null - * - * @param img {@link Image} - * @param formatName 图片格式,例如"jpg"、"png" - * @return {@link ImageWriter} - * @since 4.3.2 - */ - public static ImageWriter getWriter(final Image img, final String formatName) { - final ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(toBufferedImage(img, formatName)); - final Iterator iter = ImageIO.getImageWriters(type, formatName); - return iter.hasNext() ? iter.next() : null; - } - - /** - * 根据给定的图片格式或者扩展名获取{@link ImageWriter},如果未找到合适的Writer,返回null - * - * @param formatName 图片格式或扩展名,例如"jpg"、"png" - * @return {@link ImageWriter} - * @since 4.3.2 - */ - public static ImageWriter getWriter(final String formatName) { - ImageWriter writer = null; - Iterator iter = ImageIO.getImageWritersByFormatName(formatName); - if (iter.hasNext()) { - writer = iter.next(); - } - if (null == writer) { - // 尝试扩展名获取 - iter = ImageIO.getImageWritersBySuffix(formatName); - if (iter.hasNext()) { - writer = iter.next(); - } - } - return writer; - } - - // -------------------------------------------------------------------------------------------------------------------- Color - /** * 获得修正后的矩形坐标位置,变为以背景中心为基准坐标(即x,y == 0,0时,处于背景正中) * @@ -1855,8 +1914,9 @@ public class ImgUtil { rectangle.y + (Math.abs(backgroundHeight - rectangle.height) / 2)// ); } + // endregion - // ------------------------------------------------------------------------------------------------------ 背景图换算 + // region ----- backgroundRemoval /** * 背景移除 @@ -1948,6 +2008,9 @@ public class ImgUtil { public static BufferedImage backgroundRemoval(final ByteArrayOutputStream outputStream, final Color override, final int tolerance) { return BackgroundRemoval.backgroundRemoval(outputStream, override, tolerance); } + // endregion + + // region ------ transform and filter /** * 图片颜色转换
        @@ -1999,4 +2062,5 @@ public class ImgUtil { return Toolkit.getDefaultToolkit().createImage( new FilteredImageSource(image.getSource(), filter)); } + // endregion } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java new file mode 100644 index 000000000..fecf0ab4c --- /dev/null +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java @@ -0,0 +1,566 @@ +package cn.hutool.swing.img; + +import cn.hutool.core.lang.builder.Builder; + +import java.awt.RenderingHints; +import java.util.HashMap; +import java.util.Map; + +/** + * 着色微调构建器 + * + * @author looly + * @since 6.0.0 + */ +public class RenderingHintsBuilder implements Builder { + private static final long serialVersionUID = 1L; + + /** + * 创建{@link RenderingHints} 构建器 + * + * @return {@code RenderingHintsBuilder} + */ + public static RenderingHintsBuilder of() { + return new RenderingHintsBuilder(); + } + + private final Map hintsMap; + + /** + * 构造 + */ + private RenderingHintsBuilder() { + // 共计10项配置 + hintsMap = new HashMap<>(10, 1); + } + + /** + * 设置是否使用抗锯齿 + * + * @param antialias 抗锯齿选项,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setAntialiasing(final Antialias antialias) { + final RenderingHints.Key key = RenderingHints.KEY_ANTIALIASING; + if (null == antialias) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, antialias.getValue()); + } + return this; + } + + /** + * 设置控制颜色着色的渲染方式 + * + * @param colorRender 颜色着色的渲染方式,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setColorRendering(final ColorRender colorRender) { + final RenderingHints.Key key = RenderingHints.KEY_COLOR_RENDERING; + if (null == colorRender) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, colorRender.getValue()); + } + return this; + } + + /** + * 设置控制如何处理抖动
        + * 抖动是用一组有限的颜色合成出一个更大范围的颜色的过程,方法是给相邻像素着色以产生不在该组颜色中的新的颜色幻觉。 + * + * @param dither 如何处理抖动,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setDithering(final Dither dither) { + final RenderingHints.Key key = RenderingHints.KEY_DITHERING; + if (null == dither) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, dither.getValue()); + } + return this; + } + + /** + * 设置字体规格 + * + * @param fractionalMetrics 字体规格,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setFractionalMetrics(final FractionalMetrics fractionalMetrics) { + final RenderingHints.Key key = RenderingHints.KEY_FRACTIONALMETRICS; + if (null == fractionalMetrics) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, fractionalMetrics.getValue()); + } + return this; + } + + /** + * 设置怎样做内插
        + * 在对一个源图像做变形时,变形后的像素很少能够恰好对应目标像素位置。
        + * 在这种情况下,每个变形后的像素的颜色值不得不由周围的像素决定。内插就是实现上述过程。 + * + * @param interpolation 内插方式,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setInterpolation(final Interpolation interpolation) { + final RenderingHints.Key key = RenderingHints.KEY_INTERPOLATION; + if (null == interpolation) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, interpolation.getValue()); + } + return this; + } + + /** + * 设置着色技术,在速度和质量之间进行权衡。 + * + * @param render 着色技术,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setRendering(final Render render) { + final RenderingHints.Key key = RenderingHints.KEY_RENDERING; + if (null == render) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, render.getValue()); + } + return this; + } + + /** + * 设置对文本着色时是否抗锯齿 + * + * @param textAntialias 文本抗锯齿方式,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setTextAntialias(final TextAntialias textAntialias) { + final RenderingHints.Key key = RenderingHints.KEY_TEXT_ANTIALIASING; + if (null == textAntialias) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, textAntialias.getValue()); + } + return this; + } + + /** + * 设置alpha合成微调 + * + * @param alphaInterpolation alpha合成微调,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setAlphaInterpolation(final AlphaInterpolation alphaInterpolation) { + final RenderingHints.Key key = RenderingHints.KEY_ALPHA_INTERPOLATION; + if (null == alphaInterpolation) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, alphaInterpolation.getValue()); + } + return this; + } + + /** + * 设置LCD文本对比呈现
        + * ,100 到 250 之间的正整数。通常,有用值的范围缩小到 140-180 + * + * @param textLCDContrast LCD文本对比呈现,100 到 250 之间的正整数 + * @return this + */ + public RenderingHintsBuilder setAlphaInterpolation(final Integer textLCDContrast) { + final RenderingHints.Key key = RenderingHints.KEY_TEXT_LCD_CONTRAST; + if (null == textLCDContrast) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, textLCDContrast); + } + return this; + } + + /** + * 设置笔划规范化控制 + * + * @param strokeControl 笔划规范化控制,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setAlphaInterpolation(final StrokeControl strokeControl) { + final RenderingHints.Key key = RenderingHints.KEY_STROKE_CONTROL; + if (null == strokeControl) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, strokeControl.getValue()); + } + return this; + } + + @Override + public RenderingHints build() { + return new RenderingHints(this.hintsMap); + } + + // region ----- enums + + /** + * 抗锯齿选项 + * + * @see RenderingHints#VALUE_ANTIALIAS_ON + * @see RenderingHints#VALUE_ANTIALIAS_OFF + * @see RenderingHints#VALUE_ANTIALIAS_DEFAULT + */ + public enum Antialias { + /** + * 使用抗锯齿 + */ + ON(RenderingHints.VALUE_ANTIALIAS_ON), + /** + * 不使用抗锯齿 + */ + OFF(RenderingHints.VALUE_ANTIALIAS_OFF), + /** + * 默认的抗锯齿 + */ + DEFAULT(RenderingHints.VALUE_ANTIALIAS_OFF); + + private final Object value; + + Antialias(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 文本抗锯齿选项 + * + * @see RenderingHints#VALUE_TEXT_ANTIALIAS_ON + * @see RenderingHints#VALUE_TEXT_ANTIALIAS_OFF + * @see RenderingHints#VALUE_TEXT_ANTIALIAS_DEFAULT + */ + public enum TextAntialias { + /** + * 使用抗锯齿呈现文本 + */ + ON(RenderingHints.VALUE_TEXT_ANTIALIAS_ON), + /** + * 不使用抗锯齿呈现文本 + */ + OFF(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF), + /** + * 使用平台默认的文本抗锯齿模式呈现文本 + */ + DEFAULT(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF), + /** + * 自动的使用字体中的信息决定是否使用抗锯齿或使用实心颜色 + */ + GASP(RenderingHints.VALUE_TEXT_ANTIALIAS_GASP), + /** + * 针对LCD显示器优化文本显示LCD_HRGB + */ + LCD_HRGB(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB), + /** + * 针对LCD显示器优化文本显示LCD_HBGR + */ + LCD_HBGR(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR), + /** + * 针对LCD显示器优化文本显示LCD_VRGB + */ + LCD_VRGB(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB), + /** + * 针对LCD显示器优化文本显示LCD_VBGR + */ + LCD_VBGR(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR); + + private final Object value; + + TextAntialias(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 颜色着色的渲染方式 + * + * @see RenderingHints#VALUE_COLOR_RENDER_SPEED + * @see RenderingHints#VALUE_COLOR_RENDER_QUALITY + * @see RenderingHints#VALUE_COLOR_RENDER_DEFAULT + */ + public enum ColorRender { + /** + * 追求速度 + */ + SPEED(RenderingHints.VALUE_COLOR_RENDER_SPEED), + /** + * 追求质量 + */ + QUALITY(RenderingHints.VALUE_COLOR_RENDER_QUALITY), + /** + * 默认渲染方式 + */ + DEFAULT(RenderingHints.VALUE_COLOR_RENDER_DEFAULT); + + private final Object value; + + ColorRender(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 着色技术 + * + * @see RenderingHints#VALUE_RENDER_SPEED + * @see RenderingHints#VALUE_RENDER_QUALITY + * @see RenderingHints#VALUE_RENDER_DEFAULT + */ + public enum Render { + /** + * 追求速度 + */ + SPEED(RenderingHints.VALUE_RENDER_SPEED), + /** + * 追求质量 + */ + QUALITY(RenderingHints.VALUE_RENDER_QUALITY), + /** + * 默认 + */ + DEFAULT(RenderingHints.VALUE_RENDER_DEFAULT); + + private final Object value; + + Render(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 控制如何处理抖动
        + * 抖动是用一组有限的颜色合成出一个更大范围的颜色的过程,方法是给相邻像素着色以产生不在该组颜色中的新的颜色幻觉。 + * + * @see RenderingHints#VALUE_DITHER_ENABLE + * @see RenderingHints#VALUE_DITHER_DISABLE + * @see RenderingHints#VALUE_DITHER_DEFAULT + */ + public enum Dither { + /** + * 抖动 + */ + ENABLE(RenderingHints.VALUE_DITHER_ENABLE), + /** + * 不抖动 + */ + DISABLE(RenderingHints.VALUE_DITHER_DISABLE), + /** + * 默认 + */ + DEFAULT(RenderingHints.VALUE_DITHER_DEFAULT); + + private final Object value; + + Dither(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 字体规格 + * + * @see RenderingHints#VALUE_FRACTIONALMETRICS_ON + * @see RenderingHints#VALUE_FRACTIONALMETRICS_OFF + * @see RenderingHints#VALUE_FRACTIONALMETRICS_DEFAULT + */ + public enum FractionalMetrics { + /** + * 启用字体规格 + */ + SPEED(RenderingHints.VALUE_FRACTIONALMETRICS_ON), + /** + * 禁用字体规格 + */ + QUALITY(RenderingHints.VALUE_FRACTIONALMETRICS_OFF), + /** + * 默认 + */ + DEFAULT(RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT); + + private final Object value; + + FractionalMetrics(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 内插
        + * 在对一个源图像做变形时,变形后的像素很少能够恰好对应目标像素位置。
        + * 在这种情况下,每个变形后的像素的颜色值不得不由周围的像素决定。内插就是实现上述过程。 + * + * @see RenderingHints#VALUE_INTERPOLATION_BICUBIC + * @see RenderingHints#VALUE_INTERPOLATION_BILINEAR + * @see RenderingHints#VALUE_INTERPOLATION_NEAREST_NEIGHBOR + */ + public enum Interpolation { + /** + * 双三次插值 + */ + BICUBIC(RenderingHints.VALUE_INTERPOLATION_BICUBIC), + /** + * 双线性插值 + */ + BILINEAR(RenderingHints.VALUE_INTERPOLATION_BILINEAR), + /** + * 最近邻插值 + */ + NEAREST_NEIGHBOR(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + + private final Object value; + + Interpolation(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * alpha合成微调 + * + * @see RenderingHints#VALUE_ALPHA_INTERPOLATION_SPEED + * @see RenderingHints#VALUE_ALPHA_INTERPOLATION_QUALITY + * @see RenderingHints#VALUE_ALPHA_INTERPOLATION_DEFAULT + */ + public enum AlphaInterpolation { + /** + * 追求速度 + */ + SPEED(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED), + /** + * 追求质量 + */ + QUALITY(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY), + /** + * 平台默认 + */ + DEFAULT(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); + + private final Object value; + + AlphaInterpolation(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + /** + * 笔划规范化控制 + * + * @see RenderingHints#VALUE_STROKE_NORMALIZE + * @see RenderingHints#VALUE_STROKE_PURE + * @see RenderingHints#VALUE_STROKE_DEFAULT + */ + public enum StrokeControl { + /** + * 追求速度 + */ + NORMALIZE(RenderingHints.VALUE_STROKE_NORMALIZE), + /** + * 追求质量 + */ + PURE(RenderingHints.VALUE_STROKE_PURE), + /** + * 平台默认 + */ + DEFAULT(RenderingHints.VALUE_STROKE_DEFAULT); + + private final Object value; + + StrokeControl(final Object value) { + this.value = value; + } + + /** + * 获取值 + * + * @return 值 + */ + public Object getValue() { + return this.value; + } + } + + + // endregion +} diff --git a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java index b57d487c3..4973c1823 100755 --- a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java +++ b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java @@ -96,4 +96,13 @@ public class ImgTest { final Image img = ImgUtil.getImage(URLUtil.getURL(file)); ImgUtil.scale(img, fileScale, 0.8f); } + + @Test + @Ignore + public void rotateWithBackgroundTest() { + Img.from(FileUtil.file("d:/test/aaa.jpg")) + .setBackgroundColor(Color.RED) + .rotate(45) + .write(FileUtil.file("d:/test/aaa45.jpg")); + } } From 4c5e127c88e46dfd8460ae59b5773f245064cfc8 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 11 Mar 2023 01:03:04 +0800 Subject: [PATCH 101/125] fix code --- .../main/java/cn/hutool/swing/img/Img.java | 9 +- .../java/cn/hutool/swing/img/ImgUtil.java | 2 +- .../swing/img/RenderingHintsBuilder.java | 95 +++++++++++-------- 3 files changed, 57 insertions(+), 49 deletions(-) diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java index 1f25d955a..d1570a778 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java @@ -613,13 +613,8 @@ public class Img implements Serializable { // 目标图像 final BufferedImage targetImg = new BufferedImage(rectangle.width, rectangle.height, getTypeInt()); - final Graphics2D graphics2d = targetImg.createGraphics(); - - // 填充背景色 - if(null != this.backgroundColor){ - graphics2d.setColor(this.backgroundColor); - graphics2d.fill(rectangle); - } + // 创建画笔并填充背景色 + final Graphics2D graphics2d = GraphicsUtil.createGraphics(targetImg, this.backgroundColor); graphics2d.setRenderingHints( RenderingHintsBuilder.of() diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index 6a30272c2..c85350f2f 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -456,7 +456,7 @@ public class ImgUtil { if (false == destDir.exists()) { FileUtil.mkdir(destDir); } else if (false == destDir.isDirectory()) { - throw new IllegalArgumentException("Destination Dir must be a Directory !"); + throw new IllegalArgumentException("Destination must be a Directory !"); } try { diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java b/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java index fecf0ab4c..fdeaa47e2 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/RenderingHintsBuilder.java @@ -1,5 +1,6 @@ package cn.hutool.swing.img; +import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.builder.Builder; import java.awt.RenderingHints; @@ -7,7 +8,19 @@ import java.util.HashMap; import java.util.Map; /** - * 着色微调构建器 + * 定义和管理键和关联值的集合构建器,提供配置包括: + *
          + *
        1. {@link RenderingHints#KEY_ANTIALIASING} 抗锯齿
        2. + *
        3. {@link RenderingHints#KEY_TEXT_ANTIALIASING} 文本抗锯齿
        4. + *
        5. {@link RenderingHints#KEY_COLOR_RENDERING} 颜色着色的渲染方式
        6. + *
        7. {@link RenderingHints#KEY_DITHERING} 抖动
        8. + *
        9. {@link RenderingHints#KEY_FRACTIONALMETRICS} 字体规格
        10. + *
        11. {@link RenderingHints#KEY_INTERPOLATION} 内插
        12. + *
        13. {@link RenderingHints#KEY_ALPHA_INTERPOLATION} alpha合成微调
        14. + *
        15. {@link RenderingHints#KEY_RENDERING} 着色
        16. + *
        17. {@link RenderingHints#KEY_STROKE_CONTROL} 笔划规范化控制
        18. + *
        19. {@link RenderingHints#KEY_TEXT_LCD_CONTRAST} LCD文本对比呈现
        20. + *
        * * @author looly * @since 6.0.0 @@ -50,6 +63,22 @@ public class RenderingHintsBuilder implements Builder { return this; } + /** + * 设置对文本着色时是否抗锯齿 + * + * @param textAntialias 文本抗锯齿方式,{@code null}表示移除此选项 + * @return this + */ + public RenderingHintsBuilder setTextAntialias(final TextAntialias textAntialias) { + final RenderingHints.Key key = RenderingHints.KEY_TEXT_ANTIALIASING; + if (null == textAntialias) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, textAntialias.getValue()); + } + return this; + } + /** * 设置控制颜色着色的渲染方式 * @@ -117,38 +146,6 @@ public class RenderingHintsBuilder implements Builder { return this; } - /** - * 设置着色技术,在速度和质量之间进行权衡。 - * - * @param render 着色技术,{@code null}表示移除此选项 - * @return this - */ - public RenderingHintsBuilder setRendering(final Render render) { - final RenderingHints.Key key = RenderingHints.KEY_RENDERING; - if (null == render) { - this.hintsMap.remove(key); - } else { - this.hintsMap.put(key, render.getValue()); - } - return this; - } - - /** - * 设置对文本着色时是否抗锯齿 - * - * @param textAntialias 文本抗锯齿方式,{@code null}表示移除此选项 - * @return this - */ - public RenderingHintsBuilder setTextAntialias(final TextAntialias textAntialias) { - final RenderingHints.Key key = RenderingHints.KEY_TEXT_ANTIALIASING; - if (null == textAntialias) { - this.hintsMap.remove(key); - } else { - this.hintsMap.put(key, textAntialias.getValue()); - } - return this; - } - /** * 设置alpha合成微调 * @@ -166,18 +163,17 @@ public class RenderingHintsBuilder implements Builder { } /** - * 设置LCD文本对比呈现
        - * ,100 到 250 之间的正整数。通常,有用值的范围缩小到 140-180 + * 设置着色技术,在速度和质量之间进行权衡。 * - * @param textLCDContrast LCD文本对比呈现,100 到 250 之间的正整数 + * @param render 着色技术,{@code null}表示移除此选项 * @return this */ - public RenderingHintsBuilder setAlphaInterpolation(final Integer textLCDContrast) { - final RenderingHints.Key key = RenderingHints.KEY_TEXT_LCD_CONTRAST; - if (null == textLCDContrast) { + public RenderingHintsBuilder setRendering(final Render render) { + final RenderingHints.Key key = RenderingHints.KEY_RENDERING; + if (null == render) { this.hintsMap.remove(key); } else { - this.hintsMap.put(key, textLCDContrast); + this.hintsMap.put(key, render.getValue()); } return this; } @@ -188,7 +184,7 @@ public class RenderingHintsBuilder implements Builder { * @param strokeControl 笔划规范化控制,{@code null}表示移除此选项 * @return this */ - public RenderingHintsBuilder setAlphaInterpolation(final StrokeControl strokeControl) { + public RenderingHintsBuilder setStrokeControl(final StrokeControl strokeControl) { final RenderingHints.Key key = RenderingHints.KEY_STROKE_CONTROL; if (null == strokeControl) { this.hintsMap.remove(key); @@ -198,6 +194,23 @@ public class RenderingHintsBuilder implements Builder { return this; } + /** + * 设置LCD文本对比呈现
        + * ,100 到 250 之间的正整数。通常,有用值的范围缩小到 140-180 + * + * @param textLCDContrast LCD文本对比呈现,100 到 250 之间的正整数 + * @return this + */ + public RenderingHintsBuilder setTextLCDContrast(final Integer textLCDContrast) { + final RenderingHints.Key key = RenderingHints.KEY_TEXT_LCD_CONTRAST; + if (null == textLCDContrast) { + this.hintsMap.remove(key); + } else { + this.hintsMap.put(key, Assert.checkBetween(textLCDContrast.intValue(), 100, 250)); + } + return this; + } + @Override public RenderingHints build() { return new RenderingHints(this.hintsMap); From 7b0f88d110caae140efcbf8cfcdac9750ff80937 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 11 Mar 2023 02:43:45 +0800 Subject: [PATCH 102/125] fix code --- .../cn/hutool/swing/img/GraphicsUtil.java | 44 ++--- .../main/java/cn/hutool/swing/img/Img.java | 15 +- .../java/cn/hutool/swing/img/ImgUtil.java | 124 +++++--------- .../java/cn/hutool/swing/img/ImgWriter.java | 151 ++++++++++++++++++ 4 files changed, 219 insertions(+), 115 deletions(-) create mode 100644 hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java index 9ba1a6c45..e090b058d 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java @@ -3,17 +3,7 @@ package cn.hutool.swing.img; import cn.hutool.core.util.ObjUtil; import cn.hutool.swing.img.color.ColorUtil; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.RenderingHints; +import java.awt.*; import java.awt.image.BufferedImage; /** @@ -34,7 +24,6 @@ public class GraphicsUtil { */ public static Graphics2D createGraphics(final BufferedImage image, final Color color) { final Graphics2D g = image.createGraphics(); - if (null != color) { // 填充背景 g.setColor(color); @@ -99,9 +88,7 @@ public class GraphicsUtil { */ public static Graphics drawString(final Graphics g, final String str, final Font font, final Color color, final int width, final int height) { // 抗锯齿 - if (g instanceof Graphics2D) { - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } + enableAntialias(g); // 创建字体 g.setFont(font); @@ -168,9 +155,7 @@ public class GraphicsUtil { */ public static Graphics drawString(final Graphics g, final String str, final Font font, final Color color, final Point point) { // 抗锯齿 - if (g instanceof Graphics2D) { - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } + enableAntialias(g); g.setFont(font); g.setColor(ObjUtil.defaultIfNull(color, Color.BLACK)); @@ -182,8 +167,8 @@ public class GraphicsUtil { /** * 绘制图片 * - * @param g 画笔 - * @param img 要绘制的图片 + * @param g 画笔 + * @param img 要绘制的图片 * @param point 绘制的位置,基于左上角 * @return 画笔对象 */ @@ -208,12 +193,27 @@ public class GraphicsUtil { /** * 设置画笔透明度 * - * @param g 画笔 + * @param g 画笔 * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 * @return 画笔 */ - public static Graphics2D setAlpha(final Graphics2D g, final float alpha){ + public static Graphics2D setAlpha(final Graphics2D g, final float alpha) { g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); return g; } + + /** + * 打开抗锯齿和文本抗锯齿 + * + * @param g {@link Graphics} + */ + private static void enableAntialias(final Graphics g) { + if (g instanceof Graphics2D) { + ((Graphics2D) g).setRenderingHints( + RenderingHintsBuilder.of() + .setAntialiasing(RenderingHintsBuilder.Antialias.ON) + .setTextAntialias(RenderingHintsBuilder.TextAntialias.ON).build() + ); + } + } } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java index d1570a778..68ba7f834 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java @@ -706,11 +706,10 @@ public class Img implements Serializable { * 结果类型设定见{@link #setTargetImageType(String)} * * @param out 写出到的目标流 - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 */ - public boolean write(final OutputStream out) throws IORuntimeException { - return write(ImgUtil.getImageOutputStream(out)); + public void write(final OutputStream out) throws IORuntimeException { + write(ImgUtil.getImageOutputStream(out)); } /** @@ -718,27 +717,25 @@ public class Img implements Serializable { * 结果类型设定见{@link #setTargetImageType(String)} * * @param targetImageStream 写出到的目标流 - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 */ - public boolean write(final ImageOutputStream targetImageStream) throws IORuntimeException { + public void write(final ImageOutputStream targetImageStream) throws IORuntimeException { Assert.notBlank(this.targetImageType, "Target image type is blank !"); Assert.notNull(targetImageStream, "Target output stream is null !"); final Image targetImage = (null == this.targetImage) ? this.srcImage : this.targetImage; Assert.notNull(targetImage, "Target image is null !"); - return ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor); + ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor); } /** * 写出图像为目标文件扩展名对应的格式 * * @param targetFile 目标文件 - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 */ - public boolean write(final File targetFile) throws IORuntimeException { + public void write(final File targetFile) throws IORuntimeException { final String formatName = FileNameUtil.extName(targetFile); if (StrUtil.isNotBlank(formatName)) { this.targetImageType = formatName; @@ -752,7 +749,7 @@ public class Img implements Serializable { ImageOutputStream out = null; try { out = ImgUtil.getImageOutputStream(targetFile); - return write(out); + write(out); } finally { IoUtil.close(out); } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index c85350f2f..b16760b21 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -10,7 +10,6 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.math.NumberUtil; import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.text.StrUtil; -import cn.hutool.core.util.ObjUtil; import javax.imageio.*; import javax.imageio.stream.ImageInputStream; @@ -502,6 +501,7 @@ public class ImgUtil { Assert.notNull(destImageFile); Assert.isFalse(srcImageFile.equals(destImageFile), "Src file is equals to dest file!"); + // 通过扩展名检查图片类型,相同类型直接复制 final String srcExtName = FileNameUtil.extName(srcImageFile); final String destExtName = FileNameUtil.extName(destImageFile); if (StrUtil.equalsIgnoreCase(srcExtName, destExtName)) { @@ -1430,15 +1430,8 @@ public class ImgUtil { // 创建图片 final BufferedImage image = new BufferedImage(width, height, imageType); - final Graphics g = image.getGraphics(); - if (null != backgroundColor) { - // 先用背景色填充整张图片,也就是背景 - g.setColor(backgroundColor); - g.fillRect(0, 0, width, height); - } - g.setColor(ObjUtil.defaultIfNull(fontColor, Color.BLACK)); - g.setFont(font);// 设置画笔字体 - g.drawString(str, 0, font.getSize());// 画出字符串 + final Graphics g = GraphicsUtil.createGraphics(image, backgroundColor); + GraphicsUtil.drawString(g, str, font, fontColor, new Point(0, font.getSize())); g.dispose(); return image; @@ -1535,6 +1528,19 @@ public class ImgUtil { write(image, imageType, getImageOutputStream(out)); } + /** + * 写出图像为目标文件扩展名对应的格式 + * + * @param image {@link Image} + * @param targetFile 目标文件 + * @throws IORuntimeException IO异常 + * @since 3.1.0 + */ + public static void write(final Image image, final File targetFile) throws IORuntimeException { + final String imageType = FileNameUtil.extName(targetFile); + ImgWriter.of(image, imageType).write(targetFile); + } + /** * 写出图像为指定格式:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
        * 此方法并不关闭流 @@ -1542,12 +1548,11 @@ public class ImgUtil { * @param image {@link Image} * @param imageType 图片类型(图片扩展名) * @param destImageStream 写出到的目标流 - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 * @since 3.1.2 */ - public static boolean write(final Image image, final String imageType, final ImageOutputStream destImageStream) throws IORuntimeException { - return write(image, imageType, destImageStream, 1); + public static void write(final Image image, final String imageType, final ImageOutputStream destImageStream) throws IORuntimeException { + write(image, imageType, destImageStream, 1); } /** @@ -1557,110 +1562,57 @@ public class ImgUtil { * @param imageType 图片类型(图片扩展名) * @param targetImageStream 写出到的目标流 * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 * @since 4.3.2 */ - public static boolean write(final Image image, final String imageType, final ImageOutputStream targetImageStream, - final float quality) throws IORuntimeException { - return write(image, imageType, targetImageStream, quality, null); + public static void write(final Image image, final String imageType, final ImageOutputStream targetImageStream, + final float quality) throws IORuntimeException { + write(image, imageType, targetImageStream, quality, null); } /** * 写出图像为指定格式 * * @param image {@link Image} - * @param imageType 图片类型(图片扩展名) + * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG) * @param destImageStream 写出到的目标流 * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 * @param backgroundColor 背景色{@link Color} - * @return 是否成功写出,如果返回false表示未找到合适的Writer * @throws IORuntimeException IO异常 * @since 4.3.2 */ - public static boolean write(final Image image, String imageType, final ImageOutputStream destImageStream, - final float quality, final Color backgroundColor) throws IORuntimeException { - if (StrUtil.isBlank(imageType)) { - imageType = IMAGE_TYPE_JPG; - } - + public static void write(final Image image, final String imageType, final ImageOutputStream destImageStream, + final float quality, final Color backgroundColor) throws IORuntimeException { final BufferedImage bufferedImage = toBufferedImage(image, imageType, backgroundColor); - final ImageWriter writer = getWriter(bufferedImage, imageType); - return write(bufferedImage, writer, destImageStream, quality); - } - - /** - * 写出图像为目标文件扩展名对应的格式 - * - * @param image {@link Image} - * @param targetFile 目标文件 - * @throws IORuntimeException IO异常 - * @since 3.1.0 - */ - public static void write(final Image image, final File targetFile) throws IORuntimeException { - FileUtil.touch(targetFile); - ImageOutputStream out = null; - try { - out = getImageOutputStream(targetFile); - write(image, FileNameUtil.extName(targetFile), out); - } finally { - IoUtil.close(out); - } + write(bufferedImage, destImageStream, quality); } /** * 通过{@link ImageWriter}写出图片到输出流 * * @param image 图片 - * @param writer {@link ImageWriter} * @param output 输出的Image流{@link ImageOutputStream} * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 - * @return 是否成功写出 * @since 4.3.2 */ - public static boolean write(final Image image, final ImageWriter writer, final ImageOutputStream output, final float quality) { - if (writer == null) { - return false; - } - - writer.setOutput(output); - final RenderedImage renderedImage = toRenderedImage(image); - // 设置质量 - ImageWriteParam imgWriteParams = null; - if (quality > 0 && quality < 1) { - imgWriteParams = writer.getDefaultWriteParam(); - if (imgWriteParams.canWriteCompressed()) { - imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); - imgWriteParams.setCompressionQuality(quality); - final ColorModel colorModel = renderedImage.getColorModel();// ColorModel.getRGBdefault(); - imgWriteParams.setDestinationType(new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16))); - } - } - - try { - if (null != imgWriteParams) { - writer.write(null, new IIOImage(renderedImage, null, null), imgWriteParams); - } else { - writer.write(renderedImage); - } - output.flush(); - } catch (final IOException e) { - throw new IORuntimeException(e); - } finally { - writer.dispose(); - } - return true; + public static void write(final Image image, final ImageOutputStream output, final float quality) { + ImgWriter.of(image, null) + .setQuality(quality) + .write(output); } /** * 根据给定的Image对象和格式获取对应的{@link ImageWriter},如果未找到合适的Writer,返回null * * @param img {@link Image} - * @param formatName 图片格式,例如"jpg"、"png" + * @param formatName 图片格式,例如"jpg"、"png",{@code null}则使用默认值"jpg" * @return {@link ImageWriter} * @since 4.3.2 */ - public static ImageWriter getWriter(final Image img, final String formatName) { + public static ImageWriter getWriter(final Image img, String formatName) { + if (null == formatName) { + formatName = IMAGE_TYPE_JPG; + } final ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(toBufferedImage(img, formatName)); final Iterator iter = ImageIO.getImageWriters(type, formatName); return iter.hasNext() ? iter.next() : null; @@ -1669,11 +1621,15 @@ public class ImgUtil { /** * 根据给定的图片格式或者扩展名获取{@link ImageWriter},如果未找到合适的Writer,返回null * - * @param formatName 图片格式或扩展名,例如"jpg"、"png" + * @param formatName 图片格式或扩展名,例如"jpg"、"png",{@code null}则使用默认值"jpg" * @return {@link ImageWriter} * @since 4.3.2 */ - public static ImageWriter getWriter(final String formatName) { + public static ImageWriter getWriter(String formatName) { + if (null == formatName) { + formatName = IMAGE_TYPE_JPG; + } + ImageWriter writer = null; Iterator iter = ImageIO.getImageWritersByFormatName(formatName); if (iter.hasNext()) { diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java new file mode 100644 index 000000000..0f07d572d --- /dev/null +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java @@ -0,0 +1,151 @@ +package cn.hutool.swing.img; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.Assert; + +import javax.imageio.IIOImage; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import java.awt.Color; +import java.awt.Image; +import java.awt.image.ColorModel; +import java.awt.image.RenderedImage; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +/** + * 图片写出封装 + */ +public class ImgWriter { + + /** + * 创建图片写出器 + * + * @param image 图片 + * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG) + * @param backgroundColor 背景色{@link Color},{@code null}表示黑色或透明 + * @return {@code ImgWriter} + */ + public static ImgWriter of(final Image image, final String imageType, final Color backgroundColor) { + return of(ImgUtil.toBufferedImage(image, imageType, backgroundColor), imageType); + } + + /** + * 创建图片写出器 + * + * @param image 图片 + * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG) + * @return {@code ImgWriter} + */ + public static ImgWriter of(final Image image, final String imageType) { + return new ImgWriter(image, imageType); + } + + private final RenderedImage image; + private final ImageWriter writer; + private ImageWriteParam writeParam; + + /** + * 构造 + * + * @param image {@link Image} + * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG) + */ + public ImgWriter(final Image image, final String imageType) { + this.image = ImgUtil.toRenderedImage(image); + this.writer = ImgUtil.getWriter(image, imageType); + } + + /** + * 设置写出质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 + * + * @param quality 写出质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 + * @return this + */ + public ImgWriter setQuality(final float quality) { + this.writeParam = buildParam(this.image, this.writer, quality); + return this; + } + + /** + * 写出图像:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
        + * 此方法并不关闭流 + * + * @param out 写出到的目标流 + * @throws IORuntimeException IO异常 + */ + public void write(final OutputStream out) throws IORuntimeException { + write(ImgUtil.getImageOutputStream(out)); + } + + /** + * 写出图像为目标文件扩展名对应的格式 + * + * @param targetFile 目标文件 + * @throws IORuntimeException IO异常 + */ + public void write(final File targetFile) throws IORuntimeException { + FileUtil.touch(targetFile); + ImageOutputStream out = null; + try { + out = ImgUtil.getImageOutputStream(targetFile); + write(out); + } finally { + IoUtil.close(out); + } + } + + /** + * 通过{@link ImageWriter}写出图片到输出流 + * + * @param output 输出的Image流{@link ImageOutputStream}, 非空 + */ + public void write(final ImageOutputStream output) { + Assert.notNull(output); + + final ImageWriter writer = this.writer; + final RenderedImage image = this.image; + writer.setOutput(output); + // 设置质量 + try { + if (null != this.writeParam) { + writer.write(null, new IIOImage(image, null, null), this.writeParam); + } else { + writer.write(image); + } + output.flush(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } finally { + writer.dispose(); + } + } + + /** + * 构建图片写出参数 + * + * @param renderedImage 图片 + * @param writer {@link ImageWriter} + * @param quality 质量,范围0~1 + * @return {@link ImageWriteParam} or {@code null} + */ + private static ImageWriteParam buildParam(final RenderedImage renderedImage, final ImageWriter writer, final float quality) { + // 设置质量 + ImageWriteParam imgWriteParams = null; + if (quality > 0 && quality < 1) { + imgWriteParams = writer.getDefaultWriteParam(); + if (imgWriteParams.canWriteCompressed()) { + imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + imgWriteParams.setCompressionQuality(quality); + final ColorModel colorModel = renderedImage.getColorModel();// ColorModel.getRGBdefault(); + imgWriteParams.setDestinationType(new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16))); + } + } + return imgWriteParams; + } +} From fb7e88515a4c255d3887b1bc47f405cb428d67cb Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 11 Mar 2023 03:00:26 +0800 Subject: [PATCH 103/125] fix code --- hutool-swing/README.md | 42 +++++++++++++++++++ .../java/cn/hutool/swing/DesktopUtil.java | 2 +- .../main/java/cn/hutool/swing/ScreenUtil.java | 3 ++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hutool-swing/README.md diff --git a/hutool-swing/README.md b/hutool-swing/README.md new file mode 100644 index 000000000..7de5d744e --- /dev/null +++ b/hutool-swing/README.md @@ -0,0 +1,42 @@ +

        + +

        +

        + 🍬A set of tools that keep Java sweet. +

        +

        + 👉 https://hutool.cn/ 👈 +

        + +## 📚Hutool-swing 模块介绍 + +`Hutool-swing`提供了swing桌面和图片多媒体相关封装,此模块大部分工具依赖于桌面环境,也要注意不同操作系统的差异。 + +------------------------------------------------------------------------------- + +## 🛠️包含内容 + +### 剪贴板(clipboard) + +提供了桌面环境下剪贴板的读取、写入和监听功能。 + +### 图片(img) + +- `ImgUtil` 提供了图片工具(旋转、灰度、裁切、缩放、描边)等功能。 +- `ImgMetaUtil` 封装`metadata-extractor`提供图片元信息读取。 +- `FontUtil` 提供字体相关工具,如字体创建等 +- `GraphicsUtil` 提供绘图相关封装,包括绘制图片、字符串等。 +- `BackgroundRemoval` 提供背景色去除功能。 +- `RenderingHintsBuilder`提供定义和管理键和关联值的集合构建器。 +- `ImgWriter` 提供图片写出封装。 +- `Img` 提供图片操作封装。 + +### 图片验证码(captcha) + +提供干扰验证码、GIF动态验证码、数字计算验证码等相关功能。 + +### 其它工具 + +- `DesktopUtil` 提供桌面相关工具,如打开文件、打开浏览器等操作 +- `RobotUtil` 提供自动化相关工具,如鼠标移动、键盘敲击、截屏等功能 +- `ScreenUtil` 提供屏幕相关工具,如截屏、获取分辨率等 \ No newline at end of file diff --git a/hutool-swing/src/main/java/cn/hutool/swing/DesktopUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/DesktopUtil.java index 986ba00f6..52ffd7641 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/DesktopUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/DesktopUtil.java @@ -93,7 +93,7 @@ public class DesktopUtil { } /** - * 使用平台默认浏览器打开指定URL地址 + * 使用平台默认邮件客户端打开邮件程序 * * @param mailAddress 邮件地址 */ diff --git a/hutool-swing/src/main/java/cn/hutool/swing/ScreenUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/ScreenUtil.java index f45f0ce79..1f129b11b 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/ScreenUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/ScreenUtil.java @@ -13,6 +13,9 @@ import java.io.File; * @since 4.1.14 */ public class ScreenUtil { + /** + * Dimension + */ public static Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); /** From d80747f9d5e511b6ec6e466f6de119dfb45e7fca Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 11 Mar 2023 19:42:04 +0800 Subject: [PATCH 104/125] fix code --- .../core/net/ssl/SSLContextBuilder.java | 1 + .../net}/ssl/TrustAnyHostnameVerifier.java | 7 +- .../cn/hutool/http/client/ClientConfig.java | 76 ++------ .../engine/httpclient4/HttpClient4Engine.java | 81 ++++++--- .../engine/httpclient5/HttpClient5Engine.java | 97 ++++++---- .../client/engine/jdk/HttpConnection.java | 16 +- .../client/engine/jdk/JdkClientEngine.java | 2 +- .../client/engine/okhttp/OkHttpEngine.java | 36 +++- .../http/ssl/AndroidSupportSSLFactory.java | 30 ---- .../http/ssl/CustomProtocolsSSLFactory.java | 24 +-- .../cn/hutool/http/ssl/DefaultSSLFactory.java | 15 -- .../main/java/cn/hutool/http/ssl/SSLInfo.java | 169 ++++++++++++++++++ .../cn/hutool/http/ssl/TrustAnySSLInfo.java | 31 ---- 13 files changed, 358 insertions(+), 227 deletions(-) rename {hutool-http/src/main/java/cn/hutool/http => hutool-core/src/main/java/cn/hutool/core/net}/ssl/TrustAnyHostnameVerifier.java (70%) delete mode 100644 hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java delete mode 100644 hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLFactory.java create mode 100755 hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java delete mode 100644 hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java diff --git a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java index 62975599f..4f8b72d9d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/ssl/SSLContextBuilder.java @@ -13,6 +13,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; + /** * {@link SSLContext}构建器,可以自定义:
        *
          diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java b/hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyHostnameVerifier.java similarity index 70% rename from hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java rename to hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyHostnameVerifier.java index e10eb6d6e..7bfc8815f 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnyHostnameVerifier.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/ssl/TrustAnyHostnameVerifier.java @@ -1,4 +1,4 @@ -package cn.hutool.http.ssl; +package cn.hutool.core.net.ssl; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; @@ -10,6 +10,11 @@ import javax.net.ssl.SSLSession; */ public class TrustAnyHostnameVerifier implements HostnameVerifier { + /** + * 单例对象 + */ + public static TrustAnyHostnameVerifier INSTANCE = new TrustAnyHostnameVerifier(); + @Override public boolean verify(final String hostname, final SSLSession session) { return true;// 直接返回true diff --git a/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java b/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java index 95fc4ea0f..2e1fcde6c 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/ClientConfig.java @@ -1,12 +1,8 @@ package cn.hutool.http.client; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.net.ssl.SSLUtil; import cn.hutool.http.HttpGlobalConfig; -import cn.hutool.http.ssl.TrustAnySSLInfo; +import cn.hutool.http.ssl.SSLInfo; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLSocketFactory; import java.net.InetSocketAddress; import java.net.Proxy; @@ -35,14 +31,7 @@ public class ClientConfig { */ private int readTimeout; - /** - * HostnameVerifier,用于HTTPS安全连接 - */ - private HostnameVerifier hostnameVerifier; - /** - * SSLSocketFactory,用于HTTPS安全连接 - */ - private SSLSocketFactory socketFactory; + private SSLInfo sslInfo; /** * 是否禁用缓存 */ @@ -58,8 +47,7 @@ public class ClientConfig { public ClientConfig() { connectionTimeout = HttpGlobalConfig.getTimeout(); readTimeout = HttpGlobalConfig.getTimeout(); - hostnameVerifier = TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER; - socketFactory = TrustAnySSLInfo.DEFAULT_SSF; + sslInfo = SSLInfo.TRUST_ANY; } /** @@ -123,34 +111,12 @@ public class ClientConfig { } /** - * 获取域名验证器 + * 获取SSLInfo * - * @return 域名验证器 + * @return SSLInfo */ - public HostnameVerifier getHostnameVerifier() { - return hostnameVerifier; - } - - /** - * 设置域名验证器
          - * 只针对HTTPS请求,如果不设置,不做验证,所有域名被信任 - * - * @param hostnameVerifier HostnameVerifier - * @return this - */ - public ClientConfig setHostnameVerifier(final HostnameVerifier hostnameVerifier) { - // 验证域 - this.hostnameVerifier = hostnameVerifier; - return this; - } - - /** - * 获取SSLSocketFactory - * - * @return SSLSocketFactory - */ - public SSLSocketFactory getSocketFactory() { - return socketFactory; + public SSLInfo getSslInfo() { + return this.sslInfo; } /** @@ -158,33 +124,11 @@ public class ClientConfig { * 只针对HTTPS请求,如果不设置,使用默认的SSLSocketFactory
          * 默认SSLSocketFactory为:SSLSocketFactoryBuilder.create().build(); * - * @param ssf SSLScketFactory + * @param sslInfo SSLInfo * @return this */ - public ClientConfig setSocketFactory(final SSLSocketFactory ssf) { - this.socketFactory = ssf; - return this; - } - - /** - * 设置HTTPS安全连接协议,只针对HTTPS请求,可以使用的协议包括:
          - * 此方法调用后{@link #setSocketFactory(SSLSocketFactory)} 将被覆盖。 - * - *
          -	 * 1. TLSv1.2
          -	 * 2. TLSv1.1
          -	 * 3. SSLv3
          -	 * ...
          -	 * 
          - * - * @param protocol 协议 - * @return this - * @see SSLUtil#createTrustAnySSLContext(String) - * @see #setSocketFactory(SSLSocketFactory) - */ - public ClientConfig setSSLProtocol(final String protocol) { - Assert.notBlank(protocol, "protocol must be not blank!"); - setSocketFactory(SSLUtil.createTrustAnySSLContext(protocol).getSocketFactory()); + public ClientConfig setSSLInfo(final SSLInfo sslInfo) { + this.sslInfo = sslInfo; return this; } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java index 571e02aca..2fe5f828e 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java @@ -10,19 +10,26 @@ import cn.hutool.http.client.ClientEngine; import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; import cn.hutool.http.client.body.HttpBody; +import cn.hutool.http.ssl.SSLInfo; import org.apache.http.Header; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicHeader; import java.io.IOException; import java.net.URI; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * Apache HttpClient5的HTTP请求引擎 @@ -38,7 +45,8 @@ public class HttpClient4Engine implements ClientEngine { /** * 构造 */ - public HttpClient4Engine() {} + public HttpClient4Engine() { + } @Override public HttpClient4Engine setConfig(final ClientConfig config) { @@ -77,33 +85,27 @@ public class HttpClient4Engine implements ClientEngine { /** * 初始化引擎 */ - private void initEngine(){ - if(null != this.engine){ + private void initEngine() { + if (null != this.engine) { return; } - RequestConfig requestConfig = null; - if(null != this.config){ - final RequestConfig.Builder builder = RequestConfig.custom(); - - final int connectionTimeout = this.config.getConnectionTimeout(); - if(connectionTimeout > 0){ - builder.setConnectTimeout(connectionTimeout); - builder.setConnectionRequestTimeout(connectionTimeout); - } - final int readTimeout = this.config.getReadTimeout(); - if(readTimeout > 0){ - builder.setSocketTimeout(readTimeout); + final HttpClientBuilder clientBuilder = HttpClients.custom(); + final ClientConfig config = this.config; + if (null != config) { + // SSL配置 + final SSLInfo sslInfo = config.getSslInfo(); + if (null != sslInfo) { + clientBuilder.setSSLSocketFactory(buildSocketFactory(sslInfo)); } - requestConfig = builder.build(); + clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); } - this.engine = HttpClients.custom() - // 设置默认头信息 - .setDefaultRequestConfig(requestConfig) - .setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())) - .build(); + // 设置默认头信息 + clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); + + this.engine = clientBuilder.build(); } /** @@ -151,4 +153,41 @@ public class HttpClient4Engine implements ClientEngine { headersMap.forEach((k, v1) -> v1.forEach((v2) -> result.add(new BasicHeader(k, v2)))); return result; } + + /** + * 支持SSL + * + * @return SSLConnectionSocketFactory + */ + private static SSLConnectionSocketFactory buildSocketFactory(final SSLInfo sslInfo) { + return new SSLConnectionSocketFactory( + sslInfo.getSslContext(), + sslInfo.getProtocols(), + null, + sslInfo.getHostnameVerifier()); + } + + /** + * 构建请求配置,包括连接请求超时和响应(读取)超时 + * + * @param config {@link ClientConfig} + * @return {@link RequestConfig} + */ + private static RequestConfig buildRequestConfig(final ClientConfig config) { + // 请求配置 + final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + + // 连接超时 + final int connectionTimeout = config.getConnectionTimeout(); + if (connectionTimeout > 0) { + requestConfigBuilder.setConnectTimeout(connectionTimeout); + requestConfigBuilder.setConnectionRequestTimeout(connectionTimeout); + } + final int readTimeout = config.getReadTimeout(); + if (readTimeout > 0) { + requestConfigBuilder.setSocketTimeout(readTimeout); + } + + return requestConfigBuilder.build(); + } } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index 33690ec10..52502214c 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -11,12 +11,14 @@ import cn.hutool.http.client.ClientEngine; import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; import cn.hutool.http.client.body.HttpBody; +import cn.hutool.http.ssl.SSLInfo; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; import org.apache.hc.core5.http.ClassicHttpRequest; @@ -45,7 +47,8 @@ public class HttpClient5Engine implements ClientEngine { /** * 构造 */ - public HttpClient5Engine() {} + public HttpClient5Engine() { + } @Override public HttpClient5Engine setConfig(final ClientConfig config) { @@ -84,47 +87,25 @@ public class HttpClient5Engine implements ClientEngine { /** * 初始化引擎 */ - private void initEngine(){ - if(null != this.engine){ + private void initEngine() { + if (null != this.engine) { return; } - // 连接配置 - final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create() - .setSslContext(SSLUtil.createTrustAnySSLContext()).build()); + final HttpClientBuilder clientBuilder = HttpClients.custom(); - // 请求配置 - RequestConfig requestConfig = null; - - if(null != this.config){ - final int connectionTimeout = this.config.getConnectionTimeout(); - if(connectionTimeout > 0){ - connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); - } - final RequestConfig.Builder builder = RequestConfig.custom(); - - if(connectionTimeout > 0){ - builder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS); - } - final int readTimeout = this.config.getReadTimeout(); - if(readTimeout > 0){ - builder.setResponseTimeout(readTimeout, TimeUnit.MILLISECONDS); - } - - requestConfig = builder.build(); + final ClientConfig config = this.config; + if (null != config) { + clientBuilder.setConnectionManager(buildConnectionManager(config)); + clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); } - final HttpClientBuilder builder = HttpClients.custom() - .setConnectionManager(connectionManagerBuilder.build()) - .setDefaultRequestConfig(requestConfig) - // 设置默认头信息 - .setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); + // 设置默认头信息 + clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); // TODO 设置代理 - this.engine = builder.build(); + this.engine = clientBuilder.build(); } /** @@ -167,4 +148,54 @@ public class HttpClient5Engine implements ClientEngine { headersMap.forEach((k, v1) -> v1.forEach((v2) -> result.add(new BasicHeader(k, v2)))); return result; } + + /** + * 构建连接管理器,包括SSL配置和连接超时配置 + * + * @param config {@link ClientConfig} + * @return {@link PoolingHttpClientConnectionManager} + */ + private static PoolingHttpClientConnectionManager buildConnectionManager(final ClientConfig config) { + final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create(); + // SSL配置 + final SSLInfo sslInfo = config.getSslInfo(); + if (null != sslInfo) { + connectionManagerBuilder.setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create() + .setTlsVersions(sslInfo.getProtocols()) + .setSslContext(sslInfo.getSslContext()) + .setHostnameVerifier(sslInfo.getHostnameVerifier()) + .build()); + } + // 连接超时配置 + final int connectionTimeout = config.getConnectionTimeout(); + if (connectionTimeout > 0) { + connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setSocketTimeout(connectionTimeout, TimeUnit.MILLISECONDS) + .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); + } + + return connectionManagerBuilder.build(); + } + + /** + * 构建请求配置,包括连接请求超时和响应(读取)超时 + * + * @param config {@link ClientConfig} + * @return {@link RequestConfig} + */ + private static RequestConfig buildRequestConfig(final ClientConfig config) { + final int connectionTimeout = config.getConnectionTimeout(); + + // 请求配置 + final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + if (connectionTimeout > 0) { + requestConfigBuilder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS); + } + final int readTimeout = config.getReadTimeout(); + if (readTimeout > 0) { + requestConfigBuilder.setResponseTimeout(readTimeout, TimeUnit.MILLISECONDS); + } + + return requestConfigBuilder.build(); + } } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java index 302046572..c03afbeb1 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java @@ -7,11 +7,9 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.http.HttpException; import cn.hutool.http.client.HeaderOperation; import cn.hutool.http.meta.Method; -import cn.hutool.http.ssl.TrustAnySSLInfo; +import cn.hutool.http.ssl.SSLInfo; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -196,23 +194,23 @@ public class HttpConnection implements HeaderOperation { } /** - * 设置https请求参数
          + * 设置https中SSL相关请求参数
          * 有些时候htts请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现,此为sun内部api,按照普通http请求处理 * - * @param hostnameVerifier 域名验证器,非https传入null - * @param ssf SSLSocketFactory,非https传入null + * @param sslInfo {@link SSLInfo} * @return this * @throws HttpException KeyManagementException和NoSuchAlgorithmException异常包装 + * @since 6.0.0 */ - public HttpConnection setHttpsInfo(final HostnameVerifier hostnameVerifier, final SSLSocketFactory ssf) throws HttpException { + public HttpConnection setSSLInfo(final SSLInfo sslInfo) throws HttpException { final HttpURLConnection conn = this.conn; if (conn instanceof HttpsURLConnection) { // Https请求 final HttpsURLConnection httpsConn = (HttpsURLConnection) conn; // 验证域 - httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(hostnameVerifier, TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER)); - httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(ssf, TrustAnySSLInfo.DEFAULT_SSF)); + httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(sslInfo.getHostnameVerifier(), SSLInfo.TRUST_ANY.getHostnameVerifier())); + httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(sslInfo.getSocketFactory(), SSLInfo.TRUST_ANY.getSocketFactory())); } return this; diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java index 0541fbf60..c079f416f 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java @@ -129,7 +129,7 @@ public class JdkClientEngine implements ClientEngine { .setConnectTimeout(config.getConnectionTimeout()) .setReadTimeout(config.getReadTimeout()) .setMethod(message.method())// - .setHttpsInfo(config.getHostnameVerifier(), config.getSocketFactory()) + .setSSLInfo(config.getSslInfo()) // 关闭JDK自动转发,采用手动转发方式 .setInstanceFollowRedirects(false) .setChunkedStreamingMode(message.isChunked() ? 4096 : -1) diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java index e3c6fbc13..0eff77c41 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java @@ -6,6 +6,7 @@ import cn.hutool.http.client.ClientConfig; import cn.hutool.http.client.ClientEngine; import cn.hutool.http.client.Request; import cn.hutool.http.client.Response; +import cn.hutool.http.ssl.SSLInfo; import okhttp3.OkHttpClient; import okhttp3.internal.http.HttpMethod; @@ -71,15 +72,34 @@ public class OkHttpEngine implements ClientEngine { return; } - final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); - final OkHttpClient.Builder builder = new OkHttpClient.Builder() - .connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS) - .readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS); + final OkHttpClient.Builder builder = new OkHttpClient.Builder(); - // 设置代理 - final Proxy proxy = config.getProxy(); - if(null != proxy){ - builder.proxy(proxy); + final ClientConfig config = this.config; + if (null != config) { + // 连接超时 + final int connectionTimeout = config.getConnectionTimeout(); + if (connectionTimeout > 0) { + builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); + } + // 读写超时 + final int readTimeout = config.getReadTimeout(); + if (readTimeout > 0) { + // 读写共用读取超时 + builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS) + .writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS); + } + + // SSL + final SSLInfo sslInfo = config.getSslInfo(); + if(null != sslInfo){ + builder.sslSocketFactory(sslInfo.getSocketFactory(), sslInfo.getTrustManager()); + } + + // 设置代理 + final Proxy proxy = config.getProxy(); + if (null != proxy) { + builder.proxy(proxy); + } } this.client = builder.build(); diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java deleted file mode 100644 index 7ae2ecf7d..000000000 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/AndroidSupportSSLFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.hutool.http.ssl; - -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.net.ssl.SSLProtocols; - -/** - * 兼容android低版本SSL连接
          - * 在测试HttpUrlConnection的时候,发现一部分手机无法连接[GithubPage] - * - *

          - * 最后发现原来是某些SSL协议没有开启 - * - * @author MikaGuraNTK - */ -public class AndroidSupportSSLFactory extends CustomProtocolsSSLFactory { - - // Android低版本不重置的话某些SSL访问就会失败 - private static final String[] protocols = { - SSLProtocols.SSLv3, SSLProtocols.TLSv1, SSLProtocols.TLSv11, SSLProtocols.TLSv12}; - - /** - * 构造 - * - * @throws IORuntimeException IO异常 - */ - public AndroidSupportSSLFactory() throws IORuntimeException { - super(protocols); - } - -} diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java index 4433c766a..d45bbeae1 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java @@ -17,68 +17,68 @@ import java.net.Socket; */ public class CustomProtocolsSSLFactory extends SSLSocketFactory { + private final SSLSocketFactory raw; private final String[] protocols; - private final SSLSocketFactory base; /** * 构造 * + * @param factory {@link SSLSocketFactory} * @param protocols 支持协议列表 - * @throws IORuntimeException IO异常 */ - public CustomProtocolsSSLFactory(final String... protocols) throws IORuntimeException { + public CustomProtocolsSSLFactory(final SSLSocketFactory factory, final String... protocols) { + this.raw = factory; this.protocols = protocols; - this.base = SSLUtil.createTrustAnySSLContext(null).getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { - return base.getDefaultCipherSuites(); + return raw.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { - return base.getSupportedCipherSuites(); + return raw.getSupportedCipherSuites(); } @Override public Socket createSocket() throws IOException { - final SSLSocket sslSocket = (SSLSocket) base.createSocket(); + final SSLSocket sslSocket = (SSLSocket) raw.createSocket(); resetProtocols(sslSocket); return sslSocket; } @Override public SSLSocket createSocket(final Socket s, final String host, final int port, final boolean autoClose) throws IOException { - final SSLSocket socket = (SSLSocket) base.createSocket(s, host, port, autoClose); + final SSLSocket socket = (SSLSocket) raw.createSocket(s, host, port, autoClose); resetProtocols(socket); return socket; } @Override public Socket createSocket(final String host, final int port) throws IOException { - final SSLSocket socket = (SSLSocket) base.createSocket(host, port); + final SSLSocket socket = (SSLSocket) raw.createSocket(host, port); resetProtocols(socket); return socket; } @Override public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort) throws IOException { - final SSLSocket socket = (SSLSocket) base.createSocket(host, port, localHost, localPort); + final SSLSocket socket = (SSLSocket) raw.createSocket(host, port, localHost, localPort); resetProtocols(socket); return socket; } @Override public Socket createSocket(final InetAddress host, final int port) throws IOException { - final SSLSocket socket = (SSLSocket) base.createSocket(host, port); + final SSLSocket socket = (SSLSocket) raw.createSocket(host, port); resetProtocols(socket); return socket; } @Override public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress, final int localPort) throws IOException { - final SSLSocket socket = (SSLSocket) base.createSocket(address, port, localAddress, localPort); + final SSLSocket socket = (SSLSocket) raw.createSocket(address, port, localAddress, localPort); resetProtocols(socket); return socket; } diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLFactory.java deleted file mode 100644 index c784b0140..000000000 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/DefaultSSLFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.hutool.http.ssl; - -/** - * 默认的SSLSocketFactory - * - * @author Looly - * @since 5.1.2 - */ -public class DefaultSSLFactory extends CustomProtocolsSSLFactory { - - /** - * 构造 - */ - public DefaultSSLFactory() {} -} diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java b/hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java new file mode 100755 index 000000000..b105e5fee --- /dev/null +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java @@ -0,0 +1,169 @@ +package cn.hutool.http.ssl; + +import cn.hutool.core.net.ssl.SSLProtocols; +import cn.hutool.core.net.ssl.SSLUtil; +import cn.hutool.core.net.ssl.TrustAnyHostnameVerifier; +import cn.hutool.core.net.ssl.TrustAnyTrustManager; +import cn.hutool.core.text.StrUtil; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +/** + * HTTP请求中SSL相关信息,包括: + *

            + *
          • {@link HostnameVerifier}
          • + *
          • {@link SSLContext}
          • + *
          • {@link X509TrustManager}
          • + *
          + * + * @author looly + * @since 6.0.0 + */ +public class SSLInfo { + + /** + * 默认{@code SSLInfo},全部为{@code null},使用客户端引擎默认配置 + */ + public static final SSLInfo DEFAULT = SSLInfo.of(); + + /** + * 信任所有的{@code SSLInfo} + */ + public static final SSLInfo TRUST_ANY = SSLInfo.of() + .setHostnameVerifier(TrustAnyHostnameVerifier.INSTANCE) + .setSslContext(SSLUtil.createTrustAnySSLContext()) + .setTrustManager(TrustAnyTrustManager.INSTANCE); + + /** + * 构建{@code SSLInfo} + * + * @return {@code SSLInfo} + */ + public static SSLInfo of() { + return new SSLInfo(); + } + + /** + * 支持的协议类型 + */ + private String[] protocols; + /** + * HostnameVerifier,用于HTTPS安全连接 + */ + private HostnameVerifier hostnameVerifier; + /** + * SSLContext,用于HTTPS安全连接 + */ + private SSLContext sslContext; + /** + * 信任管理器 + */ + private X509TrustManager trustManager; + + /** + * 构造 + */ + public SSLInfo() { + if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) { + //兼容android低版本SSL连接 + this.protocols = new String[]{ + SSLProtocols.SSLv3, + SSLProtocols.TLSv1, + SSLProtocols.TLSv11, + SSLProtocols.TLSv12}; + } + } + + /** + * 获取所有支持的协议 + * + * @return 协议列表 + */ + public String[] getProtocols() { + return protocols; + } + + /** + * 设置协议列表 + * + * @param protocols 协议列表 + * @return this + */ + public SSLInfo setProtocols(final String... protocols) { + this.protocols = protocols; + return this; + } + + /** + * 获取{@link HostnameVerifier} + * + * @return {@link HostnameVerifier} + */ + public HostnameVerifier getHostnameVerifier() { + return hostnameVerifier; + } + + /** + * 设置{@link HostnameVerifier},信任所有则使用{@link cn.hutool.core.net.ssl.TrustAnyHostnameVerifier} + * + * @param hostnameVerifier {@link HostnameVerifier} + * @return this + */ + public SSLInfo setHostnameVerifier(final HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + return this; + } + + /** + * 获取{@link SSLContext} + * + * @return {@link SSLContext} + */ + public SSLContext getSslContext() { + return sslContext; + } + + /** + * 设置{@link SSLContext},可以使用{@link cn.hutool.core.net.ssl.SSLContextBuilder}构建 + * + * @param sslContext {@link SSLContext} + * @return this + */ + public SSLInfo setSslContext(final SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + /** + * 获取{@link X509TrustManager} + * + * @return {@link X509TrustManager} + */ + public X509TrustManager getTrustManager() { + return trustManager; + } + + /** + * 设置{@link X509TrustManager},新人所有则使用{@link cn.hutool.core.net.ssl.TrustAnyTrustManager} + * + * @param trustManager {@link X509TrustManager} + * @return this + */ + public SSLInfo setTrustManager(final X509TrustManager trustManager) { + this.trustManager = trustManager; + return this; + } + + /** + * 获取{@link SSLSocketFactory} + * + * @return {@link SSLSocketFactory} + */ + public SSLSocketFactory getSocketFactory() { + final SSLSocketFactory factory = this.sslContext.getSocketFactory(); + return new CustomProtocolsSSLFactory(factory, this.protocols); + } +} diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java b/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java deleted file mode 100644 index 699c2c64a..000000000 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/TrustAnySSLInfo.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.hutool.http.ssl; - -import cn.hutool.core.text.StrUtil; - -import javax.net.ssl.SSLSocketFactory; - -/** - * 新任所有SSL配置 - * - * @author looly - */ -public class TrustAnySSLInfo { - /** - * 默认信任全部的域名校验器 - */ - public static final TrustAnyHostnameVerifier TRUST_ANY_HOSTNAME_VERIFIER; - /** - * 默认的SSLSocketFactory,区分安卓 - */ - public static final SSLSocketFactory DEFAULT_SSF; - - static { - TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier(); - if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) { - // 兼容android低版本SSL连接 - DEFAULT_SSF = new AndroidSupportSSLFactory(); - } else { - DEFAULT_SSF = new DefaultSSLFactory(); - } - } -} From d9f6de720a3e029f732eb35cbc840f0f750492d9 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 13:13:13 +0800 Subject: [PATCH 105/125] fix bug --- .../cn/hutool/poi/excel/cell/CellEditor.java | 9 +- .../cn/hutool/poi/excel/cell/CellUtil.java | 167 +++++++++++------- .../cn/hutool/poi/excel/IssueI6MBS5Test.java | 48 +++++ 3 files changed, 156 insertions(+), 68 deletions(-) create mode 100644 hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI6MBS5Test.java diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java index d17e9b9fb..f3773d771 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java @@ -5,7 +5,12 @@ import org.apache.poi.ss.usermodel.Cell; /** * 单元格编辑器接口
          * 在读取Excel值时,有时我们需要针对所有单元格统一处理结果值(如null转默认值)的情况,实现接口并调用
          - * reader.setCellEditor()设置编辑器 + * reader.setCellEditor()设置编辑器
          + * 此接口可完成以下功能: + *
            + *
          • 对单元格进行编辑,如修改样式等。
          • + *
          • 对单元格的值进行编辑,如根据单元格修改不同值,然后返回
          • + *
          * * @author Looly */ @@ -17,7 +22,7 @@ public interface CellEditor { * * @param cell 单元格对象,可以获取单元格行、列样式等信息 * @param value 单元格值 - * @return 编辑后的对象 + * @return 编辑后的值 */ Object edit(Cell cell, Object value); } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java index fc3bedd9f..3f7dc47bd 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java @@ -1,23 +1,14 @@ package cn.hutool.poi.excel.cell; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.StyleSet; +import cn.hutool.poi.excel.cell.editors.TrimEditor; import cn.hutool.poi.excel.cell.setters.CellSetterFactory; import cn.hutool.poi.excel.cell.values.ErrorCellValue; import cn.hutool.poi.excel.cell.values.NumericCellValue; -import cn.hutool.poi.excel.cell.editors.TrimEditor; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.ss.util.SheetUtil; @@ -30,6 +21,7 @@ import org.apache.poi.ss.util.SheetUtil; */ public class CellUtil { + // region ----- getCellValue /** * 获取单元格值 * @@ -128,7 +120,9 @@ public class CellUtil { return null == cellEditor ? value : cellEditor.edit(cell, value); } + // endregion + // region ----- setCellValue /** * 设置单元格值
          * 根据传入的styleSet自动匹配样式
          @@ -182,6 +176,27 @@ public class CellUtil { return; } + if (null != cellEditor) { + value = cellEditor.edit(cell, value); + } + + setCellValue(cell, value); + } + + /** + * 设置单元格值
          + * 根据传入的styleSet自动匹配样式
          + * 当为头部样式时默认赋值头部样式,但是头部中如果有数字、日期等类型,将按照数字、日期样式设置 + * + * @param cell 单元格 + * @param value 值或{@link CellSetter} + * @since 5.6.4 + */ + public static void setCellValue(final Cell cell, final Object value) { + if (null == cell) { + return; + } + // issue#1659@Github // 在使用BigWriter(SXSSF)模式写出数据时,单元格值为直接值,非引用值(is标签) // 而再使用ExcelWriter(XSSF)编辑时,会写出引用值,导致失效。 @@ -190,12 +205,11 @@ public class CellUtil { cell.setBlank(); } - if (null != cellEditor) { - value = cellEditor.edit(cell, value); - } CellSetterFactory.createCellSetter(value).setValue(cell); } + // endregion + // region ----- getCell /** * 获取单元格,如果单元格不存在,返回{@link NullCell} * @@ -233,52 +247,9 @@ public class CellUtil { } return cell; } + // endregion - /** - * 判断指定的单元格是否是合并单元格 - * - * @param sheet {@link Sheet} - * @param locationRef 单元格地址标识符,例如A11,B5 - * @return 是否是合并单元格 - * @since 5.1.5 - */ - public static boolean isMergedRegion(final Sheet sheet, final String locationRef) { - final CellLocation cellLocation = ExcelUtil.toLocation(locationRef); - return isMergedRegion(sheet, cellLocation.getX(), cellLocation.getY()); - } - - /** - * 判断指定的单元格是否是合并单元格 - * - * @param cell {@link Cell} - * @return 是否是合并单元格 - * @since 5.1.5 - */ - public static boolean isMergedRegion(final Cell cell) { - return isMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()); - } - - /** - * 判断指定的单元格是否是合并单元格 - * - * @param sheet {@link Sheet} - * @param x 列号,从0开始 - * @param y 行号,从0开始 - * @return 是否是合并单元格 - */ - public static boolean isMergedRegion(final Sheet sheet, final int x, final int y) { - final int sheetMergeCount = sheet.getNumMergedRegions(); - CellRangeAddress ca; - for (int i = 0; i < sheetMergeCount; i++) { - ca = sheet.getMergedRegion(i); - if (y >= ca.getFirstRow() && y <= ca.getLastRow() - && x >= ca.getFirstColumn() && x <= ca.getLastColumn()) { - return true; - } - } - return false; - } - + // region ----- getCellRangeAddress /** * 获取合并单元格{@link CellRangeAddress},如果不是返回null * @@ -326,7 +297,53 @@ public class CellUtil { } return null; } + // endregion + // region ----- merging 合并单元格 + /** + * 判断指定的单元格是否是合并单元格 + * + * @param sheet {@link Sheet} + * @param locationRef 单元格地址标识符,例如A11,B5 + * @return 是否是合并单元格 + * @since 5.1.5 + */ + public static boolean isMergedRegion(final Sheet sheet, final String locationRef) { + final CellLocation cellLocation = ExcelUtil.toLocation(locationRef); + return isMergedRegion(sheet, cellLocation.getX(), cellLocation.getY()); + } + + /** + * 判断指定的单元格是否是合并单元格 + * + * @param cell {@link Cell} + * @return 是否是合并单元格 + * @since 5.1.5 + */ + public static boolean isMergedRegion(final Cell cell) { + return isMergedRegion(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex()); + } + + /** + * 判断指定的单元格是否是合并单元格 + * + * @param sheet {@link Sheet} + * @param x 列号,从0开始 + * @param y 行号,从0开始 + * @return 是否是合并单元格 + */ + public static boolean isMergedRegion(final Sheet sheet, final int x, final int y) { + final int sheetMergeCount = sheet.getNumMergedRegions(); + CellRangeAddress ca; + for (int i = 0; i < sheetMergeCount; i++) { + ca = sheet.getMergedRegion(i); + if (y >= ca.getFirstRow() && y <= ca.getLastRow() + && x >= ca.getFirstColumn() && x <= ca.getLastColumn()) { + return true; + } + } + return false; + } /** * 合并单元格,可以根据设置的值来合并行和列 @@ -426,6 +443,7 @@ public class CellUtil { getCellIfMergedRegion(sheet, x, y), () -> SheetUtil.getCell(sheet, y, x)); } + // endregion /** * 为特定单元格添加批注 @@ -433,29 +451,46 @@ public class CellUtil { * @param cell 单元格 * @param commentText 批注内容 * @param commentAuthor 作者 + */ + public static void setComment(final Cell cell, final String commentText, final String commentAuthor) { + setComment(cell, commentText, commentAuthor, null); + } + + /** + * 为特定单元格添加批注 + * + * @param cell 单元格 + * @param commentText 批注内容 + * @param commentAuthor 作者,{@code null}表示无作者 * @param anchor 批注的位置、大小等信息,null表示使用默认 * @since 5.4.8 */ public static void setComment(final Cell cell, final String commentText, final String commentAuthor, ClientAnchor anchor) { final Sheet sheet = cell.getSheet(); - final Workbook wb = sheet.getWorkbook(); - final Drawing drawing = sheet.createDrawingPatriarch(); - final CreationHelper factory = wb.getCreationHelper(); + final CreationHelper factory = sheet.getWorkbook().getCreationHelper(); if (anchor == null) { anchor = factory.createClientAnchor(); + // 默认位置,在注释的单元格的右方 anchor.setCol1(cell.getColumnIndex() + 1); anchor.setCol2(cell.getColumnIndex() + 3); anchor.setRow1(cell.getRowIndex()); anchor.setRow2(cell.getRowIndex() + 2); + // 自适应 + anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); } - final Comment comment = drawing.createCellComment(anchor); + + final Comment comment = sheet.createDrawingPatriarch().createCellComment(anchor); + // https://stackoverflow.com/questions/28169011/using-sxssfapache-poi-and-adding-comment-does-not-generate-proper-excel-file + // 修正在XSSFCell中未设置地址导致错位问题 + comment.setAddress(cell.getAddress()); comment.setString(factory.createRichTextString(commentText)); - comment.setAuthor(StrUtil.emptyIfNull(commentAuthor)); + if(null != commentAuthor){ + comment.setAuthor(commentAuthor); + } cell.setCellComment(comment); } // -------------------------------------------------------------------------------------------------------------- Private method start - /** * 获取合并单元格,非合并单元格返回{@code null}
          * 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格 diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI6MBS5Test.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI6MBS5Test.java new file mode 100644 index 000000000..0527f01f9 --- /dev/null +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI6MBS5Test.java @@ -0,0 +1,48 @@ +package cn.hutool.poi.excel; + +import cn.hutool.poi.excel.cell.CellUtil; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +/** + * https://gitee.com/dromara/hutool/issues/I6MBS5
          + * 经过测试,发现BigExcelWriter中的comment会错位
          + * 修正方式见: https://stackoverflow.com/questions/28169011/using-sxssfapache-poi-and-adding-comment-does-not-generate-proper-excel-file + */ +public class IssueI6MBS5Test { + + @Test + @Ignore + public void setCommentTest() { + final ExcelWriter writer = ExcelUtil.getBigWriter("d:/test/setCommentTest.xlsx"); + final Cell cell = writer.getOrCreateCell(0, 0); + CellUtil.setCellValue(cell, "cellValue"); + CellUtil.setComment(cell, "commonText", "ascend"); + + writer.close(); + } + + @Test + @Ignore + public void setCommentTest2() { + final File file = new File("D:\\test\\CellUtilTest.xlsx"); + try (final Workbook workbook = WorkbookUtil.createBook(true)) { + final Sheet sheet = workbook.createSheet(); + final Row row = sheet.createRow(0); + final Cell cell = row.createCell(0); + CellUtil.setCellValue(cell, "cellValue"); + CellUtil.setComment(cell, "commonText", "ascend", null); + workbook.write(Files.newOutputStream(file.toPath())); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} From 3a259cdb58d5f824d2f4b35367a8f6fa7da37826 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 13:28:08 +0800 Subject: [PATCH 106/125] fix bug --- .../src/main/java/cn/hutool/core/bean/BeanUtil.java | 7 +++++-- .../src/test/java/cn/hutool/core/bean/BeanUtilTest.java | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index 971eea0c4..2a6dedea5 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -116,8 +116,11 @@ public class BeanUtil { if (ClassUtil.isNormalClass(clazz)) { for (final Method method : clazz.getMethods()) { if (method.getParameterCount() == 0) { - if (method.getName().startsWith("get") || method.getName().startsWith("is")) { - return true; + final String name = method.getName(); + if (name.startsWith("get") || name.startsWith("is")) { + if(false == "getClass".equals(name)){ + return true; + } } } } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index aef2b879d..147bb5679 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -892,4 +892,11 @@ public class BeanUtilTest { }, copyOptions); Assert.assertEquals("123", pojo.getName()); } + + @Test + public void hasGetterTest() { + // https://gitee.com/dromara/hutool/issues/I6M7Z7 + final boolean b = BeanUtil.hasGetter(Object.class); + Assert.assertFalse(b); + } } From bb89901961aa513959983d18b96c1983a3fe3a6a Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 15:04:01 +0800 Subject: [PATCH 107/125] fix code --- .../core/cache/file/AbstractFileCache.java | 2 +- .../core/classloader/JarClassLoader.java | 2 +- .../cn/hutool/core/codec/BaseN/Base62.java | 2 +- .../cn/hutool/core/codec/BaseN/Base64.java | 2 +- .../cn/hutool/core/compress/ZipReader.java | 2 +- .../java/cn/hutool/core/compress/ZipUtil.java | 2 +- .../cn/hutool/core/compress/ZipWriter.java | 2 +- .../java/cn/hutool/core/date/StopWatch.java | 2 +- .../cn/hutool/core/io/CharsetDetector.java | 1 + .../core/io/{ => file}/FileMagicNumber.java | 763 ++++++++++++------ .../cn/hutool/core/io/file/FileReader.java | 2 - .../core/io/{ => file}/FileTypeUtil.java | 37 +- .../hutool/core/io/{ => file}/FileUtil.java | 8 +- .../cn/hutool/core/io/file/FileWrapper.java | 1 - .../cn/hutool/core/io/file/FileWriter.java | 1 - .../hutool/core/io/file/LineReadWatcher.java | 1 - .../java/cn/hutool/core/io/file/Tailer.java | 1 - .../core/io/resource/ClassPathResource.java | 2 +- .../hutool/core/io/resource/FileResource.java | 2 +- .../hutool/core/io/resource/ResourceUtil.java | 2 +- .../hutool/core/io/resource/UrlResource.java | 2 +- .../core/io/resource/WebAppResource.java | 2 +- .../cn/hutool/core/io/watch/WatchMonitor.java | 2 +- .../hutool/core/net/multipart/UploadFile.java | 2 +- .../core/net/multipart/UploadFileHeader.java | 2 +- .../cn/hutool/core/reflect/ClassUtil.java | 2 +- .../java/cn/hutool/core/util/ArrayUtil.java | 32 + .../java/cn/hutool/core/util/CharsetUtil.java | 2 +- .../hutool/core/util/PrimitiveArrayUtil.java | 297 ++++++- .../java/cn/hutool/core/util/XmlUtil.java | 3 +- .../hutool/core/compress/ZipWriterTest.java | 2 +- .../core/convert/ConvertToArrayTest.java | 2 +- .../cn/hutool/core/io/FileTypeUtilTest.java | 9 + .../java/cn/hutool/core/io/FileUtilTest.java | 1 + .../java/cn/hutool/core/io/NioUtilTest.java | 1 + .../hutool/core/io/file/IssueI666HBTest.java | 1 - .../hutool/core/io/file/PathDeleterTest.java | 1 - .../cn/hutool/core/io/file/PathUtilTest.java | 1 - .../cn/hutool/core/io/file/TailerTest.java | 1 - .../core/io/resource/ResourceUtilTest.java | 2 +- .../core/thread/SimpleSchedulerTest.java | 2 +- .../cn/hutool/core/util/ArrayUtilTest.java | 32 +- .../java/cn/hutool/core/util/ZipUtilTest.java | 2 +- .../main/java/cn/hutool/crypto/KeyUtil.java | 2 +- .../cn/hutool/crypto/digest/Digester.java | 2 +- .../java/cn/hutool/crypto/digest/mac/Mac.java | 2 +- .../java/cn/hutool/crypto/PemUtilTest.java | 2 +- .../java/cn/hutool/db/PicTransferTest.java | 2 +- .../compress/archiver/SevenZArchiver.java | 2 +- .../compress/archiver/StreamArchiver.java | 2 +- .../compress/extractor/SevenZExtractor.java | 2 +- .../compress/extractor/StreamExtractor.java | 2 +- .../java/cn/hutool/extra/ftp/AbstractFtp.java | 2 +- .../main/java/cn/hutool/extra/ftp/Ftp.java | 2 +- .../main/java/cn/hutool/extra/mail/Mail.java | 2 +- .../hutool/extra/management/RuntimeInfo.java | 2 +- .../java/cn/hutool/extra/qrcode/QrConfig.java | 2 +- .../extra/servlet/JakartaServletUtil.java | 2 +- .../cn/hutool/extra/servlet/ServletUtil.java | 2 +- .../main/java/cn/hutool/extra/ssh/Sftp.java | 2 +- .../cn/hutool/extra/template/Template.java | 2 +- .../template/engine/enjoy/EnjoyEngine.java | 2 +- .../engine/freemarker/FreemarkerEngine.java | 2 +- .../engine/thymeleaf/ThymeleafEngine.java | 2 +- .../extra/template/engine/wit/WitEngine.java | 2 +- .../java/cn/hutool/extra/xml/JAXBUtil.java | 2 +- .../hutool/extra/compress/ArchiverTest.java | 2 +- .../hutool/extra/compress/ExtractorTest.java | 2 +- .../java/cn/hutool/extra/ftp/FtpTest.java | 2 +- .../java/cn/hutool/extra/mail/MailTest.java | 2 +- .../hutool/extra/qrcode/QrCodeUtilTest.java | 2 +- .../client/body/MultipartOutputStream.java | 2 +- .../hutool/http/client/body/ResponseBody.java | 2 +- .../http/server/HttpServerResponse.java | 2 +- .../hutool/http/server/action/RootAction.java | 2 +- .../java/cn/hutool/http/DownloadTest.java | 2 +- .../java/cn/hutool/http/HttpUtilTest.java | 2 +- .../test/java/cn/hutool/http/UploadTest.java | 2 +- .../hutool/http/server/SimpleServerTest.java | 2 +- .../main/java/cn/hutool/json/JSONUtil.java | 3 +- .../java/cn/hutool/json/JSONArrayTest.java | 2 +- .../java/cn/hutool/poi/csv/CsvBaseReader.java | 2 +- .../java/cn/hutool/poi/csv/CsvReader.java | 2 +- .../java/cn/hutool/poi/csv/CsvWriter.java | 2 +- .../cn/hutool/poi/excel/BigExcelWriter.java | 2 +- .../java/cn/hutool/poi/excel/ExcelReader.java | 2 +- .../java/cn/hutool/poi/excel/ExcelUtil.java | 2 +- .../java/cn/hutool/poi/excel/ExcelWriter.java | 2 +- .../cn/hutool/poi/excel/WorkbookUtil.java | 2 +- .../hutool/poi/excel/sax/ExcelSaxReader.java | 2 +- .../main/java/cn/hutool/poi/word/DocUtil.java | 2 +- .../java/cn/hutool/poi/word/Word07Writer.java | 2 +- .../java/cn/hutool/poi/csv/CsvReaderTest.java | 2 +- .../java/cn/hutool/poi/csv/CsvUtilTest.java | 2 +- .../java/cn/hutool/poi/csv/CsvWriterTest.java | 2 +- .../java/cn/hutool/poi/csv/Issue2783Test.java | 2 +- .../hutool/poi/excel/BigExcelWriteTest.java | 2 +- .../hutool/poi/excel/ExcelFileUtilTest.java | 2 +- .../cn/hutool/poi/excel/ExcelSaxReadTest.java | 2 +- .../cn/hutool/poi/excel/ExcelWriteTest.java | 2 +- .../cn/hutool/poi/excel/Issue2307Test.java | 2 +- .../cn/hutool/poi/excel/IssueI66Z6BTest.java | 2 +- .../java/cn/hutool/poi/ofd/OfdWriterTest.java | 2 +- .../cn/hutool/poi/word/WordWriterTest.java | 2 +- .../main/java/cn/hutool/setting/Setting.java | 2 +- .../java/cn/hutool/setting/SettingLoader.java | 2 +- .../java/cn/hutool/setting/dialect/Props.java | 2 +- .../cn/hutool/setting/dialect/PropsUtil.java | 1 - .../cn/hutool/setting/yaml/YamlUtilTest.java | 2 +- .../hutool/swing/captcha/AbstractCaptcha.java | 2 +- .../hutool/swing/img/BackgroundRemoval.java | 2 +- .../java/cn/hutool/swing/img/ImgUtil.java | 2 +- .../java/cn/hutool/swing/img/ImgWriter.java | 2 +- .../java/cn/hutool/swing/RobotUtilTest.java | 2 +- .../java/cn/hutool/swing/img/ImgTest.java | 4 +- .../java/cn/hutool/swing/img/ImgUtilTest.java | 2 +- 116 files changed, 1004 insertions(+), 384 deletions(-) rename hutool-core/src/main/java/cn/hutool/core/io/{ => file}/FileMagicNumber.java (65%) mode change 100755 => 100644 rename hutool-core/src/main/java/cn/hutool/core/io/{ => file}/FileTypeUtil.java (85%) rename hutool-core/src/main/java/cn/hutool/core/io/{ => file}/FileUtil.java (99%) mode change 100755 => 100644 diff --git a/hutool-core/src/main/java/cn/hutool/core/cache/file/AbstractFileCache.java b/hutool-core/src/main/java/cn/hutool/core/cache/file/AbstractFileCache.java index f8a04d6fd..427b428da 100755 --- a/hutool-core/src/main/java/cn/hutool/core/cache/file/AbstractFileCache.java +++ b/hutool-core/src/main/java/cn/hutool/core/cache/file/AbstractFileCache.java @@ -1,7 +1,7 @@ package cn.hutool.core.cache.file; import cn.hutool.core.cache.Cache; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import java.io.File; diff --git a/hutool-core/src/main/java/cn/hutool/core/classloader/JarClassLoader.java b/hutool-core/src/main/java/cn/hutool/core/classloader/JarClassLoader.java index 435bbac1d..5f0cbd9f0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/classloader/JarClassLoader.java +++ b/hutool-core/src/main/java/cn/hutool/core/classloader/JarClassLoader.java @@ -1,7 +1,7 @@ package cn.hutool.core.classloader; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.reflect.MethodUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java b/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java index 481ea51d8..ff9fdc21b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec.BaseN; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java b/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java index 9d76558c6..071ffc209 100755 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec.BaseN; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java b/hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java index 3055d8e90..36665ba1a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java +++ b/hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java @@ -1,7 +1,7 @@ package cn.hutool.core.compress; import cn.hutool.core.exceptions.ValidateException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java b/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java index 2461e57b6..4d04508f0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/compress/ZipUtil.java @@ -2,7 +2,7 @@ package cn.hutool.core.compress; import cn.hutool.core.collection.iter.EnumerationIter; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.FileNameUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java b/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java index e2d39f817..c34dd9e58 100755 --- a/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java @@ -1,6 +1,6 @@ package cn.hutool.core.compress; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.resource.Resource; diff --git a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java index cb3377766..6213e5b87 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java @@ -1,6 +1,6 @@ package cn.hutool.core.date; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; import java.text.NumberFormat; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/CharsetDetector.java b/hutool-core/src/main/java/cn/hutool/core/io/CharsetDetector.java index 615ca4814..2b52deb15 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/CharsetDetector.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/CharsetDetector.java @@ -1,6 +1,7 @@ package cn.hutool.core.io; import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.util.ArrayUtil; import java.io.File; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java old mode 100755 new mode 100644 similarity index 65% rename from hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java rename to hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java index 61c377ffd..01c22a49a --- a/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java @@ -1,4 +1,4 @@ -package cn.hutool.core.io; +package cn.hutool.core.io.file; import cn.hutool.core.util.ArrayUtil; @@ -13,25 +13,34 @@ import java.util.Objects; * @since 5.8.12 */ public enum FileMagicNumber { + /** + * 未知类型 + */ UNKNOWN(null, null) { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return false; } }, - //image start--------------------------------------------- + // region ----- image + /** + * jpeg + */ JPEG("image/jpeg", "jpg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0xff) && Objects.equals(bytes[1], (byte) 0xd8) && Objects.equals(bytes[2], (byte) 0xff); } }, + /** + * jxr + */ JXR("image/vnd.ms-photo", "jxr") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //file magic number https://www.iana.org/assignments/media-types/image/jxr return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x49) @@ -39,10 +48,13 @@ public enum FileMagicNumber { && Objects.equals(bytes[2], (byte) 0xbc); } }, + /** + * apng + */ APNG("image/apng", "apng") { @Override - public boolean match(byte[] bytes) { - boolean b = bytes.length > 8 + public boolean match(final byte[] bytes) { + final boolean b = bytes.length > 8 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x50) && Objects.equals(bytes[2], (byte) 0x4e) @@ -56,10 +68,10 @@ public enum FileMagicNumber { int i = 8; while (i < bytes.length) { try { - int dataLength = new BigInteger(1, Arrays.copyOfRange(bytes, i, i + 4)).intValue(); + final int dataLength = new BigInteger(1, Arrays.copyOfRange(bytes, i, i + 4)).intValue(); i += 4; - byte[] bytes1 = Arrays.copyOfRange(bytes, i, i + 4); - String chunkType = new String(bytes1); + final byte[] bytes1 = Arrays.copyOfRange(bytes, i, i + 4); + final String chunkType = new String(bytes1); i += 4; if (Objects.equals(chunkType, "IDAT") || Objects.equals(chunkType, "IEND")) { return false; @@ -67,7 +79,7 @@ public enum FileMagicNumber { return true; } i += dataLength + 4; - } catch (Exception e) { + } catch (final Exception e) { return false; } } @@ -75,9 +87,12 @@ public enum FileMagicNumber { return false; } }, + /** + * png + */ PNG("image/png", "png") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x50) @@ -85,34 +100,43 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x47); } }, + /** + * gif + */ GIF("image/gif", "gif") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x47) && Objects.equals(bytes[1], (byte) 0x49) && Objects.equals(bytes[2], (byte) 0x46); } }, + /** + * bmp + */ BMP("image/bmp", "bmp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x42) && Objects.equals(bytes[1], (byte) 0x4d); } }, + /** + * tiff + */ TIFF("image/tiff", "tiff") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x49) && Objects.equals(bytes[2], (byte) 0x2a) && Objects.equals(bytes[3], (byte) 0x00); - boolean flag2 = (Objects.equals(bytes[0], (byte) 0x4d) + final boolean flag2 = (Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x4d) && Objects.equals(bytes[2], (byte) 0x00) && Objects.equals(bytes[3], (byte) 0x2a)); @@ -120,10 +144,12 @@ public enum FileMagicNumber { } }, - + /** + * dwg + */ DWG("image/vnd.dwg", "dwg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 10 && Objects.equals(bytes[0], (byte) 0x41) && Objects.equals(bytes[1], (byte) 0x43) @@ -131,10 +157,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x30); } }, - + /** + * webp + */ WEBP("image/webp", "webp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[8], (byte) 0x57) && Objects.equals(bytes[9], (byte) 0x45) @@ -142,9 +170,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[11], (byte) 0x50); } }, + /** + * psd + */ PSD("image/vnd.adobe.photoshop", "psd") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x38) && Objects.equals(bytes[1], (byte) 0x42) @@ -152,9 +183,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x53); } }, + /** + * icon + */ ICO("image/x-icon", "ico") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x00) @@ -162,9 +196,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x00); } }, + /** + * xcf + */ XCF("image/x-xcf", "xcf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 9 && Objects.equals(bytes[0], (byte) 0x67) && Objects.equals(bytes[1], (byte) 0x69) @@ -178,13 +215,15 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x76); } }, - //image end----------------------------------------------- - - //audio start--------------------------------------------- + // endregion + // region ----- audio + /** + * wav + */ WAV("audio/x-wav", "wav") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x49) @@ -196,9 +235,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[11], (byte) 0x45); } }, + /** + * midi + */ MIDI("audio/midi", "midi") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x54) @@ -206,22 +248,28 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x64); } }, + /** + * mpeg-mp3 + */ MP3("audio/mpeg", "mp3") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 2) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x44) && Objects.equals(bytes[2], (byte) 0x33); - boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xFB); - boolean flag3 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF3); - boolean flag4 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF2); + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x44) && Objects.equals(bytes[2], (byte) 0x33); + final boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xFB); + final boolean flag3 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF3); + final boolean flag4 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF2); return flag1 || flag2 || flag3 || flag4; } }, + /** + * ogg + */ OGG("audio/ogg", "ogg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4f) && Objects.equals(bytes[1], (byte) 0x67) @@ -229,9 +277,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x53); } }, + /** + * flac + */ FLAC("audio/x-flac", "flac") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x66) && Objects.equals(bytes[1], (byte) 0x4c) @@ -239,9 +290,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x43); } }, + /** + * mp4 + */ M4A("audio/mp4", "m4a") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return (bytes.length > 10 && Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) @@ -256,32 +310,38 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x20)); } }, + /** + * aac + */ AAC("audio/aac", "aac") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 1) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF1); - boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF9); + final boolean flag1 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF1); + final boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF9); return flag1 || flag2; } }, + /** + * amr + */ AMR("audio/amr", "amr") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //single-channel if (bytes.length < 11) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x23) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x23) && Objects.equals(bytes[1], (byte) 0x21) && Objects.equals(bytes[2], (byte) 0x41) && Objects.equals(bytes[3], (byte) 0x4d) && Objects.equals(bytes[4], (byte) 0x52) && Objects.equals(bytes[5], (byte) 0x0A); //multi-channel: - boolean flag2 = Objects.equals(bytes[0], (byte) 0x23) + final boolean flag2 = Objects.equals(bytes[0], (byte) 0x23) && Objects.equals(bytes[1], (byte) 0x21) && Objects.equals(bytes[2], (byte) 0x41) && Objects.equals(bytes[3], (byte) 0x4d) @@ -296,17 +356,23 @@ public enum FileMagicNumber { return flag1 || flag2; } }, + /** + * ac3 + */ AC3("audio/ac3", "ac3") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x0b) && Objects.equals(bytes[1], (byte) 0x77); } }, + /** + * aiff + */ AIFF("audio/x-aiff", "aiff") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x46) && Objects.equals(bytes[1], (byte) 0x4f) @@ -318,26 +384,29 @@ public enum FileMagicNumber { && Objects.equals(bytes[11], (byte) 0x46); } }, - //audio end----------------------------------------------- + // endregion - //font start--------------------------------------------- - // The existing registration "application/font-woff" is deprecated in favor of "font/woff". + // region ----- font + /** + * woff
          + * The existing registration "application/font-woff" is deprecated in favor of "font/woff". + */ WOFF("font/woff", "woff") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) + public boolean match(final byte[] bytes) { + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) && Objects.equals(bytes[3], (byte) 0x46); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) && Objects.equals(bytes[5], (byte) 0x01) && Objects.equals(bytes[6], (byte) 0x00) && Objects.equals(bytes[7], (byte) 0x00); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) && Objects.equals(bytes[5], (byte) 0x54) && Objects.equals(bytes[6], (byte) 0x54) && Objects.equals(bytes[7], (byte) 0x4f); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); @@ -345,22 +414,25 @@ public enum FileMagicNumber { && (flag1 && (flag2 || flag3 || flag4)); } }, + /** + * woff2 + */ WOFF2("font/woff2", "woff2") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) + public boolean match(final byte[] bytes) { + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) && Objects.equals(bytes[3], (byte) 0x32); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) && Objects.equals(bytes[5], (byte) 0x01) && Objects.equals(bytes[6], (byte) 0x00) && Objects.equals(bytes[7], (byte) 0x00); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) && Objects.equals(bytes[5], (byte) 0x54) && Objects.equals(bytes[6], (byte) 0x54) && Objects.equals(bytes[7], (byte) 0x4f); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); @@ -368,9 +440,12 @@ public enum FileMagicNumber { && (flag1 && (flag2 || flag3 || flag4)); } }, + /** + * ttf + */ TTF("font/ttf", "ttf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x01) @@ -379,9 +454,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[4], (byte) 0x00); } }, + /** + * otf + */ OTF("font/otf", "otf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x4f) && Objects.equals(bytes[1], (byte) 0x54) @@ -390,13 +468,15 @@ public enum FileMagicNumber { && Objects.equals(bytes[4], (byte) 0x00); } }, + // endregion - //font end----------------------------------------------- - - //archive start----------------------------------------- + // region ----- archive + /** + * epub + */ EPUB("application/epub+zip", "epub") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 58 && Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b) && Objects.equals(bytes[2], (byte) 0x03) && Objects.equals(bytes[3], (byte) 0x04) @@ -416,21 +496,27 @@ public enum FileMagicNumber { && Objects.equals(bytes[56], (byte) 0x69) && Objects.equals(bytes[57], (byte) 0x70); } }, + /** + * zip + */ ZIP("application/zip", "zip") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b); - boolean flag2 = Objects.equals(bytes[2], (byte) 0x03) || Objects.equals(bytes[2], (byte) 0x05) || Objects.equals(bytes[2], (byte) 0x07); - boolean flag3 = Objects.equals(bytes[3], (byte) 0x04) || Objects.equals(bytes[3], (byte) 0x06) || Objects.equals(bytes[3], (byte) 0x08); + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b); + final boolean flag2 = Objects.equals(bytes[2], (byte) 0x03) || Objects.equals(bytes[2], (byte) 0x05) || Objects.equals(bytes[2], (byte) 0x07); + final boolean flag3 = Objects.equals(bytes[3], (byte) 0x04) || Objects.equals(bytes[3], (byte) 0x06) || Objects.equals(bytes[3], (byte) 0x08); return flag1 && flag2 && flag3; } }, + /** + * tar + */ TAR("application/x-tar", "tar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 261 && Objects.equals(bytes[257], (byte) 0x75) && Objects.equals(bytes[258], (byte) 0x73) @@ -439,9 +525,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[261], (byte) 0x72); } }, + /** + * rar + */ RAR("application/x-rar-compressed", "rar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x61) @@ -452,27 +541,36 @@ public enum FileMagicNumber { && (Objects.equals(bytes[6], (byte) 0x00) || Objects.equals(bytes[6], (byte) 0x01)); } }, + /** + * gz + */ GZ("application/gzip", "gz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x1f) && Objects.equals(bytes[1], (byte) 0x8b) && Objects.equals(bytes[2], (byte) 0x08); } }, + /** + * bz2 + */ BZ2("application/x-bzip2", "bz2") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x42) && Objects.equals(bytes[1], (byte) 0x5a) && Objects.equals(bytes[2], (byte) 0x68); } }, + /** + * 7z + */ SevenZ("application/x-7z-compressed", "7z") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x37) && Objects.equals(bytes[1], (byte) 0x7a) @@ -483,6 +581,9 @@ public enum FileMagicNumber { && Objects.equals(bytes[6], (byte) 0x00); } }, + /** + * pdf + */ PDF("application/pdf", "pdf") { @Override public boolean match(byte[] bytes) { @@ -498,26 +599,35 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x46); } }, + /** + * exe + */ EXE("application/x-msdownload", "exe") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x5a); } }, + /** + * swf + */ SWF("application/x-shockwave-flash", "swf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && (Objects.equals(bytes[0], 0x43) || Objects.equals(bytes[0], (byte) 0x46)) && Objects.equals(bytes[1], (byte) 0x57) && Objects.equals(bytes[2], (byte) 0x53); } }, + /** + * rtf + */ RTF("application/rtf", "rtf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x7b) && Objects.equals(bytes[1], (byte) 0x5c) @@ -526,9 +636,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[4], (byte) 0x66); } }, + /** + * nes + */ NES("application/x-nintendo-nes-rom", "nes") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4e) && Objects.equals(bytes[1], (byte) 0x45) @@ -536,9 +649,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x1a); } }, + /** + * crx + */ CRX("application/x-google-chrome-extension", "crx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x43) && Objects.equals(bytes[1], (byte) 0x72) @@ -546,30 +662,39 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x34); } }, + /** + * cab + */ CAB("application/vnd.ms-cab-compressed", "cab") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x53) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x53) && Objects.equals(bytes[2], (byte) 0x43) && Objects.equals(bytes[3], (byte) 0x46); - boolean flag2 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x53) + final boolean flag2 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x53) && Objects.equals(bytes[2], (byte) 0x63) && Objects.equals(bytes[3], (byte) 0x28); return flag1 || flag2; } }, + /** + * ps + */ PS("application/postscript", "ps") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x25) && Objects.equals(bytes[1], (byte) 0x21); } }, + /** + * xz + */ XZ("application/x-xz", "xz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 5 && Objects.equals(bytes[0], (byte) 0xFD) && Objects.equals(bytes[1], (byte) 0x37) @@ -579,9 +704,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[5], (byte) 0x00); } }, + /** + * sqlite + */ SQLITE("application/x-sqlite3", "sqlite") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 15 && Objects.equals(bytes[0], (byte) 0x53) && Objects.equals(bytes[1], (byte) 0x51) && Objects.equals(bytes[2], (byte) 0x4c) && Objects.equals(bytes[3], (byte) 0x69) @@ -593,9 +721,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[14], (byte) 0x33) && Objects.equals(bytes[15], (byte) 0x00); } }, + /** + * deb + */ DEB("application/x-deb", "deb") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 20 && Objects.equals(bytes[0], (byte) 0x21) && Objects.equals(bytes[1], (byte) 0x3c) && Objects.equals(bytes[2], (byte) 0x61) && Objects.equals(bytes[3], (byte) 0x72) @@ -610,9 +741,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[20], (byte) 0x79); } }, + /** + * ar + */ AR("application/x-unix-archive", "ar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x21) && Objects.equals(bytes[1], (byte) 0x3c) @@ -623,9 +757,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[6], (byte) 0x3e); } }, + /** + * lzo + */ LZOP("application/x-lzop", "lzo") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 7 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x4c) @@ -637,9 +774,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[7], (byte) 0x1a); } }, + /** + * lz + */ LZ("application/x-lzip", "lz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4c) && Objects.equals(bytes[1], (byte) 0x5a) @@ -647,9 +787,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x50); } }, + /** + * elf + */ ELF("application/x-executable", "elf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 52 && Objects.equals(bytes[0], (byte) 0x7f) && Objects.equals(bytes[1], (byte) 0x45) @@ -657,9 +800,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x46); } }, + /** + * lz4 + */ LZ4("application/x-lz4", "lz4") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x04) && Objects.equals(bytes[1], (byte) 0x22) @@ -667,10 +813,13 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x18); } }, - //https://github.com/madler/brotli/blob/master/br-format-v3.txt,brotli 没有固定的file magic number,所以此处只是参考 + /** + * br
          + * https://github.com/madler/brotli/blob/master/br-format-v3.txt,brotli 没有固定的file magic number,所以此处只是参考 + */ BR("application/x-brotli", "br") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0xce) && Objects.equals(bytes[1], (byte) 0xb2) @@ -678,9 +827,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x81); } }, + /** + * dcm + */ DCM("application/x-dicom", "dcm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 128 && Objects.equals(bytes[128], (byte) 0x44) && Objects.equals(bytes[129], (byte) 0x49) @@ -688,9 +840,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[131], (byte) 0x4d); } }, + /** + * rpm + */ RPM("application/x-rpm", "rpm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0xed) && Objects.equals(bytes[1], (byte) 0xab) @@ -698,15 +853,18 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0xdb); } }, + /** + * zst + */ ZSTD("application/x-zstd", "zst") { @Override - public boolean match(byte[] bytes) { - int length = bytes.length; + public boolean match(final byte[] bytes) { + final int length = bytes.length; if (length < 5) { return false; } - byte[] buf1 = new byte[]{(byte) 0x22, (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28}; - boolean flag1 = ArrayUtil.contains(buf1, bytes[0]) + final byte[] buf1 = new byte[]{(byte) 0x22, (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28}; + final boolean flag1 = ArrayUtil.contains(buf1, bytes[0]) && Objects.equals(bytes[1], (byte) 0xb5) && Objects.equals(bytes[2], (byte) 0x2f) && Objects.equals(bytes[3], (byte) 0xfd); @@ -719,15 +877,19 @@ public enum FileMagicNumber { return false; } }, - //archive end------------------------------------------------------------ - //video start------------------------------------------------------------ + // endregion + + // region ----- video + /** + * mp4 + */ MP4("video/mp4", "mp4") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 13) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -735,7 +897,7 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x53) && Objects.equals(bytes[10], (byte) 0x4e) && Objects.equals(bytes[11], (byte) 0x56); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -746,9 +908,12 @@ public enum FileMagicNumber { return flag1 || flag2; } }, + /** + * avi + */ AVI("video/x-msvideo", "avi") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x49) @@ -760,9 +925,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[11], (byte) 0x20); } }, + /** + * wmv + */ WMV("video/x-ms-wmv", "wmv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 9 && Objects.equals(bytes[0], (byte) 0x30) && Objects.equals(bytes[1], (byte) 0x26) @@ -776,13 +944,16 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0xd9); } }, + /** + * m4v + */ M4V("video/x-m4v", "m4v") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 12) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -790,7 +961,7 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x34) && Objects.equals(bytes[10], (byte) 0x56) && Objects.equals(bytes[11], (byte) 0x20); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -801,9 +972,12 @@ public enum FileMagicNumber { return flag1 || flag2; } }, + /** + * flv + */ FLV("video/x-flv", "flv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x46) && Objects.equals(bytes[1], (byte) 0x4c) @@ -811,11 +985,14 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x01); } }, + /** + * mkv + */ MKV("video/x-matroska", "mkv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //0x42 0x82 0x88 0x6d 0x61 0x74 0x72 0x6f 0x73 0x6b 0x61 - boolean flag1 = bytes.length > 11 + final boolean flag1 = bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x1a) && Objects.equals(bytes[1], (byte) 0x45) && Objects.equals(bytes[2], (byte) 0xdf) @@ -823,39 +1000,44 @@ public enum FileMagicNumber { if (flag1) { //此处需要判断是否是'\x42\x82\x88matroska',算法类似kmp判断 - byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x6d, (byte) 0x61, (byte) 0x74, (byte) 0x72, (byte) 0x6f, (byte) 0x73, (byte) 0x6b, (byte) 0x61}; - int index = FileMagicNumber.indexOf(bytes, bytes1); + final byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x6d, (byte) 0x61, (byte) 0x74, (byte) 0x72, (byte) 0x6f, (byte) 0x73, (byte) 0x6b, (byte) 0x61}; + final int index = FileMagicNumber.indexOf(bytes, bytes1); return index > 0; } return false; } }, - + /** + * webm + */ WEBM("video/webm", "webm") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = bytes.length > 8 + public boolean match(final byte[] bytes) { + final boolean flag1 = bytes.length > 8 && Objects.equals(bytes[0], (byte) 0x1a) && Objects.equals(bytes[1], (byte) 0x45) && Objects.equals(bytes[2], (byte) 0xdf) && Objects.equals(bytes[3], (byte) 0xa3); if (flag1) { //此处需要判断是否是'\x42\x82\x88webm',算法类似kmp判断 - byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x77, (byte) 0x65, (byte) 0x62, (byte) 0x6d}; - int index = FileMagicNumber.indexOf(bytes, bytes1); + final byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x77, (byte) 0x65, (byte) 0x62, (byte) 0x6d}; + final int index = FileMagicNumber.indexOf(bytes, bytes1); return index > 0; } return false; } }, - //此文件签名非常复杂,只判断常见的几种 + /** + * mov
          + * 此文件签名非常复杂,只判断常见的几种 + */ MOV("video/quicktime", "mov") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 12) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -863,36 +1045,39 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x74) && Objects.equals(bytes[10], (byte) 0x20) && Objects.equals(bytes[11], (byte) 0x20); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x6D) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x6D) && Objects.equals(bytes[5], (byte) 0x6F) && Objects.equals(bytes[6], (byte) 0x6F) && Objects.equals(bytes[7], (byte) 0x76); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x65) && Objects.equals(bytes[7], (byte) 0x65); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x6D) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x6D) && Objects.equals(bytes[5], (byte) 0x64) && Objects.equals(bytes[6], (byte) 0x61) && Objects.equals(bytes[7], (byte) 0x74); - boolean flag5 = Objects.equals(bytes[4], (byte) 0x77) + final boolean flag5 = Objects.equals(bytes[4], (byte) 0x77) && Objects.equals(bytes[5], (byte) 0x69) && Objects.equals(bytes[6], (byte) 0x64) && Objects.equals(bytes[7], (byte) 0x65); - boolean flag6 = Objects.equals(bytes[4], (byte) 0x70) + final boolean flag6 = Objects.equals(bytes[4], (byte) 0x70) && Objects.equals(bytes[5], (byte) 0x6E) && Objects.equals(bytes[6], (byte) 0x6F) && Objects.equals(bytes[7], (byte) 0x74); - boolean flag7 = Objects.equals(bytes[4], (byte) 0x73) + final boolean flag7 = Objects.equals(bytes[4], (byte) 0x73) && Objects.equals(bytes[5], (byte) 0x6B) && Objects.equals(bytes[6], (byte) 0x69) && Objects.equals(bytes[7], (byte) 0x70); return flag1 || flag2 || flag3 || flag4 || flag5 || flag6 || flag7; } }, + /** + * mpg + */ MPEG("video/mpeg", "mpg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x00) @@ -900,9 +1085,12 @@ public enum FileMagicNumber { && (bytes[3] >= (byte) 0xb0 && bytes[3] <= (byte) 0xbf); } }, + /** + * rmvb + */ RMVB("video/vnd.rn-realvideo", "rmvb") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x2E) && Objects.equals(bytes[1], (byte) 0x52) @@ -910,9 +1098,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[3], (byte) 0x46); } }, + /** + * 3gp + */ M3GP("video/3gpp", "3gp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 10 && Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) @@ -923,94 +1114,115 @@ public enum FileMagicNumber { && Objects.equals(bytes[10], (byte) 0x70); } }, - //video end --------------------------------------------------------------- - //document start ---------------------------------------------------------- + // endregion + + // region ----- document + /** + * doc + */ DOC("application/msword", "doc") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; - boolean flag1 = bytes.length > 515 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 515 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xec, (byte) 0xa5, (byte) 0xc1, (byte) 0x00}; - boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2); - byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x4d, (byte) 0x53, (byte) 0x57, (byte) 0x6f, (byte) 0x72, (byte) 0x64 + final byte[] byte2 = new byte[]{(byte) 0xec, (byte) 0xa5, (byte) 0xc1, (byte) 0x00}; + final boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2); + final byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x4d, (byte) 0x53, (byte) 0x57, (byte) 0x6f, (byte) 0x72, (byte) 0x64 , (byte) 0x44, (byte) 0x6f, (byte) 0x63, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x57, (byte) 0x6f, (byte) 0x72, (byte) 0x64, (byte) 0x2e, (byte) 0x44, (byte) 0x6f, (byte) 0x63, (byte) 0x75, (byte) 0x6d, (byte) 0x65, (byte) 0x6e, (byte) 0x74, (byte) 0x2e, (byte) 0x38, (byte) 0x00, (byte) 0xf4, (byte) 0x39, (byte) 0xb2, (byte) 0x71}; - byte[] range = Arrays.copyOfRange(bytes, 2075, 2142); - boolean flag3 = bytes.length > 2142 && FileMagicNumber.indexOf(range, byte3) > 0; + final byte[] range = Arrays.copyOfRange(bytes, 2075, 2142); + final boolean flag3 = bytes.length > 2142 && FileMagicNumber.indexOf(range, byte3) > 0; return flag2 || flag3; } return false; } }, - + /** + * xls + */ XLS("application/vnd.ms-excel", "xls") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; - boolean flag1 = bytes.length > 520 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 520 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; - boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2) && (bytes[518] == 0x00 || bytes[518] == 0x02); - byte[] byte3 = new byte[]{(byte) 0x09, (byte) 0x08, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x05, (byte) 0x00}; - boolean flag3 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 520), byte3); - byte[] byte4 = new byte[]{(byte) 0xe2, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x5c, (byte) 0x00, (byte) 0x70, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x43, (byte) 0x61, (byte) 0x6c, (byte) 0x63}; - boolean flag4 = bytes.length > 2095 && Arrays.equals(Arrays.copyOfRange(bytes, 1568, 2095), byte4); + final byte[] byte2 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + final boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2) && (bytes[518] == 0x00 || bytes[518] == 0x02); + final byte[] byte3 = new byte[]{(byte) 0x09, (byte) 0x08, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x05, (byte) 0x00}; + final boolean flag3 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 520), byte3); + final byte[] byte4 = new byte[]{(byte) 0xe2, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x5c, (byte) 0x00, (byte) 0x70, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x43, (byte) 0x61, (byte) 0x6c, (byte) 0x63}; + final boolean flag4 = bytes.length > 2095 && Arrays.equals(Arrays.copyOfRange(bytes, 1568, 2095), byte4); return flag2 || flag3 || flag4; } return false; } }, + /** + * ppt + */ PPT("application/vnd.ms-powerpoint", "ppt") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; - boolean flag1 = bytes.length > 524 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 524 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xa0, (byte) 0x46, (byte) 0x1d, (byte) 0xf0}; - byte[] byteRange = Arrays.copyOfRange(bytes, 512, 516); - boolean flag2 = Arrays.equals(byteRange, byte2); - byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x6e, (byte) 0x1e, (byte) 0xf0}; - boolean flag3 = Arrays.equals(byteRange, byte3); - byte[] byte4 = new byte[]{(byte) 0x0f, (byte) 0x00, (byte) 0xe8, (byte) 0x03}; - boolean flag4 = Arrays.equals(byteRange, byte4); - byte[] byte5 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; - boolean flag5 = Arrays.equals(byteRange, byte5) && bytes[522] == 0x00 && bytes[523] == 0x00; - byte[] byte6 = new byte[]{(byte) 0x00, (byte) 0xb9, (byte) 0x29, (byte) 0xe8, (byte) 0x11, (byte) 0x00, (byte) 0x00, (byte) 0x00, + final byte[] byte2 = new byte[]{(byte) 0xa0, (byte) 0x46, (byte) 0x1d, (byte) 0xf0}; + final byte[] byteRange = Arrays.copyOfRange(bytes, 512, 516); + final boolean flag2 = Arrays.equals(byteRange, byte2); + final byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x6e, (byte) 0x1e, (byte) 0xf0}; + final boolean flag3 = Arrays.equals(byteRange, byte3); + final byte[] byte4 = new byte[]{(byte) 0x0f, (byte) 0x00, (byte) 0xe8, (byte) 0x03}; + final boolean flag4 = Arrays.equals(byteRange, byte4); + final byte[] byte5 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + final boolean flag5 = Arrays.equals(byteRange, byte5) && bytes[522] == 0x00 && bytes[523] == 0x00; + final byte[] byte6 = new byte[]{(byte) 0x00, (byte) 0xb9, (byte) 0x29, (byte) 0xe8, (byte) 0x11, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x4d, (byte) 0x53, (byte) 0x20, (byte) 0x50, (byte) 0x6f, (byte) 0x77, (byte) 0x65, (byte) 0x72, (byte) 0x50, (byte) 0x6f, (byte) 0x69, (byte) 0x6e, (byte) 0x74, (byte) 0x20, (byte) 0x39, (byte) 0x37}; - boolean flag6 = bytes.length > 2096 && Arrays.equals(Arrays.copyOfRange(bytes, 2072, 2096), byte6); + final boolean flag6 = bytes.length > 2096 && Arrays.equals(Arrays.copyOfRange(bytes, 2072, 2096), byte6); return flag2 || flag3 || flag4 || flag5 || flag6; } return false; } }, + /** + * docx + */ DOCX("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), DOCX); } }, + /** + * pptx + */ PPTX("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), PPTX); } }, + /** + * xlsx + */ XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), XLSX); } }, + // endregion - //document end ------------------------------------------------------------ - //other start ------------------------------------------------------------- + // region ----- others + /** + * wasm + */ WASM("application/wasm", "wasm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 7 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x61) @@ -1022,10 +1234,13 @@ public enum FileMagicNumber { && Objects.equals(bytes[7], (byte) 0x00); } }, - // https://source.android.com/devices/tech/dalvik/dex-format#dex-file-magic + /** + * dex
          + * https://source.android.com/devices/tech/dalvik/dex-format#dex-file-magic + */ DEX("application/vnd.android.dex", "dex") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 36 && Objects.equals(bytes[0], (byte) 0x64) && Objects.equals(bytes[1], (byte) 0x65) @@ -1034,9 +1249,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[36], (byte) 0x70); } }, + /** + * dey + */ DEY("application/vnd.android.dey", "dey") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 100 && Objects.equals(bytes[0], (byte) 0x64) && Objects.equals(bytes[1], (byte) 0x65) @@ -1045,113 +1263,172 @@ public enum FileMagicNumber { DEX.match(Arrays.copyOfRange(bytes, 40, 100)); } }, + /** + * eml + */ EML("message/rfc822", "eml") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 8) { return false; } - byte[] byte1 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x20, (byte) 0x20}; - byte[] byte2 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x3F, (byte) 0x3F, (byte) 0x3F}; - byte[] byte3 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x3A, (byte) 0x20}; - byte[] byte4 = new byte[]{(byte) 0x52, (byte) 0x65, (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x2D, (byte) 0x50, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x3A, (byte) 0x20}; + final byte[] byte1 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x20, (byte) 0x20}; + final byte[] byte2 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x3F, (byte) 0x3F, (byte) 0x3F}; + final byte[] byte3 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x3A, (byte) 0x20}; + final byte[] byte4 = new byte[]{(byte) 0x52, (byte) 0x65, (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x2D, (byte) 0x50, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x3A, (byte) 0x20}; return Arrays.equals(Arrays.copyOfRange(bytes, 0, 7), byte1) || Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte2) || Arrays.equals(Arrays.copyOfRange(bytes, 0, 6), byte3) || bytes.length > 13 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 13), byte4); } }, + /** + * mdb + */ MDB("application/vnd.ms-access", "mdb") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x6E, (byte) 0x64, + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x6E, (byte) 0x64, (byte) 0x61, (byte) 0x72, (byte) 0x64, (byte) 0x20, (byte) 0x4A, (byte) 0x65, (byte) 0x74, (byte) 0x20, (byte) 0x44, (byte) 0x42}; return bytes.length > 18 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 18), byte1); } }, - //CHM 49 54 53 46 + /** + * CHM 49 54 53 46 + */ CHM("application/vnd.ms-htmlhelp", "chm") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x49, (byte) 0x54, (byte) 0x53, (byte) 0x46}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x49, (byte) 0x54, (byte) 0x53, (byte) 0x46}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, - //class CA FE BA BE + + /** + * class CA FE BA BE + */ CLASS("application/java-vm", "class") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, - //torrent 64 38 3A 61 6E 6E 6F 75 6E 63 65 + /** + * torrent 64 38 3A 61 6E 6E 6F 75 6E 63 65 + */ TORRENT("application/x-bittorrent", "torrent") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x64, (byte) 0x38, (byte) 0x3A, (byte) 0x61, (byte) 0x6E, (byte) 0x6E, (byte) 0x6F, (byte) 0x75, (byte) 0x6E, (byte) 0x63, (byte) 0x65}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x64, (byte) 0x38, (byte) 0x3A, (byte) 0x61, (byte) 0x6E, (byte) 0x6E, (byte) 0x6F, (byte) 0x75, (byte) 0x6E, (byte) 0x63, (byte) 0x65}; return bytes.length > 11 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 11), byte1); } }, + /** + * wpd + */ WPD("application/vnd.wordperfect", "wpd") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xFF, (byte) 0x57, (byte) 0x50, (byte) 0x43}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xFF, (byte) 0x57, (byte) 0x50, (byte) 0x43}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, + /** + * dbx + */ DBX("", "dbx") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xCF, (byte) 0xAD, (byte) 0x12, (byte) 0xFE}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xCF, (byte) 0xAD, (byte) 0x12, (byte) 0xFE}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, + /** + * pst + */ PST("application/vnd.ms-outlook-pst", "pst") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x21, (byte) 0x42, (byte) 0x44, (byte) 0x4E}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x21, (byte) 0x42, (byte) 0x44, (byte) 0x4E}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, + /** + * ram + */ RAM("audio/x-pn-realaudio", "ram") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x2E, (byte) 0x72, (byte) 0x61, (byte) 0xFD, (byte) 0x00}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x2E, (byte) 0x72, (byte) 0x61, (byte) 0xFD, (byte) 0x00}; return bytes.length > 5 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 5), byte1); } } - //other end --------------------------------------------------------------- + // endregion ; - private final String mimeType; - private final String extension; - FileMagicNumber(String mimeType, String extension) { - this.mimeType = mimeType; - this.extension = extension; - } - - public static FileMagicNumber getMagicNumber(byte[] bytes) { - FileMagicNumber number = Arrays.stream(values()) + /** + * 根据给定的bytes,获取对应识别到的{@code FileMagicNumber} + * + * @param bytes bytes魔数 + * @return {@code FileMagicNumber} + */ + public static FileMagicNumber getMagicNumber(final byte[] bytes) { + final FileMagicNumber number = Arrays.stream(values()) .filter(fileMagicNumber -> fileMagicNumber.match(bytes)) .findFirst() .orElse(UNKNOWN); - if (number.equals(FileMagicNumber.ZIP)) { - FileMagicNumber fn = FileMagicNumber.matchDocument(bytes); + + // 压缩文档类型,如office或jar等 + if (FileMagicNumber.ZIP.equals(number)) { + final FileMagicNumber fn = FileMagicNumber.matchDocument(bytes); return fn == UNKNOWN ? ZIP : fn; } return number; } + private final String mimeType; + private final String extension; + + /** + * 构造 + * + * @param mimeType 媒体类型 + * @param extension 扩展名 + */ + FileMagicNumber(final String mimeType, final String extension) { + this.mimeType = mimeType; + this.extension = extension; + } + + /** + * 获取媒体类型 + * + * @return 媒体类型 + */ public String getMimeType() { return mimeType; } + /** + * 获取扩展名 + * + * @return 扩展名 + */ public String getExtension() { return extension; } - private static int indexOf(byte[] array, byte[] target) { + /** + * 是否匹配bytes + * + * @param bytes bytes + * @return 是否匹配 + */ + public abstract boolean match(byte[] bytes); + + // region ----- private static methods + private static int indexOf(final byte[] array, final byte[] target) { if (array == null || target == null || array.length < target.length) { return -1; } @@ -1172,19 +1449,26 @@ public enum FileMagicNumber { } //处理 Open XML 类型的文件 - private static boolean compareBytes(byte[] buf, byte[] slice, int startOffset) { - int sl = slice.length; + private static boolean compareBytes(final byte[] buf, final byte[] slice, final int startOffset) { + final int sl = slice.length; if (startOffset + sl > buf.length) { return false; } - byte[] sub = Arrays.copyOfRange(buf, startOffset, startOffset + sl); + final byte[] sub = Arrays.copyOfRange(buf, startOffset, startOffset + sl); return Arrays.equals(sub, slice); } - private static FileMagicNumber matchOpenXmlMime(byte[] bytes, int offset) { - byte[] word = new byte[]{'w', 'o', 'r', 'd', '/'}; - byte[] ppt = new byte[]{'p', 'p', 't', '/'}; - byte[] xl = new byte[]{'x', 'l', '/'}; + /** + * 判断OpenXML文档类型 + * + * @param bytes bytes魔数 + * @param offset 偏移 + * @return {@code FileMagicNumber} + */ + private static FileMagicNumber matchOpenXmlMime(final byte[] bytes, final int offset) { + final byte[] word = new byte[]{'w', 'o', 'r', 'd', '/'}; + final byte[] ppt = new byte[]{'p', 'p', 't', '/'}; + final byte[] xl = new byte[]{'x', 'l', '/'}; if (FileMagicNumber.compareBytes(bytes, word, offset)) { return FileMagicNumber.DOCX; } @@ -1197,17 +1481,23 @@ public enum FileMagicNumber { return FileMagicNumber.UNKNOWN; } - private static FileMagicNumber matchDocument(byte[] bytes) { - FileMagicNumber fileMagicNumber = FileMagicNumber.matchOpenXmlMime(bytes, (byte) 0x1e); + /** + * 匹配文档类型 + * + * @param bytes bytes魔数 + * @return 匹配到的文档类型 + */ + private static FileMagicNumber matchDocument(final byte[] bytes) { + final FileMagicNumber fileMagicNumber = FileMagicNumber.matchOpenXmlMime(bytes, (byte) 0x1e); if (false == fileMagicNumber.equals(UNKNOWN)) { return fileMagicNumber; } - byte[] bytes1 = new byte[]{0x5B, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x5F, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5D, 0x2E, 0x78, 0x6D, 0x6C}; - byte[] bytes2 = new byte[]{0x5F, 0x72, 0x65, 0x6C, 0x73, 0x2F, 0x2E, 0x72, 0x65, 0x6C, 0x73}; - byte[] bytes3 = new byte[]{0x64, 0x6F, 0x63, 0x50, 0x72, 0x6F, 0x70, 0x73}; - boolean flag1 = FileMagicNumber.compareBytes(bytes, bytes1, (byte) 0x1e); - boolean flag2 = FileMagicNumber.compareBytes(bytes, bytes2, (byte) 0x1e); - boolean flag3 = FileMagicNumber.compareBytes(bytes, bytes3, (byte) 0x1e); + final byte[] bytes1 = new byte[]{0x5B, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x5F, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5D, 0x2E, 0x78, 0x6D, 0x6C}; + final byte[] bytes2 = new byte[]{0x5F, 0x72, 0x65, 0x6C, 0x73, 0x2F, 0x2E, 0x72, 0x65, 0x6C, 0x73}; + final byte[] bytes3 = new byte[]{0x64, 0x6F, 0x63, 0x50, 0x72, 0x6F, 0x70, 0x73}; + final boolean flag1 = FileMagicNumber.compareBytes(bytes, bytes1, (byte) 0x1e); + final boolean flag2 = FileMagicNumber.compareBytes(bytes, bytes2, (byte) 0x1e); + final boolean flag3 = FileMagicNumber.compareBytes(bytes, bytes3, (byte) 0x1e); if (false == (flag1 || flag2 || flag3)) { return UNKNOWN; } @@ -1217,7 +1507,7 @@ public enum FileMagicNumber { if (index == -1) { continue; } - FileMagicNumber fn = FileMagicNumber.matchOpenXmlMime(bytes, index + 30); + final FileMagicNumber fn = FileMagicNumber.matchOpenXmlMime(bytes, index + 30); if (false == fn.equals(UNKNOWN)) { return fn; } @@ -1225,19 +1515,26 @@ public enum FileMagicNumber { return UNKNOWN; } - private static int searchSignature(byte[] bytes, int start, int rangeNum) { - byte[] signature = new byte[]{0x50, 0x4B, 0x03, 0x04}; - int length = bytes.length; + /** + * 查找文档签名(文档标识) + * + * @param bytes bytes + * @param start 开始位置 + * @param rangeNum 步进长度 + * @return 签名 + */ + @SuppressWarnings("SameParameterValue") + private static int searchSignature(final byte[] bytes, final int start, final int rangeNum) { + final byte[] signature = new byte[]{0x50, 0x4B, 0x03, 0x04}; + final int length = bytes.length; int end = start + rangeNum; if (end > length) { end = length; } - int index = FileMagicNumber.indexOf(Arrays.copyOfRange(bytes, start, end), signature); + final int index = FileMagicNumber.indexOf(Arrays.copyOfRange(bytes, start, end), signature); return (index == -1) ? -1 : (start + index); } - - public abstract boolean match(byte[] bytes); - + // endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java index 5590b81f7..f82e9e260 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java @@ -1,7 +1,6 @@ package cn.hutool.core.io.file; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.func.SerConsumer; @@ -19,7 +18,6 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.function.Function; /** * 文件读取器 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileTypeUtil.java similarity index 85% rename from hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java rename to hutool-core/src/main/java/cn/hutool/core/io/file/FileTypeUtil.java index 1be5c63a8..04a7803ff 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileTypeUtil.java @@ -1,7 +1,8 @@ -package cn.hutool.core.io; +package cn.hutool.core.io.file; import cn.hutool.core.codec.HexUtil; -import cn.hutool.core.io.file.FileNameUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; import java.io.File; @@ -32,7 +33,7 @@ public class FileTypeUtil { * @param extName 文件扩展名 * @return 之前已经存在的文件扩展名 */ - public static String putFileType(String fileStreamHexHead, String extName) { + public static String putFileType(final String fileStreamHexHead, final String extName) { return FILE_TYPE_MAP.put(fileStreamHexHead, extName); } @@ -42,7 +43,7 @@ public class FileTypeUtil { * @param fileStreamHexHead 文件流头部Hex信息 * @return 移除的文件扩展名 */ - public static String removeFileType(String fileStreamHexHead) { + public static String removeFileType(final String fileStreamHexHead) { return FILE_TYPE_MAP.remove(fileStreamHexHead); } @@ -52,13 +53,13 @@ public class FileTypeUtil { * @param fileStreamHexHead 文件流头部16进制字符串 * @return 文件类型,未找到为{@code null} */ - public static String getType(String fileStreamHexHead) { - for (Entry fileTypeEntry : FILE_TYPE_MAP.entrySet()) { + public static String getType(final String fileStreamHexHead) { + for (final Entry fileTypeEntry : FILE_TYPE_MAP.entrySet()) { if (StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) { return fileTypeEntry.getValue(); } } - byte[] bytes = (HexUtil.decodeHex(fileStreamHexHead)); + final byte[] bytes = (HexUtil.decodeHex(fileStreamHexHead)); return FileMagicNumber.getMagicNumber(bytes).getExtension(); } @@ -68,8 +69,9 @@ public class FileTypeUtil { * @param in 文件流 * @param fileHeadSize 自定义读取文件头部的大小 * @return 文件类型,未找到为{@code null} + * @throws IORuntimeException IO异常 */ - public static String getType(InputStream in,int fileHeadSize) throws IORuntimeException { + public static String getType(final InputStream in, final int fileHeadSize) throws IORuntimeException { return getType((IoUtil.readHex(in, fileHeadSize,false))); } @@ -82,7 +84,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取流引起的异常 */ - public static String getType(InputStream in,boolean isExact) throws IORuntimeException { + public static String getType(final InputStream in, final boolean isExact) throws IORuntimeException { return isExact ?getType(readHex8192Upper(in)) :getType(readHex64Upper(in)); @@ -96,7 +98,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取流引起的异常 */ - public static String getType(InputStream in) throws IORuntimeException { + public static String getType(final InputStream in) throws IORuntimeException { return getType(in,false); } @@ -116,7 +118,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取流引起的异常 */ - public static String getType(InputStream in, String filename) throws IORuntimeException { + public static String getType(final InputStream in, final String filename) throws IORuntimeException { return getType(in,filename,false); } @@ -136,7 +138,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取流引起的异常 */ - public static String getType(InputStream in, String filename,boolean isExact) throws IORuntimeException { + public static String getType(final InputStream in, final String filename, final boolean isExact) throws IORuntimeException { String typeName = getType(in,isExact); if (null == typeName) { // 未成功识别类型,扩展名辅助识别 @@ -193,7 +195,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取文件引起的异常 */ - public static String getType(File file,boolean isExact) throws IORuntimeException { + public static String getType(final File file, final boolean isExact) throws IORuntimeException { InputStream in = null; try { in = IoUtil.toStream(file); @@ -216,7 +218,7 @@ public class FileTypeUtil { * @return 类型,文件的扩展名,未找到为{@code null} * @throws IORuntimeException 读取文件引起的异常 */ - public static String getType(File file) throws IORuntimeException { + public static String getType(final File file) throws IORuntimeException { return getType(file,false); } @@ -228,7 +230,7 @@ public class FileTypeUtil { * @return 类型 * @throws IORuntimeException 读取文件引起的异常 */ - public static String getTypeByPath(String path,boolean isExact) throws IORuntimeException { + public static String getTypeByPath(final String path, final boolean isExact) throws IORuntimeException { return getType(FileUtil.file(path),isExact); } @@ -239,7 +241,7 @@ public class FileTypeUtil { * @return 类型 * @throws IORuntimeException 读取文件引起的异常 */ - public static String getTypeByPath(String path) throws IORuntimeException { + public static String getTypeByPath(final String path) throws IORuntimeException { return getTypeByPath(path,false); } @@ -252,7 +254,6 @@ public class FileTypeUtil { */ private static String readHex8192Upper(final InputStream in) throws IORuntimeException { try { - final int i = in.available(); return IoUtil.readHex(in, Math.min(8192, in.available()), false); } catch (final IOException e) { throw new RuntimeException(e); @@ -266,7 +267,7 @@ public class FileTypeUtil { * @return 16进制字符串 * @throws IORuntimeException IO异常 */ - private static String readHex64Upper(InputStream in) throws IORuntimeException { + private static String readHex64Upper(final InputStream in) throws IORuntimeException { return IoUtil.readHex(in, 64, false); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileUtil.java old mode 100755 new mode 100644 similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java rename to hutool-core/src/main/java/cn/hutool/core/io/file/FileUtil.java index d284e6a07..b2472a9f8 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileUtil.java @@ -1,9 +1,9 @@ -package cn.hutool.core.io; +package cn.hutool.core.io.file; import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.file.FileReader; -import cn.hutool.core.io.file.*; -import cn.hutool.core.io.file.FileWriter; +import cn.hutool.core.io.BomReader; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.stream.BOMInputStream; import cn.hutool.core.io.unit.DataSizeUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWrapper.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWrapper.java index 3c712c028..a7405a8b1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWrapper.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWrapper.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.func.Wrapper; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java index 2e8c704b0..cd51770c2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileWriter.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/LineReadWatcher.java b/hutool-core/src/main/java/cn/hutool/core/io/file/LineReadWatcher.java index 3abbb178d..e6acd1ebb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/LineReadWatcher.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/LineReadWatcher.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.watch.SimpleWatcher; import cn.hutool.core.lang.func.SerConsumer; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java b/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java index 4b9410388..e15c504ad 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/Tailer.java @@ -2,7 +2,6 @@ package cn.hutool.core.io.file; import cn.hutool.core.date.DateUnit; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java index d2553d510..4dfe544cd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/ClassPathResource.java @@ -1,7 +1,7 @@ package cn.hutool.core.io.resource; import cn.hutool.core.classloader.ClassLoaderUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.net.url.URLUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/FileResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/FileResource.java index 4f9f133fe..f35d598a5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/FileResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/FileResource.java @@ -1,6 +1,6 @@ package cn.hutool.core.io.resource; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.net.url.URLUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java index 1ce456083..dc03d3266 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java @@ -2,7 +2,7 @@ package cn.hutool.core.io.resource; import cn.hutool.core.collection.iter.EnumerationIter; import cn.hutool.core.collection.iter.IterUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.classloader.ClassLoaderUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java index c68159df7..24903cb21 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/UrlResource.java @@ -1,6 +1,6 @@ package cn.hutool.core.io.resource; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.net.url.URLUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/WebAppResource.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/WebAppResource.java index a7b57302a..e4fbecb63 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/WebAppResource.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/WebAppResource.java @@ -2,7 +2,7 @@ package cn.hutool.core.io.resource; import java.io.File; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; /** * Web root资源访问对象 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/watch/WatchMonitor.java b/hutool-core/src/main/java/cn/hutool/core/io/watch/WatchMonitor.java index 4d9b3e983..d0900753d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/watch/WatchMonitor.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/watch/WatchMonitor.java @@ -1,6 +1,6 @@ package cn.hutool.core.io.watch; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.watch.watchers.WatcherChain; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java index 30f443e80..75c5dc584 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFile.java @@ -1,6 +1,6 @@ package cn.hutool.core.net.multipart; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java index 88382709a..31bd3cc66 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/multipart/UploadFileHeader.java @@ -1,6 +1,6 @@ package cn.hutool.core.net.multipart; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; /** diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java index 5c7de2ac7..e40212402 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java @@ -4,7 +4,7 @@ import cn.hutool.core.bean.NullWrapperBean; import cn.hutool.core.classloader.ClassLoaderUtil; import cn.hutool.core.convert.BasicType; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.net.url.URLDecoder; import cn.hutool.core.net.url.URLUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 6c572a5ee..bd8373d44 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -2102,4 +2102,36 @@ public class ArrayUtil extends PrimitiveArrayUtil { final Set elementSet = SetUtil.of(Arrays.asList(array)); return elementSet.size() != array.length; } + + /** + * array数组是否以prefix开头,每个元素的匹配使用{@link ObjUtil#equals(Object, Object)}匹配。 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @param 数组元素类型 + * @return 是否开头 + */ + public static boolean startWith(final T[] array, final T[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (ObjUtil.notEquals(array[i], prefix[i])) { + return false; + } + } + return true; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java index 14d427164..18108aa08 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/CharsetUtil.java @@ -1,7 +1,7 @@ package cn.hutool.core.util; import cn.hutool.core.io.CharsetDetector; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; import java.io.File; diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java index 2f446e5fd..32dce00d9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java @@ -18,8 +18,7 @@ public class PrimitiveArrayUtil { */ public static final int INDEX_NOT_FOUND = -1; - // ---------------------------------------------------------------------- isEmpty - + // region ----- isEmpty /** * 数组是否为空 * @@ -99,8 +98,9 @@ public class PrimitiveArrayUtil { public static boolean isEmpty(final boolean[] array) { return array == null || array.length == 0; } + // endregion - // ---------------------------------------------------------------------- isNotEmpty + // region ----- isNotEmpty /** * 数组是否为非空 @@ -181,8 +181,9 @@ public class PrimitiveArrayUtil { public static boolean isNotEmpty(final boolean[] array) { return false == isEmpty(array); } + // endregion - // ---------------------------------------------------------------------- resize + // region ----- resize /** * 生成一个新的重新设置大小的数组
          @@ -203,8 +204,9 @@ public class PrimitiveArrayUtil { } return newArray; } + // endregion - // ---------------------------------------------------------------------- addAll + // region ----- addAll /** * 将多个数组合并在一起
          @@ -461,8 +463,9 @@ public class PrimitiveArrayUtil { } return result; } + // endregion - // ---------------------------------------------------------------------- split + // region ----- split /** * 拆分byte数组为几个等份(最后一份按照剩余长度分配空间) @@ -472,7 +475,7 @@ public class PrimitiveArrayUtil { * @return 拆分后的数组 */ public static byte[][] split(final byte[] array, final int len) { - int amount = array.length / len; + final int amount = array.length / len; final int remainder = array.length % len; // 兼容切片长度大于原数组长度的情况 final boolean hasRemainder = remainder > 0; @@ -493,8 +496,9 @@ public class PrimitiveArrayUtil { } return arrays; } + // endregion - // ---------------------------------------------------------------------- indexOf、LastIndexOf、contains + // region ----- indexOf、LastIndexOf、contains /** * 返回数组中指定元素所在位置,未找到返回{@link #INDEX_NOT_FOUND} @@ -895,8 +899,9 @@ public class PrimitiveArrayUtil { public static boolean contains(final boolean[] array, final boolean value) { return indexOf(array, value) > INDEX_NOT_FOUND; } + // endregion - // ------------------------------------------------------------------- Wrap and unwrap + // region ----- Wrap and unwrap /** * 将原始类型数组包装为包装类型 @@ -1250,8 +1255,9 @@ public class PrimitiveArrayUtil { } return array; } + // endregion - // ------------------------------------------------------------------- sub + // region ----- sub /** * 获取子数组 @@ -1548,8 +1554,9 @@ public class PrimitiveArrayUtil { } return Arrays.copyOfRange(array, start, end); } + // endregion - // ------------------------------------------------------------------- remove + // region ----- remove /** * 移除数组中对应位置的元素
          @@ -1693,7 +1700,7 @@ public class PrimitiveArrayUtil { return result; } - // ---------------------------------------------------------------------- removeEle + // region ----- removeEle /** * 移除数组中指定的元素
          @@ -1814,8 +1821,9 @@ public class PrimitiveArrayUtil { public static boolean[] removeEle(final boolean[] array, final boolean element) throws IllegalArgumentException { return remove(array, indexOf(array, element)); } + // endregion - // ---------------------------------------------------------------------- reverse + // region ----- reverse /** * 反转数组,会变更原数组 @@ -2088,8 +2096,9 @@ public class PrimitiveArrayUtil { public static boolean[] reverse(final boolean[] array) { return reverse(array, 0, array.length); } + // endregion - // ------------------------------------------------------------------------------------------------------------ min and max + // region ------------------------------------------- min and max /** * 取最小值 @@ -2370,8 +2379,9 @@ public class PrimitiveArrayUtil { } return max; } + // endregion - // ---------------------------------------------------------------------- shuffle + // region ----- shuffle /** * 打乱数组顺序,会变更原数组 @@ -2636,8 +2646,9 @@ public class PrimitiveArrayUtil { return array; } + // endregion - // ---------------------------------------------------------------------- swap + // region ----- swap /** * 交换数组中两个位置的值 @@ -2791,7 +2802,7 @@ public class PrimitiveArrayUtil { return array; } - // ---------------------------------------------------------------------- asc and desc + // region ----- asc and desc /** * 检查数组是否升序,即{@code array[i] <= array[i+1]}
          @@ -3111,7 +3122,257 @@ public class PrimitiveArrayUtil { return false; } } - return true; } + // endregion + + // region ----- startWith + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final boolean[] array, final boolean[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final byte[] array, final byte[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final char[] array, final char[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final double[] array, final double[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final float[] array, final float[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final int[] array, final int[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final long[] array, final long[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + + /** + * array数组是否以prefix开头 + *
            + *
          • array和prefix为同一个数组(即array == prefix),返回{@code true}
          • + *
          • array或prefix为空数组(null或length为0的数组),返回{@code true}
          • + *
          • prefix长度大于array,返回{@code false}
          • + *
          + * + * @param array 数组 + * @param prefix 前缀 + * @return 是否开头 + */ + public static boolean startWith(final short[] array, final short[] prefix) { + if (array == prefix) { + return true; + } + if(isEmpty(array)){ + return isEmpty(prefix); + } + if (prefix.length > array.length) { + return false; + } + + for (int i = 0; i < prefix.length; i++) { + if (array[i] != prefix[i]) { + return false; + } + } + return true; + } + // endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index 65d66f91a..ffab70fcf 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -4,11 +4,10 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Console; import cn.hutool.core.map.BiMap; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java b/hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java index f575483ab..c38f5a213 100755 --- a/hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java @@ -1,6 +1,6 @@ package cn.hutool.core.compress; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.FileResource; import cn.hutool.core.util.CharsetUtil; import org.junit.Ignore; diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToArrayTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToArrayTest.java index af486b7ee..bee7c8a4b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToArrayTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToArrayTest.java @@ -1,7 +1,7 @@ package cn.hutool.core.convert; import cn.hutool.core.convert.impl.ArrayConverter; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import org.junit.Assert; import org.junit.Ignore; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java index c626a4a52..e7d865f5f 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java @@ -1,5 +1,7 @@ package cn.hutool.core.io; +import cn.hutool.core.io.file.FileTypeUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; import org.junit.Assert; @@ -85,4 +87,11 @@ public class FileTypeUtilTest { final String type = FileTypeUtil.getType(inputStream); Console.log(type); } + + @Test + public void issueI6MACITest() { + final File file = FileUtil.file("text.txt"); + final String type = FileTypeUtil.getType(file); + Assert.assertEquals("txt", type); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index 0edc2f82d..b5aac3796 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.io; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.file.FileNameUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.file.LineSeparator; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java index 334d76212..cacfbfafe 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java @@ -1,5 +1,6 @@ package cn.hutool.core.io; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.stream.EmptyOutputStream; import cn.hutool.core.lang.Console; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java index 6e16ca2f9..934daef76 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/IssueI666HBTest.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java index 98eba2832..32e9a7f1e 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathDeleterTest.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java index 364d70051..62fb093d2 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/PathUtilTest.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.file; -import cn.hutool.core.io.FileUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/file/TailerTest.java b/hutool-core/src/test/java/cn/hutool/core/io/file/TailerTest.java index 027abb049..7a365555d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/file/TailerTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/file/TailerTest.java @@ -3,7 +3,6 @@ package cn.hutool.core.io.file; import org.junit.Ignore; import org.junit.Test; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; public class TailerTest { diff --git a/hutool-core/src/test/java/cn/hutool/core/io/resource/ResourceUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/resource/ResourceUtilTest.java index 437af0cf1..45981ce6e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/resource/ResourceUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/resource/ResourceUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.core.io.resource; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; import org.junit.Assert; diff --git a/hutool-core/src/test/java/cn/hutool/core/thread/SimpleSchedulerTest.java b/hutool-core/src/test/java/cn/hutool/core/thread/SimpleSchedulerTest.java index 76ff6b082..a382c5e9d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/thread/SimpleSchedulerTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/thread/SimpleSchedulerTest.java @@ -1,6 +1,6 @@ package cn.hutool.core.thread; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.RuntimeUtil; diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 5bad7fd2b..3c009e5c3 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -617,7 +617,7 @@ public class ArrayUtilTest { @Test public void subTest() { final int[] arr = {1, 2, 3, 4, 5}; - int[] empty = new int[0]; + final int[] empty = new int[0]; Assert.assertArrayEquals(empty, ArrayUtil.sub(arr, 2, 2)); Assert.assertArrayEquals(empty, ArrayUtil.sub(arr, 5, 5)); Assert.assertArrayEquals(empty, ArrayUtil.sub(arr, 5, 7)); @@ -689,4 +689,34 @@ public class ArrayUtilTest { Assert.assertTrue(ArrayUtil.hasSameElement(e)); } + + @Test + public void startWithTest() { + boolean b = ArrayUtil.startWith(new String[]{}, new String[]{}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith(new String[]{"1", "2", "3"}, new String[]{"1"}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith(new String[]{"1"}, new String[]{"1"}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith((String[])null, null); + Assert.assertTrue(b); + } + + @Test + public void startWithTest2() { + boolean b = ArrayUtil.startWith(new int[]{}, new int[]{}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith(new int[]{1,2,3}, new int[]{1}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith(new int[]{1}, new int[]{1}); + Assert.assertTrue(b); + + b = ArrayUtil.startWith((int[])null, null); + Assert.assertTrue(b); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java index aac0e1b76..f6011e994 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java @@ -2,7 +2,7 @@ package cn.hutool.core.util; import cn.hutool.core.compress.ZipReader; import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.lang.Console; import cn.hutool.core.text.StrUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java index 5f028e992..7d2e87923 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java @@ -1,7 +1,7 @@ package cn.hutool.crypto; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/Digester.java b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/Digester.java index 7259d347e..046087077 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/Digester.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/Digester.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.digest; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ArrayUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java index a30d9f133..8b5c4e7cb 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java @@ -1,7 +1,7 @@ package cn.hutool.crypto.digest.mac; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.codec.HexUtil; diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/PemUtilTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/PemUtilTest.java index 86173e5d4..e1e642300 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/PemUtilTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/PemUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.crypto; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.crypto.asymmetric.KeyType; diff --git a/hutool-db/src/test/java/cn/hutool/db/PicTransferTest.java b/hutool-db/src/test/java/cn/hutool/db/PicTransferTest.java index 9d1e70dc3..71f85f6d7 100644 --- a/hutool-db/src/test/java/cn/hutool/db/PicTransferTest.java +++ b/hutool-db/src/test/java/cn/hutool/db/PicTransferTest.java @@ -1,7 +1,7 @@ package cn.hutool.db; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/SevenZArchiver.java b/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/SevenZArchiver.java index 2762a5233..31650006f 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/SevenZArchiver.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/SevenZArchiver.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress.archiver; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/StreamArchiver.java b/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/StreamArchiver.java index 052c4657a..66ce4bbb3 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/StreamArchiver.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/compress/archiver/StreamArchiver.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress.archiver; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/SevenZExtractor.java b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/SevenZExtractor.java index 637f326b2..f452e5523 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/SevenZExtractor.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/SevenZExtractor.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress.extractor; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java index 5c907dc72..75172b6d4 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/compress/extractor/StreamExtractor.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress.extractor; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java index 8de423650..1af69d6a3 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/AbstractFtp.java @@ -1,7 +1,7 @@ package cn.hutool.extra.ftp; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharUtil; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java index 6092b475d..6b251c1a6 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java @@ -1,7 +1,7 @@ package cn.hutool.extra.ftp; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java index 6c0650676..24b8d52a9 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java @@ -1,7 +1,7 @@ package cn.hutool.extra.mail; import cn.hutool.core.lang.builder.Builder; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/management/RuntimeInfo.java b/hutool-extra/src/main/java/cn/hutool/extra/management/RuntimeInfo.java index e6cf3eca6..ae6b35e0c 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/management/RuntimeInfo.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/management/RuntimeInfo.java @@ -1,6 +1,6 @@ package cn.hutool.extra.management; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import java.io.Serializable; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java index 1dec0bcc0..f9dda33d6 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java @@ -1,6 +1,6 @@ package cn.hutool.extra.qrcode; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.swing.img.ImgUtil; import com.google.zxing.BarcodeFormat; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java index 6d80f8a84..b036c7326 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/servlet/JakartaServletUtil.java @@ -6,7 +6,7 @@ import cn.hutool.core.bean.copier.ValueProvider; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.iter.ArrayIter; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.map.CaseInsensitiveMap; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java index c58da909f..a6d6325b0 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/servlet/ServletUtil.java @@ -6,7 +6,7 @@ import cn.hutool.core.bean.copier.ValueProvider; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.iter.ArrayIter; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.map.CaseInsensitiveMap; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java index 675b55c2d..bd01b8da7 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java @@ -2,7 +2,7 @@ package cn.hutool.extra.ssh; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.extra.ftp.AbstractFtp; import cn.hutool.extra.ftp.FtpConfig; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java b/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java index feb6dca32..be7f4d4f7 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java @@ -1,6 +1,6 @@ package cn.hutool.extra.template; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import java.io.BufferedOutputStream; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyEngine.java index b7dce0f16..e03a5457b 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyEngine.java @@ -1,6 +1,6 @@ package cn.hutool.extra.template.engine.enjoy; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.id.IdUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.template.Template; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerEngine.java index 876638de0..69cf65b83 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerEngine.java @@ -1,7 +1,7 @@ package cn.hutool.extra.template.engine.freemarker; import cn.hutool.core.classloader.ClassLoaderUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.extra.template.Template; import cn.hutool.extra.template.TemplateConfig; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafEngine.java index dbd57ea3f..a527113cd 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafEngine.java @@ -7,7 +7,7 @@ import org.thymeleaf.templateresolver.FileTemplateResolver; import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.StringTemplateResolver; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.extra.template.Template; import cn.hutool.extra.template.TemplateConfig; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitEngine.java index 30a796d7f..e7c813703 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitEngine.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitEngine.java @@ -1,6 +1,6 @@ package cn.hutool.extra.template.engine.wit; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.map.Dict; import cn.hutool.extra.template.Template; import cn.hutool.extra.template.TemplateConfig; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/xml/JAXBUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/xml/JAXBUtil.java index ec13c635c..9a1cf4b30 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/xml/JAXBUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/xml/JAXBUtil.java @@ -1,7 +1,7 @@ package cn.hutool.extra.xml; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/compress/ArchiverTest.java b/hutool-extra/src/test/java/cn/hutool/extra/compress/ArchiverTest.java index 9fe4bf34a..a180f4a7f 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/compress/ArchiverTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/compress/ArchiverTest.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; import cn.hutool.extra.compress.archiver.StreamArchiver; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/compress/ExtractorTest.java b/hutool-extra/src/test/java/cn/hutool/extra/compress/ExtractorTest.java index c7aba91ac..bf2407e5f 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/compress/ExtractorTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/compress/ExtractorTest.java @@ -1,6 +1,6 @@ package cn.hutool.extra.compress; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.extra.compress.extractor.Extractor; import org.junit.Ignore; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java b/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java index 84b78366e..fb18662ef 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java @@ -1,6 +1,6 @@ package cn.hutool.extra.ftp; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.extra.ssh.Sftp; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java b/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java index caf30961b..bf84e765d 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java @@ -1,6 +1,6 @@ package cn.hutool.extra.mail; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java index cacda174b..807405e88 100755 --- a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java @@ -1,7 +1,7 @@ package cn.hutool.extra.qrcode; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.text.StrUtil; diff --git a/hutool-http/src/main/java/cn/hutool/http/client/body/MultipartOutputStream.java b/hutool-http/src/main/java/cn/hutool/http/client/body/MultipartOutputStream.java index ceb99425f..24627c79e 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/body/MultipartOutputStream.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/body/MultipartOutputStream.java @@ -1,7 +1,7 @@ package cn.hutool.http.client.body; import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.resource.HttpResource; diff --git a/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java b/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java index ae5d3f3a8..c1019d73c 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java @@ -1,6 +1,6 @@ package cn.hutool.http.client.body; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.StreamProgress; import cn.hutool.core.io.file.FileNameUtil; diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java index ff04da7ac..aad4635d9 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerResponse.java @@ -1,6 +1,6 @@ package cn.hutool.http.server; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.net.url.URLEncoder; diff --git a/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java index ce1b31c9a..e8cf6149e 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/action/RootAction.java @@ -1,7 +1,7 @@ package cn.hutool.http.server.action; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.http.server.HttpServerRequest; import cn.hutool.http.server.HttpServerResponse; diff --git a/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java b/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java index 15e73e42d..ec5e36eb7 100644 --- a/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java @@ -1,7 +1,7 @@ package cn.hutool.http; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.StreamProgress; import cn.hutool.core.lang.Console; diff --git a/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java index 4d67192e7..46205f016 100755 --- a/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HttpUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.http; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.regex.ReUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-http/src/test/java/cn/hutool/http/UploadTest.java b/hutool-http/src/test/java/cn/hutool/http/UploadTest.java index b6095fadf..2117b9be7 100644 --- a/hutool-http/src/test/java/cn/hutool/http/UploadTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/UploadTest.java @@ -1,6 +1,6 @@ package cn.hutool.http; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.MultiFileResource; import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; diff --git a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java index 8b7a8be18..dffe0e455 100644 --- a/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/server/SimpleServerTest.java @@ -1,7 +1,7 @@ package cn.hutool.http.server; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.net.multipart.UploadFile; import cn.hutool.http.meta.ContentType; diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java index 7863af839..df799b09b 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java @@ -1,8 +1,7 @@ package cn.hutool.json; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.io.file.FileReader; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java index 97a3ca581..a47014556 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONArrayTest.java @@ -2,7 +2,7 @@ package cn.hutool.json; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.convert.ConvertException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.map.Dict; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvBaseReader.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvBaseReader.java index 475d08d5f..609167f7f 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvBaseReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvBaseReader.java @@ -1,6 +1,6 @@ package cn.hutool.poi.csv; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java index d80eabc81..86f98424e 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java @@ -1,6 +1,6 @@ package cn.hutool.poi.csv; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.func.SerConsumer; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java index 30ec937d4..edab978bb 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java @@ -4,7 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.iter.ArrayIter; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/BigExcelWriter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/BigExcelWriter.java index d8f619d85..cfeb73430 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/BigExcelWriter.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/BigExcelWriter.java @@ -1,6 +1,6 @@ package cn.hutool.poi.excel; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.streaming.SXSSFSheet; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java index 8dc63595a..a953aba71 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java @@ -1,6 +1,6 @@ package cn.hutool.poi.excel; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.func.SerBiConsumer; import cn.hutool.poi.excel.cell.CellEditor; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java index 85c9b7034..22a59c968 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java @@ -1,7 +1,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.exceptions.DependencyException; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.regex.ReUtil; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java index b14a814e6..daf67cab2 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelWriter.java @@ -3,7 +3,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.comparator.IndexedComparator; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/WorkbookUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/WorkbookUtil.java index ec41107ec..093b3bb26 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/WorkbookUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/WorkbookUtil.java @@ -1,7 +1,7 @@ package cn.hutool.poi.excel; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java index 267c83adf..ebea0cd08 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java @@ -1,6 +1,6 @@ package cn.hutool.poi.excel.sax; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.poi.exceptions.POIException; import java.io.File; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/word/DocUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/word/DocUtil.java index 3d713eb6d..d949e20a5 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/word/DocUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/word/DocUtil.java @@ -1,6 +1,6 @@ package cn.hutool.poi.word; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.poi.exceptions.POIException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; diff --git a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java index 473067d8a..5e390ea64 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java @@ -1,6 +1,6 @@ package cn.hutool.poi.word; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.FileNameUtil; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvReaderTest.java b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvReaderTest.java index 4e9c19931..9e1dd52ca 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvReaderTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvReaderTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.csv; import cn.hutool.core.annotation.Alias; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvUtilTest.java index cd929bb8e..689065c1f 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvUtilTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.csv; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; import lombok.AllArgsConstructor; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvWriterTest.java index 3321137a9..791d844f4 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/csv/CsvWriterTest.java @@ -1,6 +1,6 @@ package cn.hutool.poi.csv; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java b/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java index c0c43a705..101dd6937 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java @@ -1,6 +1,6 @@ package cn.hutool.poi.csv; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.func.SerConsumer; import cn.hutool.core.util.CharsetUtil; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java index 0c8aa0700..4c2c5e461 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.poi.excel.style.StyleUtil; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelFileUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelFileUtilTest.java index df0a1853a..4b9a9f07c 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelFileUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelFileUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.poi.excel; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index cd0cb8f95..bafdfa8b3 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.text.StrUtil; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java index 930747589..cc9a69430 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.lang.id.IdUtil; import cn.hutool.core.map.MapUtil; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java index 35c30d41e..58312bde4 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/Issue2307Test.java @@ -1,7 +1,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.xssf.usermodel.XSSFSheet; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI66Z6BTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI66Z6BTest.java index b2c08c300..e160fed80 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI66Z6BTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI66Z6BTest.java @@ -1,7 +1,7 @@ package cn.hutool.poi.excel; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/ofd/OfdWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/ofd/OfdWriterTest.java index 9600ab3ce..292db1ef9 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/ofd/OfdWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/ofd/OfdWriterTest.java @@ -1,6 +1,6 @@ package cn.hutool.poi.ofd; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java index 8b54e0996..510eaf870 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java @@ -2,7 +2,7 @@ package cn.hutool.poi.word; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java index 3aad945c7..705f9079d 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java @@ -2,7 +2,7 @@ package cn.hutool.setting; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.resource.Resource; import cn.hutool.core.io.resource.ResourceUtil; diff --git a/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java b/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java index 516284d49..7715aeb86 100755 --- a/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java @@ -1,6 +1,6 @@ package cn.hutool.setting; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.LineReader; import cn.hutool.core.io.resource.Resource; diff --git a/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java b/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java index c7bfac22d..f251cdc09 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java @@ -1,7 +1,7 @@ package cn.hutool.setting.dialect; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.resource.Resource; diff --git a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java index 0c1c2f80d..a5c77b2ea 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/dialect/PropsUtil.java @@ -1,6 +1,5 @@ package cn.hutool.setting.dialect; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.io.resource.NoResourceException; import cn.hutool.core.map.SafeConcurrentHashMap; diff --git a/hutool-setting/src/test/java/cn/hutool/setting/yaml/YamlUtilTest.java b/hutool-setting/src/test/java/cn/hutool/setting/yaml/YamlUtilTest.java index c27825e39..ed409e3a2 100755 --- a/hutool-setting/src/test/java/cn/hutool/setting/yaml/YamlUtilTest.java +++ b/hutool-setting/src/test/java/cn/hutool/setting/yaml/YamlUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.setting.yaml; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.map.Dict; import cn.hutool.core.util.CharsetUtil; import org.junit.Assert; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java b/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java index ad031b020..e3202d6c7 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java @@ -1,7 +1,7 @@ package cn.hutool.swing.captcha; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.net.url.URLUtil; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java b/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java index 571e9ce59..21af9782b 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java @@ -1,6 +1,6 @@ package cn.hutool.swing.img; -import cn.hutool.core.io.FileTypeUtil; +import cn.hutool.core.io.file.FileTypeUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.swing.img.color.ColorUtil; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index b16760b21..f4c81603c 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -1,7 +1,7 @@ package cn.hutool.swing.img; import cn.hutool.core.codec.BaseN.Base64; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.file.FileNameUtil; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java index 0f07d572d..506fc39c2 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java @@ -1,6 +1,6 @@ package cn.hutool.swing.img; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-swing/src/test/java/cn/hutool/swing/RobotUtilTest.java b/hutool-swing/src/test/java/cn/hutool/swing/RobotUtilTest.java index 00c32e48c..17862906d 100755 --- a/hutool-swing/src/test/java/cn/hutool/swing/RobotUtilTest.java +++ b/hutool-swing/src/test/java/cn/hutool/swing/RobotUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.swing; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java index 4973c1823..16ebc058b 100755 --- a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java +++ b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgTest.java @@ -1,7 +1,7 @@ package cn.hutool.swing.img; -import cn.hutool.core.io.FileTypeUtil; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileTypeUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.net.url.URLUtil; import org.junit.Ignore; import org.junit.Test; diff --git a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java index 47dcd5fdd..521f0b118 100755 --- a/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java +++ b/hutool-swing/src/test/java/cn/hutool/swing/img/ImgUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.swing.img; -import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.lang.Console; import cn.hutool.swing.img.color.ColorUtil; From cc6a3d4964b8dfc78dd40d62d8b4540821fb82bb Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 16:01:07 +0800 Subject: [PATCH 108/125] fix bug --- .../java/cn/hutool/core/io/file/FileMagicNumber.java | 12 ++++++++---- .../java/cn/hutool/core/io/FileTypeUtilTest.java | 2 +- hutool-core/src/test/resources/1.txt | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 hutool-core/src/test/resources/1.txt diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java index 01c22a49a..bb7a1d02c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileMagicNumber.java @@ -394,6 +394,9 @@ public enum FileMagicNumber { WOFF("font/woff", "woff") { @Override public boolean match(final byte[] bytes) { + if(bytes.length < 8){ + return false; + } final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) @@ -410,8 +413,7 @@ public enum FileMagicNumber { && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); - return bytes.length > 7 - && (flag1 && (flag2 || flag3 || flag4)); + return flag1 && (flag2 || flag3 || flag4); } }, /** @@ -420,6 +422,9 @@ public enum FileMagicNumber { WOFF2("font/woff2", "woff2") { @Override public boolean match(final byte[] bytes) { + if(bytes.length < 8){ + return false; + } final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) @@ -436,8 +441,7 @@ public enum FileMagicNumber { && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); - return bytes.length > 7 - && (flag1 && (flag2 || flag3 || flag4)); + return flag1 && (flag2 || flag3 || flag4); } }, /** diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java index e7d865f5f..3c6da37ff 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java @@ -90,7 +90,7 @@ public class FileTypeUtilTest { @Test public void issueI6MACITest() { - final File file = FileUtil.file("text.txt"); + final File file = FileUtil.file("1.txt"); final String type = FileTypeUtil.getType(file); Assert.assertEquals("txt", type); } diff --git a/hutool-core/src/test/resources/1.txt b/hutool-core/src/test/resources/1.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/hutool-core/src/test/resources/1.txt @@ -0,0 +1 @@ +1 From 32c7dd0c6b02d3ab8399c361cf12c4204bf4511b Mon Sep 17 00:00:00 2001 From: emptypoint <1215582715@qq.com> Date: Sun, 12 Mar 2023 20:52:27 +0800 Subject: [PATCH 109/125] 1.fix doc; 2.update code; --- .../hutool/core/text/finder/CharFinder.java | 6 +- .../hutool/core/text/finder/LengthFinder.java | 2 +- .../core/text/finder/PatternFinder.java | 4 +- .../cn/hutool/core/text/split/SplitIter.java | 2 +- .../cn/hutool/core/text/split/SplitUtil.java | 68 ++++++++++--------- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/text/finder/CharFinder.java b/hutool-core/src/main/java/cn/hutool/core/text/finder/CharFinder.java index 61029fdb0..5eece80c0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/finder/CharFinder.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/finder/CharFinder.java @@ -1,7 +1,7 @@ package cn.hutool.core.text.finder; import cn.hutool.core.lang.Assert; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.util.CharUtil; /** * 字符查找器
          @@ -42,13 +42,13 @@ public class CharFinder extends TextFinder { final int limit = getValidEndIndex(); if(negative){ for (int i = from; i > limit; i--) { - if (NumberUtil.equals(c, text.charAt(i), caseInsensitive)) { + if (CharUtil.equals(c, text.charAt(i), caseInsensitive)) { return i; } } } else{ for (int i = from; i < limit; i++) { - if (NumberUtil.equals(c, text.charAt(i), caseInsensitive)) { + if (CharUtil.equals(c, text.charAt(i), caseInsensitive)) { return i; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java b/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java index be20641b1..40f1e855f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/finder/LengthFinder.java @@ -16,7 +16,7 @@ public class LengthFinder extends TextFinder { /** * 构造 - * @param length 长度 + * @param length 长度,必须大于0 */ public LengthFinder(final int length) { Assert.isTrue(length > 0, "Length must be great than 0"); diff --git a/hutool-core/src/main/java/cn/hutool/core/text/finder/PatternFinder.java b/hutool-core/src/main/java/cn/hutool/core/text/finder/PatternFinder.java index 6de946500..209058b6a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/finder/PatternFinder.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/finder/PatternFinder.java @@ -1,5 +1,7 @@ package cn.hutool.core.text.finder; +import cn.hutool.core.regex.PatternPool; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -23,7 +25,7 @@ public class PatternFinder extends TextFinder { * @param caseInsensitive 是否忽略大小写 */ public PatternFinder(final String regex, final boolean caseInsensitive) { - this(Pattern.compile(regex, caseInsensitive ? Pattern.CASE_INSENSITIVE : 0)); + this(PatternPool.get(regex, caseInsensitive ? Pattern.CASE_INSENSITIVE : 0)); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java index b82bb0336..2c36dd4c4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java @@ -125,7 +125,7 @@ public class SplitIter extends ComputeIter implements Serializable { * @return 切分后的列表 */ public List toList(final boolean trim) { - return toList((str) -> trim ? StrUtil.trim(str) : str); + return toList(trim ? StrUtil::trim : Function.identity()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java index 6a16f86de..e6505b214 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java @@ -25,6 +25,7 @@ public class SplitUtil { /** * 切分字符串路径,仅支持Unix分界符:/ + *

          去除每个元素两边空格,大小写敏感,忽略空串

          * * @param str 被切分的字符串 * @return 切分后的集合 @@ -36,6 +37,7 @@ public class SplitUtil { /** * 切分字符串路径,仅支持Unix分界符:/ + *

          去除每个元素两边空格,大小写敏感,忽略空串

          * * @param str 被切分的字符串 * @return 切分后的集合 @@ -47,9 +49,10 @@ public class SplitUtil { /** * 切分字符串路径,仅支持Unix分界符:/ + *

          去除每个元素两边空格,大小写敏感,忽略空串

          * * @param str 被切分的字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @return 切分后的集合 * @since 3.0.8 */ @@ -59,9 +62,10 @@ public class SplitUtil { /** * 切分字符串路径,仅支持Unix分界符:/ + *

          去除每个元素两边空格,大小写敏感,忽略空串

          * * @param str 被切分的字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @return 切分后的集合 * @since 3.0.8 */ @@ -70,7 +74,7 @@ public class SplitUtil { } /** - * 切分字符串 + * 切分字符串,大小写敏感,去除每个元素两边空白符 * * @param str 被切分的字符串 * @param separator 分隔符字符 @@ -101,7 +105,7 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.0.8 @@ -115,7 +119,7 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 @@ -131,7 +135,7 @@ public class SplitUtil { * @param 切分后的元素类型 * @param str 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param ignoreEmpty 是否忽略空串 * @param mapping 切分后的字符串元素的转换方法 * @return 切分后的集合,元素类型是经过 mapping 转换后的 @@ -146,7 +150,7 @@ public class SplitUtil { * * @param text 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 @@ -161,7 +165,7 @@ public class SplitUtil { * * @param text 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @param ignoreCase 是否忽略大小写 @@ -178,7 +182,7 @@ public class SplitUtil { * @param 切分后的元素类型 * @param text 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 + * @param limit 限制分片数,小于等于0表示无限制 * @param ignoreEmpty 是否忽略空串 * @param ignoreCase 是否忽略大小写 * @param mapping 切分后的字符串元素的转换方法 @@ -187,7 +191,7 @@ public class SplitUtil { */ public static List split(final CharSequence text, final char separator, final int limit, final boolean ignoreEmpty, final boolean ignoreCase, final Function mapping) { - if (null == text) { + if (StrUtil.isEmpty(text)) { return new ArrayList<>(0); } final SplitIter splitIter = new SplitIter(text, new CharFinder(separator, ignoreCase), limit, ignoreEmpty); @@ -199,7 +203,7 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separator 分隔符字符 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 @@ -226,7 +230,7 @@ public class SplitUtil { } /** - * 切分字符串,去除每个元素两边空格,忽略大小写 + * 切分字符串,去除每个元素两边空格,不忽略大小写 * * @param str 被切分的字符串 * @param separator 分隔符字符串 @@ -254,11 +258,11 @@ public class SplitUtil { } /** - * 切分字符串,去除每个元素两边空格,忽略大小写 + * 切分字符串,去除每个元素两边空格,不忽略大小写 * * @param str 被切分的字符串 * @param separator 分隔符字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.2.1 @@ -272,7 +276,7 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separator 分隔符字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 @@ -287,7 +291,7 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separator 分隔符字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.2.1 @@ -310,7 +314,7 @@ public class SplitUtil { * @since 3.2.1 */ public static List split(final CharSequence text, final String separator, final int limit, final boolean isTrim, final boolean ignoreEmpty, final boolean ignoreCase) { - if (null == text) { + if (StrUtil.isEmpty(text)) { return new ArrayList<>(0); } final SplitIter splitIter = new SplitIter(text, new StrFinder(separator, ignoreCase), limit, ignoreEmpty); @@ -340,12 +344,12 @@ public class SplitUtil { * 如果为空字符串或者null 则返回空集合 * * @param text 被切分的字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @return 切分后的集合 * @since 3.0.8 */ public static List split(final CharSequence text, final int limit) { - if (null == text) { + if (StrUtil.isBlank(text)) { return new ArrayList<>(0); } final SplitIter splitIter = new SplitIter(text, new CharMatcherFinder(CharUtil::isBlankChar), limit, true); @@ -356,11 +360,11 @@ public class SplitUtil { * 切分字符串为字符串数组 * * @param str 被切分的字符串 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @return 切分后的集合 * @since 3.0.8 */ - public static String[] splitToArray(final String str, final int limit) { + public static String[] splitToArray(final CharSequence str, final int limit) { return toArray(split(str, limit)); } //---------------------------------------------------------------------------------------------- Split by regex @@ -370,13 +374,13 @@ public class SplitUtil { * * @param text 字符串 * @param separatorRegex 分隔符正则 - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.0.8 */ - public static List splitByRegex(final String text, final String separatorRegex, final int limit, final boolean isTrim, final boolean ignoreEmpty) { + public static List splitByRegex(final CharSequence text, final String separatorRegex, final int limit, final boolean isTrim, final boolean ignoreEmpty) { final Pattern pattern = PatternPool.get(separatorRegex); return split(text, pattern, limit, isTrim, ignoreEmpty); } @@ -387,14 +391,14 @@ public class SplitUtil { * * @param text 字符串 * @param separatorPattern 分隔符正则{@link Pattern} - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.0.8 */ - public static List split(final String text, final Pattern separatorPattern, final int limit, final boolean isTrim, final boolean ignoreEmpty) { - if (null == text) { + public static List split(final CharSequence text, final Pattern separatorPattern, final int limit, final boolean isTrim, final boolean ignoreEmpty) { + if (StrUtil.isEmpty(text)) { return new ArrayList<>(0); } final SplitIter splitIter = new SplitIter(text, new PatternFinder(separatorPattern), limit, ignoreEmpty); @@ -406,13 +410,13 @@ public class SplitUtil { * * @param str 被切分的字符串 * @param separatorPattern 分隔符正则{@link Pattern} - * @param limit 限制分片数 + * @param limit 限制分片数,小于等于0表示无限制 * @param isTrim 是否去除切分字符串后每个元素两边的空格 * @param ignoreEmpty 是否忽略空串 * @return 切分后的集合 * @since 3.0.8 */ - public static String[] splitToArray(final String str, final Pattern separatorPattern, final int limit, final boolean isTrim, final boolean ignoreEmpty) { + public static String[] splitToArray(final CharSequence str, final Pattern separatorPattern, final int limit, final boolean isTrim, final boolean ignoreEmpty) { return toArray(split(str, separatorPattern, limit, isTrim, ignoreEmpty)); } //---------------------------------------------------------------------------------------------- Split by length @@ -421,11 +425,11 @@ public class SplitUtil { * 根据给定长度,将给定字符串截取为多个部分 * * @param text 字符串 - * @param len 每一个小节的长度 + * @param len 每一个小节的长度,必须大于0 * @return 截取后的字符串数组 */ public static String[] splitByLength(final CharSequence text, final int len) { - if (null == text) { + if (StrUtil.isEmpty(text)) { return new String[0]; } final SplitIter splitIter = new SplitIter(text, new LengthFinder(len), -1, false); @@ -449,8 +453,8 @@ public class SplitUtil { * @param isTrim 是否trim * @return {@link Function} */ - private static Function trimFunc(final boolean isTrim) { - return (str) -> isTrim ? StrUtil.trim(str) : str; + public static Function trimFunc(final boolean isTrim) { + return isTrim ? StrUtil::trim : Function.identity(); } //---------------------------------------------------------------------------------------------------------- Private method end } From 4da3e62e64206bfc1f07d366d9fba9b74d695c82 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 23:46:29 +0800 Subject: [PATCH 110/125] fix readme --- README-EN.md | 2 +- README.md | 2 +- hutool-core/README.md | 2 +- .../annotation/GenericAnnotationMapping.java | 14 +-- .../java/cn/hutool/core/util/CharUtil.java | 1 + hutool-http/README.md | 114 ++++++++++++++++++ hutool-swing/README.md | 2 +- 7 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 hutool-http/README.md diff --git a/README-EN.md b/README-EN.md index 545f935ea..1acb7eaeb 100755 --- a/README-EN.md +++ b/README-EN.md @@ -1,5 +1,5 @@

          - +

          🍬A set of tools that keep Java sweet. diff --git a/README.md b/README.md index 622c5490f..c24d857fb 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

          - +

          🍬A set of tools that keep Java sweet. diff --git a/hutool-core/README.md b/hutool-core/README.md index f7cf33d14..1ffab5d11 100755 --- a/hutool-core/README.md +++ b/hutool-core/README.md @@ -1,5 +1,5 @@

          - +

          🍬A set of tools that keep Java sweet. diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/GenericAnnotationMapping.java b/hutool-core/src/main/java/cn/hutool/core/annotation/GenericAnnotationMapping.java index 1d35b024c..7bcfcb751 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/GenericAnnotationMapping.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/GenericAnnotationMapping.java @@ -17,21 +17,21 @@ import java.util.stream.Stream; */ public class GenericAnnotationMapping implements AnnotationMapping { - private final Annotation annotation; - private final boolean isRoot; - private final Method[] attributes; - /** * 创建一个通用注解包装类 * * @param annotation 注解对象 * @param isRoot 是否根注解 - * @return {@link GenericAnnotationMapping}实例 + * @return {@code GenericAnnotationMapping}实例 */ public static GenericAnnotationMapping create(final Annotation annotation, final boolean isRoot) { return new GenericAnnotationMapping(annotation, isRoot); } + private final Annotation annotation; + private final boolean isRoot; + private final Method[] attributes; + /** * 创建一个通用注解包装类 * @@ -133,14 +133,14 @@ public class GenericAnnotationMapping implements AnnotationMapping { * @return 是否 */ @Override - public boolean equals(Object o) { + public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } - GenericAnnotationMapping that = (GenericAnnotationMapping)o; + final GenericAnnotationMapping that = (GenericAnnotationMapping)o; return isRoot == that.isRoot && annotation.equals(that.annotation); } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java index 1b73f0049..52a592618 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java @@ -254,6 +254,7 @@ public class CharUtil implements CharPool { * @see Character#isSpaceChar(int) * @since 4.0.10 */ + @SuppressWarnings("UnnecessaryUnicodeEscape") public static boolean isBlankChar(final int c) { return Character.isWhitespace(c) || Character.isSpaceChar(c) diff --git a/hutool-http/README.md b/hutool-http/README.md new file mode 100644 index 000000000..28211ff68 --- /dev/null +++ b/hutool-http/README.md @@ -0,0 +1,114 @@ +

          + +

          +

          + 🍬A set of tools that keep Java sweet. +

          +

          + 👉 https://hutool.cn/ 👈 +

          + +## 📚Hutool-http 模块介绍 + +`Hutool-http`提供了简易的Http服务器和客户端门面封装。 + +------------------------------------------------------------------------------- + +## 🛠️包含内容 + +### 注解(annotation) + +提供了注解工具类,以及一些注解封装。如`CombinationAnnotationElement`组合注解以及Alias别名注解等。 + +### bean(bean) + +提供了Bean工具类,以及Bean属性解析、Bean拷贝、动态Bean等。 + +### 构建器(builder) + +抽象了Builder接口,提供建造者模式的封装,并默认提供了包括equals封装、Bean构建封装、比较器封装等。 + +### 克隆(clone) + +提供`Cloneable`接口,明确`clone`方法,并提供默认实现类。 + +### 编码(codec) + +提供了BaseN编码(Base16、Base32、Base58、Base62、Base64)编码实现。并提供了包括BCD、PunyCode、百分号编码的实现。 +同时提供了包括莫尔斯电码、凯撒密码、RotN这类有趣功能的实现。 + +### 集合(collection) + +集合中主要是提供了针对`Iterator`实现类的工具封装方法`IterUtil`和集合类封装的工具类`CollUtil`,并提供了一些特别的集合封装。 + +### 比较器(comparator) + +主要是一些比较器的实现,如Bean字段比较器、自定义函数比较器、版本比较器等。 + +### 动态编译(compiler) + +提供`javax.tools.JavaCompiler`的包装简化服务,形成源码动态编译工具类`CompilerUtil`,完成代码动态编译及热部署。 + +### 压缩(compress) + +主要针对`java.util.zip`中的相关类封装工具,提供Zip、Gzip、Zlib等格式的压缩解压缩封装,为`ZipUtil`提供服务。 + +### 转换(convert) + +“万能”转换器,提供整套的类型转换方式。通过`Converter`接口和`ConverterRegistry`转换登记中心,完成任意数据类型转换和自定义转换。 + +### 日期时间(date) + +提供`Date`、`Calendar`、`java.time`相关API的工具化封装。包括时间解析、格式化、偏移等。 + +### 异常(exceptions) + +提供异常工具`ExceptionUtil`,以及一些工具内部使用的异常。 + +### getter接口(getter) + +提供各种类型的get操作接口封装。 + +### 图片(img) + +提供图片、绘图、字体等工具封装,并提供GIF生成器和解析器实现。 + +### IO流和文件(io) + +提供IO流工具、文件工具、文件类型工具等,并提供流拷贝、Checksum、文件监听功能实现。 + +### 语言特性(lang) + +超级大杂项,提供一些设计模式的抽象实现(如单例模式`Singleton`),还有正则、Id生成器、函数、Hash算法、可变对象、树形结构、字典等。 + +### Map(map) + +提供Map工具类和各类Map实现封装,如行列键的Table实现、自定义键值对转换的Map、线程安全的WeakMap实现等。 + +### 数学(math) + +提供简单数学计算封装,如排列组合、货币类等。 + +### 网络(net) + +提供网络相关工具封装,以及Ip地址工具类、SSL工具类、URL编码解码等。 + +### StreamAPI封装(stream) + +提供简单的Stream相关封装。 + +### Swing和AWT(swing) + +提供桌面应用API的工具封装,如启动应用、控制键盘鼠标操作、截屏等功能。 + +### 文本字符串(text) + +提供强大的字符串文本封装,包括字符转换、字符串查找、字符串替换、字符串切分、Unicode工具等,并提供CSV格式封装。 + +### 线程及并发(thread) + +线程并发封装,包括线程工具、锁工具、`CompletableFuture`封装工具、线程池构建等。 + +### 工具杂项(util) + +提供其他不便归类的杂项工具类。如数组、编码、字符、Class、坐标系、身份证、组织机构代码、脱敏、枚举、转义、XML、进制转换、随机数、反射、正则、SPI等各种工具。 \ No newline at end of file diff --git a/hutool-swing/README.md b/hutool-swing/README.md index 7de5d744e..f27d33ff1 100644 --- a/hutool-swing/README.md +++ b/hutool-swing/README.md @@ -1,5 +1,5 @@

          - +

          🍬A set of tools that keep Java sweet. From f05e084a3b39c5140693509452c4e6bdb1061ce6 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Mar 2023 23:49:14 +0800 Subject: [PATCH 111/125] fix test --- .../annotation/AnnotatedElementUtilTest.java | 126 +++++++++--------- .../CombinationAnnotationElementTest.java | 18 +-- .../GenericAnnotationMappingTest.java | 44 +++--- .../HierarchicalAnnotatedElementTest.java | 72 +++++----- .../annotation/MetaAnnotatedElementTest.java | 78 +++++------ .../RepeatableAnnotationCollectorTest.java | 52 ++++---- .../RepeatableMetaAnnotatedElementTest.java | 44 +++--- .../ResolvedAnnotationMappingTest.java | 111 +++++++-------- 8 files changed, 273 insertions(+), 272 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java index 7445efde8..78070ef39 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java @@ -39,7 +39,7 @@ public class AnnotatedElementUtilTest { @Test public void testClearCaches() { - AnnotatedElement type = Foo.class; + final AnnotatedElement type = Foo.class; AnnotatedElement element = AnnotatedElementUtil.getResolvedMetaElementCache(type); Assert.assertSame(element, AnnotatedElementUtil.getResolvedMetaElementCache(type)); @@ -94,22 +94,22 @@ public class AnnotatedElementUtilTest { @Test public void testFindAnnotations() { - Annotation[] annotations = AnnotatedElementUtil.findAnnotations(Foo.class); + final Annotation[] annotations = AnnotatedElementUtil.findAnnotations(Foo.class); Assert.assertArrayEquals(ANNOTATIONS, annotations); } @Test public void testFindResolvedAnnotation() { - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation3.class); + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation2.class); + final Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation1.class); + final Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.findResolvedAnnotation(Foo.class, Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -121,19 +121,19 @@ public class AnnotatedElementUtilTest { @Test public void testFindResolvedAnnotations() { - Annotation[] resolvedAnnotations = AnnotatedElementUtil.findResolvedAnnotations(Foo.class); - Map, Annotation> annotationMap = Stream.of(resolvedAnnotations).collect(Collectors.toMap(Annotation::annotationType, Function.identity())); + final Annotation[] resolvedAnnotations = AnnotatedElementUtil.findResolvedAnnotations(Foo.class); + final Map, Annotation> annotationMap = Stream.of(resolvedAnnotations).collect(Collectors.toMap(Annotation::annotationType, Function.identity())); - Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); + final Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = (Annotation2)annotationMap.get(Annotation2.class); + final Annotation2 resolvedAnnotation2 = (Annotation2)annotationMap.get(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = (Annotation1)annotationMap.get(Annotation1.class); + final Annotation1 resolvedAnnotation1 = (Annotation1)annotationMap.get(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -145,16 +145,16 @@ public class AnnotatedElementUtilTest { @Test public void testFindAllResolvedAnnotations() { - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation3.class)[0]; + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation3.class)[0]; Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation2.class)[0]; + final Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation2.class)[0]; Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation1.class)[0]; + final Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.findAllResolvedAnnotations(Foo.class, Annotation1.class)[0]; Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -195,7 +195,7 @@ public class AnnotatedElementUtilTest { public void testFindDirectlyResolvedAnnotation() { Assert.assertEquals(ANNOTATION4, AnnotatedElementUtil.findDirectlyResolvedAnnotation(Foo.class, Annotation4.class)); Assert.assertEquals(ANNOTATION6, AnnotatedElementUtil.findDirectlyResolvedAnnotation(Foo.class, Annotation6.class)); - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findDirectlyResolvedAnnotation(Foo.class, Annotation3.class); + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findDirectlyResolvedAnnotation(Foo.class, Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -207,12 +207,12 @@ public class AnnotatedElementUtilTest { @Test public void testFindDirectlyResolvedAnnotations() { - Annotation[] resolvedAnnotations = AnnotatedElementUtil.findDirectlyResolvedAnnotations(Foo.class); - Map, Annotation> annotationMap = Stream.of(resolvedAnnotations).collect(Collectors.toMap(Annotation::annotationType, Function.identity())); + final Annotation[] resolvedAnnotations = AnnotatedElementUtil.findDirectlyResolvedAnnotations(Foo.class); + final Map, Annotation> annotationMap = Stream.of(resolvedAnnotations).collect(Collectors.toMap(Annotation::annotationType, Function.identity())); Assert.assertEquals(ANNOTATION4, annotationMap.get(Annotation4.class)); Assert.assertEquals(ANNOTATION6, annotationMap.get(Annotation6.class)); - Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); + final Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -227,7 +227,7 @@ public class AnnotatedElementUtilTest { Assert.assertEquals(ANNOTATION4, AnnotatedElementUtil.findAllDirectlyResolvedAnnotations(Foo.class, Annotation4.class)[0]); Assert.assertEquals(ANNOTATION6, AnnotatedElementUtil.findAllDirectlyResolvedAnnotations(Foo.class, Annotation6.class)[0]); - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findAllDirectlyResolvedAnnotations(Foo.class, Annotation3.class)[0]; + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.findAllDirectlyResolvedAnnotations(Foo.class, Annotation3.class)[0]; Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -261,7 +261,7 @@ public class AnnotatedElementUtilTest { @Test public void testGetAnnotations() { - Annotation[] annotations = AnnotatedElementUtil.getAnnotations(Foo.class); + final Annotation[] annotations = AnnotatedElementUtil.getAnnotations(Foo.class); Assert.assertArrayEquals( new Annotation[]{ ANNOTATION3, ANNOTATION2, ANNOTATION1 }, annotations @@ -270,15 +270,15 @@ public class AnnotatedElementUtilTest { @Test public void testGetAllAnnotations() { - Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation3.class); + final Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation3.class); Assert.assertEquals(1, resolvedAnnotation3s.length); Assert.assertEquals(ANNOTATION3, resolvedAnnotation3s[0]); // value与alias互为别名 - Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation2.class); + final Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation2.class); Assert.assertEquals(1, resolvedAnnotation2s.length); Assert.assertEquals(ANNOTATION2, resolvedAnnotation2s[0]); // value与alias互为别名 - Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation1.class); + final Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation1.class); Assert.assertEquals(1, resolvedAnnotation1s.length); Assert.assertEquals(ANNOTATION1, resolvedAnnotation1s[0]); @@ -289,16 +289,16 @@ public class AnnotatedElementUtilTest { @Test public void testGetResolvedAnnotation() { - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation3.class); + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation2.class); + final Annotation2 resolvedAnnotation2 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation1.class); + final Annotation1 resolvedAnnotation1 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -310,22 +310,22 @@ public class AnnotatedElementUtilTest { @Test public void testGetAllResolvedAnnotations() { - Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation3.class); + final Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation3.class); Assert.assertEquals(1, resolvedAnnotation3s.length); - Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; + final Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation2.class); + final Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation2.class); Assert.assertEquals(1, resolvedAnnotation2s.length); - Annotation2 resolvedAnnotation2 = resolvedAnnotation2s[0]; + final Annotation2 resolvedAnnotation2 = resolvedAnnotation2s[0]; Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation1.class); + final Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation1.class); Assert.assertEquals(1, resolvedAnnotation1s.length); - Annotation1 resolvedAnnotation1 = resolvedAnnotation1s[0]; + final Annotation1 resolvedAnnotation1 = resolvedAnnotation1s[0]; Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -337,19 +337,19 @@ public class AnnotatedElementUtilTest { @Test public void testGetResolvedAnnotations() { - Map, Annotation> annotationMap = Stream.of(AnnotatedElementUtil.getResolvedAnnotations(Foo.class)) + final Map, Annotation> annotationMap = Stream.of(AnnotatedElementUtil.getResolvedAnnotations(Foo.class)) .collect(Collectors.toMap(Annotation::annotationType, Function.identity())); - Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); + final Annotation3 resolvedAnnotation3 = (Annotation3)annotationMap.get(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = (Annotation2)annotationMap.get(Annotation2.class); + final Annotation2 resolvedAnnotation2 = (Annotation2)annotationMap.get(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = (Annotation1)annotationMap.get(Annotation1.class); + final Annotation1 resolvedAnnotation1 = (Annotation1)annotationMap.get(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -372,9 +372,9 @@ public class AnnotatedElementUtilTest { @Test public void testGetAllDirectlyAnnotations() { - Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyAnnotations(Foo.class, Annotation3.class); + final Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyAnnotations(Foo.class, Annotation3.class); Assert.assertEquals(1, resolvedAnnotation3s.length); - Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; + final Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; Assert.assertEquals(ANNOTATION3, resolvedAnnotation3); Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation2.class).length); @@ -386,14 +386,14 @@ public class AnnotatedElementUtilTest { @Test public void testGetDirectlyAnnotations() { - Annotation[] annotations = AnnotatedElementUtil.getDirectlyAnnotations(Foo.class); + final Annotation[] annotations = AnnotatedElementUtil.getDirectlyAnnotations(Foo.class); Assert.assertEquals(1, annotations.length); Assert.assertEquals(ANNOTATION3, annotations[0]); } @Test public void testGetDirectlyResolvedAnnotation() { - Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.getDirectlyResolvedAnnotation(Foo.class, Annotation3.class); + final Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.getDirectlyResolvedAnnotation(Foo.class, Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -407,9 +407,9 @@ public class AnnotatedElementUtilTest { @Test public void testGetDirectlyAllResolvedAnnotations() { - Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation3.class); + final Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation3.class); Assert.assertEquals(1, resolvedAnnotation3s.length); - Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; + final Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0]; Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -423,10 +423,10 @@ public class AnnotatedElementUtilTest { @Test public void testGetDirectlyResolvedAnnotations() { - Annotation[] annotations = AnnotatedElementUtil.getDirectlyResolvedAnnotations(Foo.class); + final Annotation[] annotations = AnnotatedElementUtil.getDirectlyResolvedAnnotations(Foo.class); Assert.assertEquals(1, annotations.length); - Annotation3 resolvedAnnotation3 = (Annotation3)annotations[0]; + final Annotation3 resolvedAnnotation3 = (Annotation3)annotations[0]; Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 @@ -436,7 +436,7 @@ public class AnnotatedElementUtilTest { public void testToHierarchyMetaElement() { Assert.assertNotNull(AnnotatedElementUtil.toHierarchyMetaElement(null, false)); Assert.assertNotNull(AnnotatedElementUtil.toHierarchyMetaElement(null, true)); - AnnotatedElement element = AnnotatedElementUtil.toHierarchyMetaElement(Foo.class, false); + final AnnotatedElement element = AnnotatedElementUtil.toHierarchyMetaElement(Foo.class, false); // 带有元注解 Assert.assertArrayEquals(ANNOTATIONS, element.getAnnotations()); @@ -445,17 +445,17 @@ public class AnnotatedElementUtilTest { Assert.assertArrayEquals(DECLARED_ANNOTATIONS, element.getDeclaredAnnotations()); // 解析注解属性 - AnnotatedElement resolvedElement = AnnotatedElementUtil.toHierarchyMetaElement(Foo.class, true); - Annotation3 resolvedAnnotation3 = resolvedElement.getAnnotation(Annotation3.class); + final AnnotatedElement resolvedElement = AnnotatedElementUtil.toHierarchyMetaElement(Foo.class, true); + final Annotation3 resolvedAnnotation3 = resolvedElement.getAnnotation(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = resolvedElement.getAnnotation(Annotation2.class); + final Annotation2 resolvedAnnotation2 = resolvedElement.getAnnotation(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = resolvedElement.getAnnotation(Annotation1.class); + final Annotation1 resolvedAnnotation1 = resolvedElement.getAnnotation(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -469,7 +469,7 @@ public class AnnotatedElementUtilTest { public void testToHierarchyRepeatableMetaElement() { Assert.assertNotNull(AnnotatedElementUtil.toHierarchyRepeatableMetaElement(null, false)); Assert.assertNotNull(AnnotatedElementUtil.toHierarchyRepeatableMetaElement(null, true)); - AnnotatedElement element = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, false); + final AnnotatedElement element = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, false); // 带有元注解 Assert.assertArrayEquals(ANNOTATIONS, element.getAnnotations()); @@ -478,17 +478,17 @@ public class AnnotatedElementUtilTest { Assert.assertArrayEquals(DECLARED_ANNOTATIONS, element.getDeclaredAnnotations()); // 解析注解属性 - AnnotatedElement resolvedElement = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, true); - Annotation3 resolvedAnnotation3 = resolvedElement.getAnnotation(Annotation3.class); + final AnnotatedElement resolvedElement = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, true); + final Annotation3 resolvedAnnotation3 = resolvedElement.getAnnotation(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = resolvedElement.getAnnotation(Annotation2.class); + final Annotation2 resolvedAnnotation2 = resolvedElement.getAnnotation(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = resolvedElement.getAnnotation(Annotation1.class); + final Annotation1 resolvedAnnotation1 = resolvedElement.getAnnotation(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -501,7 +501,7 @@ public class AnnotatedElementUtilTest { @Test public void testToHierarchyElement() { Assert.assertNotNull(AnnotatedElementUtil.toHierarchyElement(Foo.class)); - AnnotatedElement element = AnnotatedElementUtil.toHierarchyElement(Foo.class); + final AnnotatedElement element = AnnotatedElementUtil.toHierarchyElement(Foo.class); Assert.assertArrayEquals(new Annotation[]{ANNOTATION3, ANNOTATION4, ANNOTATION6}, element.getAnnotations()); } @@ -520,16 +520,16 @@ public class AnnotatedElementUtilTest { Assert.assertSame(element, AnnotatedElementUtil.toMetaElement(Foo.class, true)); // 第二次获取时从缓存中获取 Assert.assertEquals(3, element.getAnnotations().length); - Annotation3 resolvedAnnotation3 = element.getAnnotation(Annotation3.class); + final Annotation3 resolvedAnnotation3 = element.getAnnotation(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = element.getAnnotation(Annotation2.class); + final Annotation2 resolvedAnnotation2 = element.getAnnotation(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = element.getAnnotation(Annotation1.class); + final Annotation1 resolvedAnnotation1 = element.getAnnotation(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -550,16 +550,16 @@ public class AnnotatedElementUtilTest { Assert.assertEquals(element, AnnotatedElementUtil.toRepeatableMetaElement(Foo.class, RepeatableAnnotationCollector.none(), true)); // 第二次获取时从缓存中获取 Assert.assertEquals(3, element.getAnnotations().length); - Annotation3 resolvedAnnotation3 = element.getAnnotation(Annotation3.class); + final Annotation3 resolvedAnnotation3 = element.getAnnotation(Annotation3.class); Assert.assertNotNull(resolvedAnnotation3); Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value()); Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名 - Annotation2 resolvedAnnotation2 = element.getAnnotation(Annotation2.class); + final Annotation2 resolvedAnnotation2 = element.getAnnotation(Annotation2.class); Assert.assertNotNull(resolvedAnnotation2); Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖 - Annotation1 resolvedAnnotation1 = element.getAnnotation(Annotation1.class); + final Annotation1 resolvedAnnotation1 = element.getAnnotation(Annotation1.class); Assert.assertNotNull(resolvedAnnotation1); Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖 Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名 @@ -567,10 +567,10 @@ public class AnnotatedElementUtilTest { @Test public void testAsElement() { - Annotation[] annotations = new Annotation[]{ANNOTATION1, ANNOTATION2}; + final Annotation[] annotations = new Annotation[]{ANNOTATION1, ANNOTATION2}; Assert.assertNotNull(AnnotatedElementUtil.asElement()); - AnnotatedElement element = AnnotatedElementUtil.asElement(ANNOTATION1, null, ANNOTATION2); + final AnnotatedElement element = AnnotatedElementUtil.asElement(ANNOTATION1, null, ANNOTATION2); Assert.assertArrayEquals(annotations, element.getAnnotations()); Assert.assertArrayEquals(annotations, element.getDeclaredAnnotations()); Assert.assertEquals(ANNOTATION1, element.getAnnotation(Annotation1.class)); @@ -579,7 +579,7 @@ public class AnnotatedElementUtilTest { @Test public void testEmptyElement() { - AnnotatedElement element = AnnotatedElementUtil.emptyElement(); + final AnnotatedElement element = AnnotatedElementUtil.emptyElement(); Assert.assertSame(element, AnnotatedElementUtil.emptyElement()); Assert.assertNull(element.getAnnotation(Annotation1.class)); Assert.assertEquals(0, element.getAnnotations().length); diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/CombinationAnnotationElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/CombinationAnnotationElementTest.java index cb81ef2cb..b4fb77fdc 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/CombinationAnnotationElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/CombinationAnnotationElementTest.java @@ -12,36 +12,36 @@ public class CombinationAnnotationElementTest { @Test public void testOf() { - CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); + final CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); Assert.assertNotNull(element); } @Test public void testIsAnnotationPresent() { - CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); + final CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); Assert.assertTrue(element.isAnnotationPresent(MetaAnnotationForTest.class)); } @Test public void testGetAnnotation() { - AnnotationForTest annotation1 = ClassForTest.class.getAnnotation(AnnotationForTest.class); - MetaAnnotationForTest annotation2 = AnnotationForTest.class.getAnnotation(MetaAnnotationForTest.class); - CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); + final AnnotationForTest annotation1 = ClassForTest.class.getAnnotation(AnnotationForTest.class); + final MetaAnnotationForTest annotation2 = AnnotationForTest.class.getAnnotation(MetaAnnotationForTest.class); + final CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); Assert.assertEquals(annotation1, element.getAnnotation(AnnotationForTest.class)); Assert.assertEquals(annotation2, element.getAnnotation(MetaAnnotationForTest.class)); } @Test public void testGetAnnotations() { - CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); - Annotation[] annotations = element.getAnnotations(); + final CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); + final Annotation[] annotations = element.getAnnotations(); Assert.assertEquals(2, annotations.length); } @Test public void testGetDeclaredAnnotations() { - CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); - Annotation[] annotations = element.getDeclaredAnnotations(); + final CombinationAnnotationElement element = CombinationAnnotationElement.of(ClassForTest.class, a -> true); + final Annotation[] annotations = element.getDeclaredAnnotations(); Assert.assertEquals(2, annotations.length); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java index 011cf1419..46b5cea04 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java @@ -19,8 +19,8 @@ public class GenericAnnotationMappingTest { @Test public void testEquals() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertEquals(mapping, mapping); Assert.assertNotEquals(mapping, null); Assert.assertEquals(mapping, GenericAnnotationMapping.create(annotation, false)); @@ -29,8 +29,8 @@ public class GenericAnnotationMappingTest { @Test public void testHashCode() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - int hashCode = GenericAnnotationMapping.create(annotation, false).hashCode(); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final int hashCode = GenericAnnotationMapping.create(annotation, false).hashCode(); Assert.assertEquals(hashCode, GenericAnnotationMapping.create(annotation, false).hashCode()); Assert.assertNotEquals(hashCode, GenericAnnotationMapping.create(annotation, true).hashCode()); } @@ -38,14 +38,14 @@ public class GenericAnnotationMappingTest { @Test public void testCreate() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertNotNull(mapping); } @Test public void testIsRoot() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, true); Assert.assertTrue(mapping.isRoot()); @@ -55,55 +55,55 @@ public class GenericAnnotationMappingTest { @Test public void testGetAnnotation() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertSame(annotation, mapping.getAnnotation()); } @SneakyThrows @Test public void testGetAttributes() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); for (int i = 0; i < mapping.getAttributes().length; i++) { - Method method = mapping.getAttributes()[i]; + final Method method = mapping.getAttributes()[i]; Assert.assertEquals(Annotation1.class.getDeclaredMethod(method.getName()), method); } } @Test public void testAnnotationType() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertEquals(annotation.annotationType(), mapping.annotationType()); } @Test public void testIsResolved() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertFalse(mapping.isResolved()); } @Test public void testGetAttributeValue() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertEquals(annotation.value(), mapping.getAttributeValue("value", String.class)); Assert.assertNull(mapping.getAttributeValue("value", Integer.class)); } @Test public void testGetResolvedAnnotation() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertSame(annotation, mapping.getResolvedAnnotation()); } @Test public void testGetResolvedAttributeValue() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final GenericAnnotationMapping mapping = GenericAnnotationMapping.create(annotation, false); Assert.assertEquals(annotation.value(), mapping.getResolvedAttributeValue("value", String.class)); Assert.assertNull(mapping.getResolvedAttributeValue("value", Integer.class)); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java index f4e8a0034..62f577fd1 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java @@ -22,11 +22,11 @@ public class HierarchicalAnnotatedElementTest { @SneakyThrows @Test public void testCreateFromMethod() { - Method method1 = Foo.class.getDeclaredMethod("method"); + final Method method1 = Foo.class.getDeclaredMethod("method"); HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(method1); Assert.assertEquals(3, elements.getElementMappings().size()); - Method method2 = Foo.class.getDeclaredMethod("method2"); + final Method method2 = Foo.class.getDeclaredMethod("method2"); elements = HierarchicalAnnotatedElements.create(method2); Assert.assertEquals(1, elements.getElementMappings().size()); } @@ -46,7 +46,7 @@ public class HierarchicalAnnotatedElementTest { @Test public void testEquals() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY); Assert.assertEquals(elements, elements); Assert.assertEquals(elements, HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY)); Assert.assertNotEquals(elements, HierarchicalAnnotatedElements.create(Super.class, ELEMENT_MAPPING_FACTORY)); @@ -56,7 +56,7 @@ public class HierarchicalAnnotatedElementTest { @Test public void testHashCode() { - int hashCode = HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY).hashCode(); + final int hashCode = HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY).hashCode(); Assert.assertEquals(hashCode, HierarchicalAnnotatedElements.create(Foo.class, ELEMENT_MAPPING_FACTORY).hashCode()); Assert.assertNotEquals(hashCode, HierarchicalAnnotatedElements.create(Super.class, ELEMENT_MAPPING_FACTORY).hashCode()); Assert.assertNotEquals(hashCode, HierarchicalAnnotatedElements.create(Foo.class, (es, e) -> e).hashCode()); @@ -64,14 +64,14 @@ public class HierarchicalAnnotatedElementTest { @Test public void testGetElement() { - AnnotatedElement element = Foo.class; - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(element, ELEMENT_MAPPING_FACTORY); + final AnnotatedElement element = Foo.class; + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(element, ELEMENT_MAPPING_FACTORY); Assert.assertSame(element, elements.getElement()); } @Test public void testIsAnnotationPresent() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); Assert.assertTrue(elements.isAnnotationPresent(Annotation1.class)); Assert.assertTrue(elements.isAnnotationPresent(Annotation2.class)); Assert.assertTrue(elements.isAnnotationPresent(Annotation3.class)); @@ -79,91 +79,91 @@ public class HierarchicalAnnotatedElementTest { @Test public void testGetAnnotations() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); - Annotation[] annotations = new Annotation[]{ annotation1, annotation2, annotation3 }; + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation[] annotations = new Annotation[]{ annotation1, annotation2, annotation3 }; Assert.assertArrayEquals(annotations, elements.getAnnotations()); } @Test public void testGetAnnotation() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); Assert.assertEquals(annotation1, elements.getAnnotation(Annotation1.class)); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); Assert.assertEquals(annotation2, elements.getAnnotation(Annotation2.class)); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); Assert.assertEquals(annotation3, elements.getAnnotation(Annotation3.class)); } @Test public void testGetAnnotationsByType() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); Assert.assertArrayEquals(new Annotation[]{ annotation1 }, elements.getAnnotationsByType(Annotation1.class)); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); Assert.assertArrayEquals(new Annotation[]{ annotation2 }, elements.getAnnotationsByType(Annotation2.class)); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); Assert.assertArrayEquals(new Annotation[]{ annotation3 }, elements.getAnnotationsByType(Annotation3.class)); } @Test public void testGetDeclaredAnnotationsByType() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); Assert.assertArrayEquals(new Annotation[]{ annotation1 }, elements.getDeclaredAnnotationsByType(Annotation1.class)); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); Assert.assertArrayEquals(new Annotation[]{ annotation2 }, elements.getDeclaredAnnotationsByType(Annotation2.class)); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); Assert.assertArrayEquals(new Annotation[]{ annotation3 }, elements.getDeclaredAnnotationsByType(Annotation3.class)); } @Test public void testGetDeclaredAnnotation() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); Assert.assertEquals(annotation1, elements.getDeclaredAnnotation(Annotation1.class)); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); Assert.assertEquals(annotation2, elements.getDeclaredAnnotation(Annotation2.class)); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); Assert.assertEquals(annotation3, elements.getDeclaredAnnotation(Annotation3.class)); } @Test public void testGetDeclaredAnnotations() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); - Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); - Annotation[] annotations = new Annotation[]{ annotation1, annotation2, annotation3 }; + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation2 annotation2 = Super.class.getAnnotation(Annotation2.class); + final Annotation3 annotation3 = Interface.class.getAnnotation(Annotation3.class); + final Annotation[] annotations = new Annotation[]{ annotation1, annotation2, annotation3 }; Assert.assertArrayEquals(annotations, elements.getDeclaredAnnotations()); } @Test public void testIterator() { - HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); - Iterator iterator = elements.iterator(); + final HierarchicalAnnotatedElements elements = HierarchicalAnnotatedElements.create(Foo.class); + final Iterator iterator = elements.iterator(); Assert.assertNotNull(iterator); - List elementList = new ArrayList<>(); + final List elementList = new ArrayList<>(); iterator.forEachRemaining(elementList::add); Assert.assertEquals(Arrays.asList(Foo.class, Super.class, Interface.class), elementList); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java index f4cdfdc1d..ff79d53f9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java @@ -26,7 +26,7 @@ public class MetaAnnotatedElementTest { @Test public void testEquals() { - AnnotatedElement element = new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY); + final AnnotatedElement element = new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY); Assert.assertEquals(element, element); Assert.assertNotEquals(element, null); Assert.assertEquals(element, new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY)); @@ -36,7 +36,7 @@ public class MetaAnnotatedElementTest { @Test public void testHashCode() { - int hashCode = new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode(); + final int hashCode = new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode(); Assert.assertEquals(hashCode, new MetaAnnotatedElement<>(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode()); Assert.assertNotEquals(hashCode, new MetaAnnotatedElement<>(Foo.class, MAPPING_FACTORY).hashCode()); } @@ -44,15 +44,15 @@ public class MetaAnnotatedElementTest { @Test public void testCreate() { // 第二次创建时优先从缓存中获取 - AnnotatedElement resolvedElement = MetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY); + final AnnotatedElement resolvedElement = MetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY); Assert.assertEquals(resolvedElement, MetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY)); - AnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final AnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); Assert.assertEquals(element, MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY)); } @Test public void testGetMapping() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); Assert.assertTrue(element.getMapping(Annotation1.class).isPresent()); Assert.assertTrue(element.getMapping(Annotation2.class).isPresent()); Assert.assertTrue(element.getMapping(Annotation3.class).isPresent()); @@ -61,7 +61,7 @@ public class MetaAnnotatedElementTest { @Test public void testGetDeclaredMapping() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); Assert.assertFalse(element.getDeclaredMapping(Annotation1.class).isPresent()); Assert.assertFalse(element.getDeclaredMapping(Annotation2.class).isPresent()); Assert.assertTrue(element.getDeclaredMapping(Annotation3.class).isPresent()); @@ -70,7 +70,7 @@ public class MetaAnnotatedElementTest { @Test public void testIsAnnotationPresent() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); Assert.assertTrue(element.isAnnotationPresent(Annotation1.class)); Assert.assertTrue(element.isAnnotationPresent(Annotation2.class)); Assert.assertTrue(element.isAnnotationPresent(Annotation3.class)); @@ -79,11 +79,11 @@ public class MetaAnnotatedElementTest { @Test public void testGetAnnotation() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); - Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); + final Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); Assert.assertEquals(annotation1, element.getAnnotation(Annotation1.class)); Assert.assertEquals(annotation2, element.getAnnotation(Annotation2.class)); @@ -93,9 +93,9 @@ public class MetaAnnotatedElementTest { @Test public void testGetDeclaredAnnotation() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertNull(element.getDeclaredAnnotation(Annotation1.class)); Assert.assertNull(element.getDeclaredAnnotation(Annotation2.class)); @@ -105,8 +105,8 @@ public class MetaAnnotatedElementTest { @Test public void testGetAnnotationByType() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); Assert.assertArrayEquals( new Annotation[]{ annotation4 }, element.getAnnotationsByType(Annotation4.class) @@ -116,8 +116,8 @@ public class MetaAnnotatedElementTest { @Test public void testGetDeclaredAnnotationByType() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); Assert.assertArrayEquals( new Annotation[]{ annotation4 }, element.getDeclaredAnnotationsByType(Annotation4.class) @@ -127,37 +127,37 @@ public class MetaAnnotatedElementTest { @Test public void testGetAnnotations() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); - Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); - Annotation[] annotations = new Annotation[]{ annotation3, annotation4, annotation2, annotation1 }; + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); + final Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); + final Annotation[] annotations = new Annotation[]{ annotation3, annotation4, annotation2, annotation1 }; Assert.assertArrayEquals(annotations, element.getAnnotations()); } @Test public void testGetDeclaredAnnotations() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - Annotation[] annotations = new Annotation[]{ annotation3, annotation4 }; + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation[] annotations = new Annotation[]{ annotation3, annotation4 }; Assert.assertArrayEquals(annotations, element.getDeclaredAnnotations()); } @Test public void testIterator() { - MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); - Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); - Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); - Annotation[] annotations = new Annotation[]{ annotation3, annotation4, annotation2, annotation1 }; + final MetaAnnotatedElement element = MetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY); + final Annotation4 annotation4 = Foo.class.getAnnotation(Annotation4.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation2 annotation2 = Annotation3.class.getAnnotation(Annotation2.class); + final Annotation1 annotation1 = Annotation2.class.getAnnotation(Annotation1.class); + final Annotation[] annotations = new Annotation[]{ annotation3, annotation4, annotation2, annotation1 }; - Iterator iterator = element.iterator(); - List mappingList = new ArrayList<>(); + final Iterator iterator = element.iterator(); + final List mappingList = new ArrayList<>(); iterator.forEachRemaining(mapping -> mappingList.add(mapping.getAnnotation())); Assert.assertEquals(Arrays.asList(annotations), mappingList); @@ -165,8 +165,8 @@ public class MetaAnnotatedElementTest { @Test public void testGetElement() { - AnnotatedElement source = Foo.class; - MetaAnnotatedElement element = MetaAnnotatedElement.create(source, MAPPING_FACTORY); + final AnnotatedElement source = Foo.class; + final MetaAnnotatedElement element = MetaAnnotatedElement.create(source, MAPPING_FACTORY); Assert.assertSame(source, element.getElement()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableAnnotationCollectorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableAnnotationCollectorTest.java index ac9386a57..098fe81f6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableAnnotationCollectorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableAnnotationCollectorTest.java @@ -52,15 +52,15 @@ public class RepeatableAnnotationCollectorTest { @Test public void testNone() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none(); Assert.assertSame(collector, RepeatableAnnotationCollector.none()); Assert.assertEquals(0, collector.getFinalRepeatableAnnotations(null).size()); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); Assert.assertEquals(Collections.singletonList(annotation), collector.getFinalRepeatableAnnotations(annotation)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getFinalRepeatableAnnotations(annotation3)); Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, Annotation3.class)); @@ -70,32 +70,32 @@ public class RepeatableAnnotationCollectorTest { @Test public void testNoneWhenAccumulate() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none(); Assert.assertSame(collector, RepeatableAnnotationCollector.none()); Assert.assertEquals(0, collector.getAllRepeatableAnnotations(null).size()); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); Assert.assertEquals(Collections.singletonList(annotation), collector.getAllRepeatableAnnotations(annotation)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getAllRepeatableAnnotations(annotation3)); } @Test public void testGenericCollector() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard(); Assert.assertSame(collector, RepeatableAnnotationCollector.standard()); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - List annotations = Stream.of(annotation.value()) + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final List annotations = Stream.of(annotation.value()) .map(Annotation2::value) .flatMap(Stream::of) .collect(Collectors.toList()); Assert.assertEquals(annotations, collector.getFinalRepeatableAnnotations(annotation)); Assert.assertEquals(ANNOTATION3S, collector.getFinalRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getFinalRepeatableAnnotations(annotation3)); Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class)); @@ -105,11 +105,11 @@ public class RepeatableAnnotationCollectorTest { @Test public void testGenericCollectorWhenAccumulate() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard(); Assert.assertSame(collector, RepeatableAnnotationCollector.standard()); - List annotations = new ArrayList<>(); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final List annotations = new ArrayList<>(); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); annotations.add(annotation); annotations.addAll(Arrays.asList(annotation.value())); Stream.of(annotation.value()) @@ -120,15 +120,15 @@ public class RepeatableAnnotationCollectorTest { Assert.assertEquals(ANNOTATIONS, collector.getAllRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getAllRepeatableAnnotations(annotation3)); } @Test public void testConditionCollector() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - List annotations = Stream.of(annotation.value()) + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final List annotations = Stream.of(annotation.value()) .map(Annotation2::value) .flatMap(Stream::of) .collect(Collectors.toList()); @@ -136,7 +136,7 @@ public class RepeatableAnnotationCollectorTest { Assert.assertEquals(ANNOTATION3S, collector.getFinalRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getFinalRepeatableAnnotations(annotation3)); Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class)); @@ -146,10 +146,10 @@ public class RepeatableAnnotationCollectorTest { @Test public void testConditionCollectorWhenAccumulate() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE); - List annotations = new ArrayList<>(); - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final List annotations = new ArrayList<>(); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); annotations.add(annotation); annotations.addAll(Arrays.asList(annotation.value())); Stream.of(annotation.value()) @@ -159,18 +159,18 @@ public class RepeatableAnnotationCollectorTest { Assert.assertEquals(annotations, collector.getAllRepeatableAnnotations(annotation)); Assert.assertEquals(ANNOTATIONS, collector.getAllRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getAllRepeatableAnnotations((annotation3))); } @Test public void testFullCollector() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full(); Assert.assertSame(collector, RepeatableAnnotationCollector.full()); Assert.assertEquals(ANNOTATION3S, collector.getFinalRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getFinalRepeatableAnnotations(annotation3)); Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class)); @@ -180,12 +180,12 @@ public class RepeatableAnnotationCollectorTest { @Test public void testFullCollectorWhenAccumulate() { - RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full(); + final RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full(); Assert.assertSame(collector, RepeatableAnnotationCollector.full()); Assert.assertEquals(ANNOTATIONS, collector.getAllRepeatableAnnotations(ANNOTATION1)); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals(Collections.singletonList(annotation3), collector.getAllRepeatableAnnotations(annotation3)); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableMetaAnnotatedElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableMetaAnnotatedElementTest.java index 2fc38fe03..26afe079d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableMetaAnnotatedElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatableMetaAnnotatedElementTest.java @@ -28,7 +28,7 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testEquals() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY); + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY); Assert.assertEquals(element, element); Assert.assertNotEquals(element, null); Assert.assertEquals(element, RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY)); @@ -38,7 +38,7 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testHashCode() { - int hashCode = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode(); + final int hashCode = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode(); Assert.assertEquals(hashCode, RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode()); Assert.assertNotEquals(hashCode, RepeatableMetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY).hashCode()); Assert.assertNotEquals(hashCode, RepeatableMetaAnnotatedElement.create(Annotation1.class, MAPPING_FACTORY).hashCode()); @@ -46,7 +46,7 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testIsAnnotationPresent() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); Assert.assertTrue(element.isAnnotationPresent(Annotation1.class)); @@ -57,13 +57,13 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetAnnotations() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); - List> annotationTypes = Arrays.stream(element.getAnnotations()) + final List> annotationTypes = Arrays.stream(element.getAnnotations()) .map(Annotation::annotationType) .collect(Collectors.toList()); - Map, Integer> countMap = IterUtil.countMap(annotationTypes.iterator()); + final Map, Integer> countMap = IterUtil.countMap(annotationTypes.iterator()); Assert.assertEquals((Integer)1, countMap.get(Annotation1.class)); Assert.assertEquals((Integer)2, countMap.get(Annotation2.class)); @@ -73,26 +73,26 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetAnnotation() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); Assert.assertEquals(annotation1, element.getAnnotation(Annotation1.class)); - Annotation4 annotation4 = Annotation1.class.getAnnotation(Annotation4.class); + final Annotation4 annotation4 = Annotation1.class.getAnnotation(Annotation4.class); Assert.assertEquals(annotation4, element.getAnnotation(Annotation4.class)); - Annotation2 annotation2 = annotation1.value()[0]; + final Annotation2 annotation2 = annotation1.value()[0]; Assert.assertEquals(annotation2, element.getAnnotation(Annotation2.class)); - Annotation3 annotation3 = annotation2.value()[0]; + final Annotation3 annotation3 = annotation2.value()[0]; Assert.assertEquals(annotation3, element.getAnnotation(Annotation3.class)); } @Test public void testGetAnnotationsByType() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); @@ -111,13 +111,13 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetDeclaredAnnotations() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); - List> annotationTypes = Arrays.stream(element.getDeclaredAnnotations()) + final List> annotationTypes = Arrays.stream(element.getDeclaredAnnotations()) .map(Annotation::annotationType) .collect(Collectors.toList()); - Map, Integer> countMap = IterUtil.countMap(annotationTypes.iterator()); + final Map, Integer> countMap = IterUtil.countMap(annotationTypes.iterator()); Assert.assertEquals((Integer)1, countMap.get(Annotation1.class)); Assert.assertFalse(countMap.containsKey(Annotation2.class)); @@ -127,11 +127,11 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetDeclaredAnnotation() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); - Annotation1 annotation1 = Foo.class.getDeclaredAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getDeclaredAnnotation(Annotation1.class); Assert.assertEquals(annotation1, element.getDeclaredAnnotation(Annotation1.class)); Assert.assertNull(element.getDeclaredAnnotation(Annotation3.class)); Assert.assertNull(element.getDeclaredAnnotation(Annotation4.class)); @@ -140,7 +140,7 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetDeclaredAnnotationsByType() { - AnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); @@ -159,8 +159,8 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testGetElement() { - AnnotatedElement element = Foo.class; - RepeatableMetaAnnotatedElement repeatableMetaAnnotatedElement = RepeatableMetaAnnotatedElement.create( + final AnnotatedElement element = Foo.class; + final RepeatableMetaAnnotatedElement repeatableMetaAnnotatedElement = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), element, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); Assert.assertSame(element, repeatableMetaAnnotatedElement.getElement()); @@ -168,11 +168,11 @@ public class RepeatableMetaAnnotatedElementTest { @Test public void testIterator() { - RepeatableMetaAnnotatedElement element = RepeatableMetaAnnotatedElement.create( + final RepeatableMetaAnnotatedElement element = RepeatableMetaAnnotatedElement.create( RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s)) ); int count = 0; - for (GenericAnnotationMapping mapping : element) { + for (final GenericAnnotationMapping mapping : element) { count++; } Assert.assertEquals(14, count); diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java index adb56f25e..5da4e047b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java @@ -19,15 +19,15 @@ public class ResolvedAnnotationMappingTest { @Test public void testEquals() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); Assert.assertEquals(mapping, mapping); Assert.assertNotEquals(null, mapping); Assert.assertEquals(mapping, ResolvedAnnotationMapping.create(annotation, false)); Assert.assertNotEquals(mapping, ResolvedAnnotationMapping.create(annotation, true)); // Annotation3没有需要解析的属性,因此即使在构造函数指定false也一样 - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals( ResolvedAnnotationMapping.create(annotation3, false), ResolvedAnnotationMapping.create(annotation3, true) @@ -36,13 +36,13 @@ public class ResolvedAnnotationMappingTest { @Test public void testHashCode() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - int hashCode = ResolvedAnnotationMapping.create(annotation, false).hashCode(); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final int hashCode = ResolvedAnnotationMapping.create(annotation, false).hashCode(); Assert.assertEquals(hashCode, ResolvedAnnotationMapping.create(annotation, false).hashCode()); Assert.assertNotEquals(hashCode, ResolvedAnnotationMapping.create(annotation, true).hashCode()); // Annotation3没有需要解析的属性,因此即使在构造函数指定false也一样 - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertEquals( ResolvedAnnotationMapping.create(annotation3, false).hashCode(), ResolvedAnnotationMapping.create(annotation3, true).hashCode() @@ -52,92 +52,92 @@ public class ResolvedAnnotationMappingTest { @Test public void testCreate() { - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); Assert.assertNotNull(mapping3); - Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); - ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); + final Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); + final ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); Assert.assertNotNull(mapping2); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, false); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, false); Assert.assertNotNull(mapping1); } @Test public void testIsRoot() { - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); Assert.assertTrue(mapping3.isRoot()); - Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); - ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); + final Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); + final ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); Assert.assertFalse(mapping2.isRoot()); } @Test public void testGetRoot() { - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, false); Assert.assertSame(mapping3, mapping3.getRoot()); - Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); - ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); + final Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); + final ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, false); Assert.assertSame(mapping3, mapping2.getRoot()); - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, false); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, false); Assert.assertSame(mapping3, mapping1.getRoot()); } @Test public void testGetAnnotation() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); Assert.assertSame(annotation, mapping.getAnnotation()); } @SneakyThrows @Test public void testGetAttributes() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); for (int i = 0; i < mapping.getAttributes().length; i++) { - Method method = mapping.getAttributes()[i]; + final Method method = mapping.getAttributes()[i]; Assert.assertEquals(Annotation1.class.getDeclaredMethod(method.getName()), method); } } @Test public void testHasAttribute() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); Assert.assertTrue(mapping.hasAttribute("value", String.class)); Assert.assertFalse(mapping.hasAttribute("value", Integer.class)); - int index = mapping.getAttributeIndex("value", String.class); + final int index = mapping.getAttributeIndex("value", String.class); Assert.assertTrue(mapping.hasAttribute(index)); Assert.assertFalse(mapping.hasAttribute(Integer.MIN_VALUE)); } @Test public void testAnnotationType() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); Assert.assertEquals(annotation.annotationType(), mapping.annotationType()); } @Test public void testIsResolved() { - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(annotation1, true); + final ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(annotation1, true); Assert.assertTrue(mapping1.isResolved()); Assert.assertFalse(ResolvedAnnotationMapping.create(annotation1, false).isResolved()); - Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); + final Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(annotation2, true); Assert.assertFalse(mapping2.isResolved()); @@ -147,10 +147,10 @@ public class ResolvedAnnotationMappingTest { @Test public void testGetAttributeIndex() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); for (int i = 0; i < mapping.getAttributes().length; i++) { - Method method = mapping.getAttributes()[i]; + final Method method = mapping.getAttributes()[i]; Assert.assertEquals(i, mapping.getAttributeIndex(method.getName(), method.getReturnType())); } Assert.assertEquals(ResolvedAnnotationMapping.NOT_FOUND_INDEX, mapping.getAttributeIndex("value", Void.class)); @@ -159,29 +159,29 @@ public class ResolvedAnnotationMappingTest { @Test public void testGetAttributeValue() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, false); Assert.assertNull(mapping.getAttribute(Integer.MAX_VALUE)); - int valueIdx = mapping.getAttributeIndex("value", String.class); + final int valueIdx = mapping.getAttributeIndex("value", String.class); Assert.assertEquals(annotation.value(), mapping.getAttributeValue(valueIdx)); Assert.assertEquals(annotation.value(), mapping.getAttributeValue("value", String.class)); - int name1Idx = mapping.getAttributeIndex("value1", String.class); + final int name1Idx = mapping.getAttributeIndex("value1", String.class); Assert.assertEquals(annotation.value1(), mapping.getAttributeValue(name1Idx)); Assert.assertEquals(annotation.value1(), mapping.getAttributeValue("value1", String.class)); - int name2Idx = mapping.getAttributeIndex("value2", String.class); + final int name2Idx = mapping.getAttributeIndex("value2", String.class); Assert.assertEquals(annotation.value2(), mapping.getAttributeValue(name2Idx)); Assert.assertEquals(annotation.value2(), mapping.getAttributeValue("value2", String.class)); } @Test public void testGetResolvedAnnotation() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, true); - Annotation1 synthesis = (Annotation1)mapping.getResolvedAnnotation(); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, true); + final Annotation1 synthesis = (Annotation1)mapping.getResolvedAnnotation(); Assert.assertEquals(annotation.annotationType(), synthesis.annotationType()); Assert.assertEquals(annotation.value(), synthesis.value()); @@ -195,7 +195,7 @@ public class ResolvedAnnotationMappingTest { Assert.assertNotEquals(synthesis.hashCode(), annotation.hashCode()); Assert.assertNotEquals(synthesis.toString(), annotation.toString()); - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); Assert.assertSame(annotation3, ResolvedAnnotationMapping.create(annotation3, true).getResolvedAnnotation()); } @@ -203,8 +203,8 @@ public class ResolvedAnnotationMappingTest { @Test public void testGetResolvedAttributeValueWhenAliased() { - Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, true); + final Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping = ResolvedAnnotationMapping.create(annotation, true); Assert.assertNull(mapping.getResolvedAttributeValue(Integer.MIN_VALUE)); // value = value1 = value2 @@ -232,20 +232,20 @@ public class ResolvedAnnotationMappingTest { @Test public void testGetResolvedAttributeWhenOverwritten() { - Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); - ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, true); + final Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class); + final ResolvedAnnotationMapping mapping3 = ResolvedAnnotationMapping.create(annotation3, true); Assert.assertEquals(annotation3.value(), mapping3.getResolvedAttributeValue("value", String.class)); Assert.assertEquals((Integer)annotation3.alias(), mapping3.getResolvedAttributeValue("alias", Integer.class)); // annotation2中与annotation3同名同类型的属性value、alias被覆写 - Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); - ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, true); + final Annotation2 annotation2 = Foo.class.getAnnotation(Annotation2.class); + final ResolvedAnnotationMapping mapping2 = ResolvedAnnotationMapping.create(mapping3, annotation2, true); Assert.assertEquals(annotation3.value(), mapping2.getResolvedAttributeValue("value", String.class)); Assert.assertEquals((Integer)annotation3.alias(), mapping2.getResolvedAttributeValue("alias", Integer.class)); // annotation1中与annotation3同名同类型的属性value被覆写,由于value存在别名value1,value2因此也一并被覆写 - Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); - ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, true); + final Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class); + final ResolvedAnnotationMapping mapping1 = ResolvedAnnotationMapping.create(mapping2, annotation1, true); Assert.assertEquals(annotation3.value(), mapping1.getResolvedAttributeValue("value", String.class)); Assert.assertEquals(annotation3.value(), mapping1.getResolvedAttributeValue("value1", String.class)); Assert.assertEquals(annotation3.value(), mapping1.getResolvedAttributeValue("value2", String.class)); @@ -253,6 +253,7 @@ public class ResolvedAnnotationMappingTest { Assert.assertEquals(annotation1.alias(), mapping1.getResolvedAttributeValue("alias", String.class)); } + @SuppressWarnings("unused") @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME) private @interface Annotation1 { From 5b559d19bd76385f9189e2ae4a7bf34ad6bfee36 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 01:11:43 +0800 Subject: [PATCH 112/125] fix code --- hutool-all/pom.xml | 63 ------------------- .../java/cn/hutool/core/codec/HexUtil.java | 2 +- .../cn/hutool/core/codec/PercentCodec.java | 2 +- .../codec/{BaseN => binary}/Base16Codec.java | 4 +- .../core/codec/{BaseN => binary}/Base32.java | 2 +- .../codec/{BaseN => binary}/Base32Codec.java | 5 +- .../core/codec/{BaseN => binary}/Base58.java | 2 +- .../codec/{BaseN => binary}/Base58Codec.java | 2 +- .../core/codec/{BaseN => binary}/Base62.java | 2 +- .../codec/{BaseN => binary}/Base62Codec.java | 2 +- .../core/codec/{BaseN => binary}/Base64.java | 2 +- .../{BaseN => binary}/Base64Decoder.java | 5 +- .../core/codec/binary/package-info.java | 11 ++++ .../core/convert/impl/ArrayConverter.java | 2 +- .../core/date/TemporalAccessorUtil.java | 2 - .../date/format/parser/CSTDateParser.java | 5 +- .../date/format/parser/NormalDateParser.java | 4 ++ .../format/parser/PatternsDateParser.java | 1 + .../date/format/parser/PureDateParser.java | 4 ++ .../core/date/format/parser/TimeParser.java | 4 ++ .../date/format/parser/UTCDateParser.java | 1 + .../InvocationTargetRuntimeException.java | 50 +++++++++++++-- .../hutool/core/exceptions/UtilException.java | 16 ++--- .../main/java/cn/hutool/core/io/IoUtil.java | 13 ++++ .../cn/hutool/core/io/file/PathCopier.java | 1 - .../cn/hutool/core/io/file/PathMover.java | 2 +- .../core/io/stream/EmptyOutputStream.java | 4 +- .../core/map/ReferenceConcurrentMap.java | 1 + .../core/map/multi/AbsCollValueMap.java | 26 ++++---- .../java/cn/hutool/core/map/multi/Graph.java | 1 + .../cn/hutool/core/thread/SyncFinisher.java | 4 +- .../annotation/AnnotatedElementUtilTest.java | 4 +- .../GenericAnnotationMappingTest.java | 2 +- .../HierarchicalAnnotatedElementTest.java | 2 +- .../annotation/MetaAnnotatedElementTest.java | 2 +- .../ResolvedAnnotationMappingTest.java | 2 +- .../java/cn/hutool/core/codec/Base32Test.java | 2 +- .../java/cn/hutool/core/codec/Base58Test.java | 2 +- .../java/cn/hutool/core/codec/Base62Test.java | 2 +- .../java/cn/hutool/core/codec/Base64Test.java | 2 +- .../core/collection/CollStreamUtilTest.java | 5 +- .../convert/NumberChineseFormatterTest.java | 4 +- .../java/cn/hutool/core/io/NioUtilTest.java | 2 +- .../java/cn/hutool/core/lang/AssertTest.java | 11 ++-- .../hutool/core/stream/EntryStreamTest.java | 40 ++++++++---- .../java/cn/hutool/core/util/ObjUtilTest.java | 6 +- .../cn/hutool/cron/TaskExecutorManager.java | 3 - .../cn/hutool/cron/TaskLauncherManager.java | 7 ++- .../main/java/cn/hutool/crypto/KeyUtil.java | 2 +- .../java/cn/hutool/crypto/SecureUtil.java | 2 +- .../crypto/asymmetric/AsymmetricCrypto.java | 2 +- .../asymmetric/AsymmetricEncryptor.java | 2 +- .../crypto/asymmetric/BaseAsymmetric.java | 2 +- .../cn/hutool/crypto/asymmetric/Sign.java | 2 +- .../java/cn/hutool/crypto/digest/mac/Mac.java | 2 +- .../cn/hutool/crypto/digest/otp/HOTP.java | 2 +- .../java/cn/hutool/crypto/symmetric/RC4.java | 2 +- .../crypto/symmetric/SymmetricEncryptor.java | 2 +- .../cn/hutool/crypto/asymmetric/RSATest.java | 2 +- .../cn/hutool/crypto/asymmetric/SM2Test.java | 2 +- .../java/cn/hutool/crypto/digest/OTPTest.java | 2 +- .../cn/hutool/crypto/symmetric/AESTest.java | 2 +- .../java/cn/hutool/db/meta/ResultColumn.java | 18 +++--- .../java/cn/hutool/db/sql/ConditionGroup.java | 1 + .../src/test/java/cn/hutool/db/DerbyTest.java | 7 +-- .../cn/hutool/extra/mail/MailAccount.java | 5 +- .../cn/hutool/extra/qrcode/QrCodeUtil.java | 2 +- .../main/java/cn/hutool/extra/ssh/Sftp.java | 5 +- .../java/cn/hutool/extra/ftp/FtpTest.java | 2 +- .../hutool/extra/qrcode/QrCodeUtilTest.java | 2 +- .../cn/hutool/extra/ssh/JschUtilTest.java | 6 +- .../main/java/cn/hutool/http/HttpUtil.java | 2 +- .../httpclient5/HttpClient5BodyEntity.java | 5 +- .../client/engine/jdk/HttpConnection.java | 4 -- .../client/engine/jdk/JdkClientEngine.java | 2 +- .../client/engine/okhttp/OkHttpEngine.java | 5 +- .../client/engine/okhttp/OkHttpResponse.java | 13 ++-- .../java/cn/hutool/http/html/HTMLFilter.java | 33 ++++++---- .../java/cn/hutool/http/DownloadTest.java | 2 +- .../main/java/cn/hutool/json/jwt/Claims.java | 2 +- .../src/main/java/cn/hutool/json/jwt/JWT.java | 2 +- .../json/jwt/signers/AsymmetricJWTSigner.java | 2 +- .../log/dialect/logtube/LogTubeLog.java | 1 + .../src/test/java/cn/hutool/log/LogTest.java | 3 - .../java/cn/hutool/poi/csv/CsvParser.java | 21 ++++--- .../java/cn/hutool/poi/csv/CsvReader.java | 16 ++--- .../cn/hutool/poi/excel/cell/NullCell.java | 10 --- .../java/cn/hutool/poi/csv/Issue2783Test.java | 12 ++-- .../java/cn/hutool/setting/GroupedSet.java | 5 +- .../java/cn/hutool/setting/SettingLoader.java | 4 +- .../hutool/swing/captcha/AbstractCaptcha.java | 2 +- .../swing/clipboard/ClipboardMonitor.java | 39 ++---------- .../hutool/swing/clipboard/ClipboardUtil.java | 23 +++++-- .../java/cn/hutool/swing/img/ImgUtil.java | 2 +- 94 files changed, 320 insertions(+), 309 deletions(-) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base16Codec.java (98%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base32.java (99%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base32Codec.java (98%) mode change 100755 => 100644 rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base58.java (99%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base58Codec.java (99%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base62.java (99%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base62Codec.java (99%) rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base64.java (99%) mode change 100755 => 100644 rename hutool-core/src/main/java/cn/hutool/core/codec/{BaseN => binary}/Base64Decoder.java (98%) create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/binary/package-info.java diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 5f87a6a2a..7169d0704 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -17,69 +17,6 @@ Hutool是一个优雅而小巧的Java工具类库 https://github.com/looly/hutool - - - cn.hutool - hutool-core - ${project.parent.version} - - - cn.hutool - hutool-crypto - ${project.parent.version} - - - cn.hutool - hutool-db - ${project.parent.version} - - - cn.hutool - hutool-extra - ${project.parent.version} - - - cn.hutool - hutool-http - ${project.parent.version} - - - cn.hutool - hutool-log - ${project.parent.version} - - - cn.hutool - hutool-setting - ${project.parent.version} - - - cn.hutool - hutool-cron - ${project.parent.version} - - - cn.hutool - hutool-json - ${project.parent.version} - - - cn.hutool - hutool-poi - ${project.parent.version} - - - cn.hutool - hutool-socket - ${project.parent.version} - - - cn.hutool - hutool-swing - ${project.parent.version} - - - diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java b/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java index a07006291..4562f8d74 100755 --- a/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base16Codec; +import cn.hutool.core.codec.binary.Base16Codec; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/PercentCodec.java b/hutool-core/src/main/java/cn/hutool/core/codec/PercentCodec.java index 1a1e810aa..52b522892 100755 --- a/hutool-core/src/main/java/cn/hutool/core/codec/PercentCodec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/PercentCodec.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base16Codec; +import cn.hutool.core.codec.binary.Base16Codec; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.CharPool; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base16Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java similarity index 98% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base16Codec.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java index 8d05d17c9..715a6a5cb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base16Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.codec.Decoder; import cn.hutool.core.codec.Encoder; @@ -81,7 +81,7 @@ public class Base16Codec implements Encoder, Decoder - * '你' =》'\u4f60' + * '你' =》'\u4f60' * * * @param ch char值 diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32.java similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32.java index ecf95cda1..19bf32f0f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java old mode 100755 new mode 100644 similarity index 98% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32Codec.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java index 05c5d70db..ea39c76d1 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base32Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.codec.Decoder; import cn.hutool.core.codec.Encoder; @@ -21,6 +21,9 @@ import java.util.Arrays; */ public class Base32Codec implements Encoder, Decoder { + /** + * 单例对象 + */ public static Base32Codec INSTANCE = new Base32Codec(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58.java similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58.java index 3806dce03..4d376f17e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.exceptions.ValidateException; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58Codec.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java index 0d0436d37..0fa479d49 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base58Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.codec.Decoder; import cn.hutool.core.codec.Encoder; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62.java similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62.java index ff9fdc21b..f0dc87817 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62Codec.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java index 9ee3337cb..2e6e933fd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base62Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.codec.Decoder; import cn.hutool.core.codec.Encoder; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64.java old mode 100755 new mode 100644 similarity index 99% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64.java index 071ffc209..3b47bcb31 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64Decoder.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64Decoder.java similarity index 98% rename from hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64Decoder.java rename to hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64Decoder.java index 013308dd2..cda233a8a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/BaseN/Base64Decoder.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base64Decoder.java @@ -1,4 +1,4 @@ -package cn.hutool.core.codec.BaseN; +package cn.hutool.core.codec.binary; import cn.hutool.core.codec.Decoder; import cn.hutool.core.lang.mutable.MutableInt; @@ -13,6 +13,9 @@ import cn.hutool.core.util.ArrayUtil; */ public class Base64Decoder implements Decoder { + /** + * 单例对象 + */ public static Base64Decoder INSTANCE = new Base64Decoder(); private static final byte PADDING = -2; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/binary/package-info.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/package-info.java new file mode 100644 index 000000000..82c9d3a5f --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/package-info.java @@ -0,0 +1,11 @@ +/** + * BaseN编码解码,提供将bytes和baseN的编码转换功能。 + *

            + *
          • Base16
          • + *
          • Base32
          • + *
          • Base58
          • + *
          • Base62
          • + *
          • Base64
          • + *
          + */ +package cn.hutool.core.codec.binary; diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java index 78b8a83d0..bc089791b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java @@ -1,6 +1,6 @@ package cn.hutool.core.convert.impl; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.convert.Convert; diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java index c737af574..51483bf34 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java @@ -164,8 +164,6 @@ public class TemporalAccessorUtil extends TemporalUtil{ result = ((OffsetTime) temporalAccessor).atDate(LocalDate.now()).toInstant(); } else { // issue#1891@Github - // Instant.from不能完成日期转换 - //result = Instant.from(temporalAccessor); result = toInstant(TimeUtil.of(temporalAccessor)); } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java index dbe94f8ed..2c13a43b2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java @@ -16,7 +16,10 @@ import cn.hutool.core.date.format.DefaultDateBasic; * @since 6.0.0 */ public class CSTDateParser extends DefaultDateBasic implements DateParser { - + private static final long serialVersionUID = 1L; + /** + * 单例对象 + */ public static CSTDateParser INSTANCE = new CSTDateParser(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java index f090b86ac..99c04ae0a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java @@ -21,7 +21,11 @@ import cn.hutool.core.util.CharUtil; * @since 6.0.0 */ public class NormalDateParser extends DefaultDateBasic implements DateParser { + private static final long serialVersionUID = 1L; + /** + * 单例 + */ public static NormalDateParser INSTANCE = new NormalDateParser(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java index c4332a60b..13e937069 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java @@ -16,6 +16,7 @@ import java.util.Locale; * @since 6.0.0 */ public class PatternsDateParser extends DefaultDateBasic implements DateParser { + private static final long serialVersionUID = 1L; /** * 创建 PatternsDateParser diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java index e5dd0f30e..e7646d59d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java @@ -18,7 +18,11 @@ import cn.hutool.core.date.format.DefaultDateBasic; * @since 6.0.0 */ public class PureDateParser extends DefaultDateBasic implements DateParser { + private static final long serialVersionUID = 1L; + /** + * 单例 + */ public static PureDateParser INSTANCE = new PureDateParser(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java index c8aec9a26..6961f02d1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java @@ -17,7 +17,11 @@ import cn.hutool.core.text.StrUtil; * @since 6.0.0 */ public class TimeParser extends DefaultDateBasic implements DateParser { + private static final long serialVersionUID = 1L; + /** + * 单例 + */ public static TimeParser INSTANCE = new TimeParser(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java index a60cb6a0c..ed295d133 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java @@ -109,6 +109,7 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { * @param after 毫秒部分的后一个字符 * @return 规范之后的毫秒部分 */ + @SuppressWarnings("SameParameterValue") private static String normalizeMillSeconds(final String dateStr, final CharSequence before, final CharSequence after) { if (StrUtil.isBlank(after)) { final String millOrNaco = StrUtil.subPre(StrUtil.subAfter(dateStr, before, true), 3); diff --git a/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java index 0d2486471..cf503e7bd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java +++ b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java @@ -6,28 +6,66 @@ package cn.hutool.core.exceptions; * @author looly */ public class InvocationTargetRuntimeException extends UtilException { + private static final long serialVersionUID = 1L; + /** + * 构造 + * + * @param e 异常 + */ public InvocationTargetRuntimeException(final Throwable e) { super(e); } + /** + * 构造 + * + * @param message 消息 + */ public InvocationTargetRuntimeException(final String message) { super(message); } + /** + * 构造 + * + * @param messageTemplate 消息模板 + * @param params 参数 + */ public InvocationTargetRuntimeException(final String messageTemplate, final Object... params) { super(messageTemplate, params); } - public InvocationTargetRuntimeException(final String message, final Throwable throwable) { - super(message, throwable); + /** + * 构造 + * + * @param message 消息 + * @param cause 被包装的子异常 + */ + public InvocationTargetRuntimeException(final String message, final Throwable cause) { + super(message, cause); } - public InvocationTargetRuntimeException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) { - super(message, throwable, enableSuppression, writableStackTrace); + /** + * 构造 + * + * @param message 消息 + * @param cause 被包装的子异常 + * @param enableSuppression 是否启用抑制 + * @param writableStackTrace 堆栈跟踪是否应该是可写的 + */ + public InvocationTargetRuntimeException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); } - public InvocationTargetRuntimeException(final Throwable throwable, final String messageTemplate, final Object... params) { - super(throwable, messageTemplate, params); + /** + * 构造 + * + * @param cause 被包装的子异常 + * @param messageTemplate 消息模板 + * @param params 参数 + */ + public InvocationTargetRuntimeException(final Throwable cause, final String messageTemplate, final Object... params) { + super(cause, messageTemplate, params); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/exceptions/UtilException.java b/hutool-core/src/main/java/cn/hutool/core/exceptions/UtilException.java index e8d96c7d1..3d3bff60e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/exceptions/UtilException.java +++ b/hutool-core/src/main/java/cn/hutool/core/exceptions/UtilException.java @@ -10,8 +10,8 @@ import cn.hutool.core.text.StrUtil; public class UtilException extends RuntimeException { private static final long serialVersionUID = 8247610319171014183L; - public UtilException(final Throwable e) { - super(ExceptionUtil.getMessage(e), e); + public UtilException(final Throwable cause) { + super(ExceptionUtil.getMessage(cause), cause); } public UtilException(final String message) { @@ -22,15 +22,15 @@ public class UtilException extends RuntimeException { super(StrUtil.format(messageTemplate, params)); } - public UtilException(final String message, final Throwable throwable) { - super(message, throwable); + public UtilException(final String message, final Throwable cause) { + super(message, cause); } - public UtilException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) { - super(message, throwable, enableSuppression, writableStackTrace); + public UtilException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); } - public UtilException(final Throwable throwable, final String messageTemplate, final Object... params) { - super(StrUtil.format(messageTemplate, params), throwable); + public UtilException(final Throwable cause, final String messageTemplate, final Object... params) { + super(StrUtil.format(messageTemplate, params), cause); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java index a9d1f0dce..68f624be5 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java @@ -882,6 +882,19 @@ public class IoUtil extends NioUtil { } } + /** + * 关闭
          + * 关闭失败不会抛出异常 + * + * @param closeable 被关闭的对象 + * @throws IOException IO异常 + */ + public static void nullSafeClose(final Closeable closeable) throws IOException { + if (null != closeable) { + closeable.close(); + } + } + /** * 尝试关闭指定对象
          * 判断对象如果实现了{@link AutoCloseable},则调用之 diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java index 99e27bcbe..eda09af2c 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathCopier.java @@ -59,7 +59,6 @@ public class PathCopier extends SrcToDestCopier { this.src = src; this.target = Assert.notNull(target, "Target path must be not null !"); this.options = ObjUtil.defaultIfNull(options, new CopyOption[]{}); - ; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java index 1ac15cb23..71b36234c 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -58,7 +58,7 @@ public class PathMover { } this.src = src; this.target = Assert.notNull(target, "Target path must be not null !"); - this.options = ObjUtil.defaultIfNull(options, new CopyOption[]{});; + this.options = ObjUtil.defaultIfNull(options, new CopyOption[]{}); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/io/stream/EmptyOutputStream.java b/hutool-core/src/main/java/cn/hutool/core/io/stream/EmptyOutputStream.java index c6de0ac74..01ecaa7ae 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/stream/EmptyOutputStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/stream/EmptyOutputStream.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.stream; -import java.io.IOException; import java.io.OutputStream; /** @@ -47,11 +46,10 @@ public class EmptyOutputStream extends OutputStream { * 什么也不做,写出到 {@code /dev/null}. * * @param b 写出的数据 - * @throws IOException 不抛出 */ @SuppressWarnings("NullableProblems") @Override - public void write(final byte[] b) throws IOException { + public void write(final byte[] b) { // to /dev/null } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/ReferenceConcurrentMap.java b/hutool-core/src/main/java/cn/hutool/core/map/ReferenceConcurrentMap.java index 6e7d43212..7cb2eb1d3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/ReferenceConcurrentMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/ReferenceConcurrentMap.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; * @since 5.8.0 */ public class ReferenceConcurrentMap implements ConcurrentMap, Iterable>, Serializable { + private static final long serialVersionUID = 1L; final ConcurrentMap, V> raw; private final ReferenceQueue lastQueue; diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/AbsCollValueMap.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/AbsCollValueMap.java index f43841f8b..2e4d27e63 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/multi/AbsCollValueMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/AbsCollValueMap.java @@ -39,7 +39,7 @@ public abstract class AbsCollValueMap extends MapWrapper> * * @param mapFactory 生成集合的工厂方法 */ - protected AbsCollValueMap(Supplier>> mapFactory) { + protected AbsCollValueMap(final Supplier>> mapFactory) { super(mapFactory); } @@ -48,7 +48,7 @@ public abstract class AbsCollValueMap extends MapWrapper> * * @param map 提供初始数据的集合 */ - protected AbsCollValueMap(Map> map) { + protected AbsCollValueMap(final Map> map) { super(new HashMap<>(map)); } @@ -72,7 +72,7 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 是否成功添加 */ @Override - public boolean putAllValues(K key, Collection coll) { + public boolean putAllValues(final K key, final Collection coll) { if (ObjUtil.isNull(coll)) { return false; } @@ -91,7 +91,7 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 是否成功添加 */ @Override - public boolean putValue(K key, V value) { + public boolean putValue(final K key, final V value) { return super.computeIfAbsent(key, k -> createCollection()) .add(value); } @@ -104,7 +104,7 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 是否成功删除 */ @Override - public boolean removeValue(K key, V value) { + public boolean removeValue(final K key, final V value) { return Opt.ofNullable(super.get(key)) .map(t -> t.remove(value)) .orElse(false); @@ -118,11 +118,11 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 是否成功删除 */ @Override - public boolean removeAllValues(K key, Collection values) { + public boolean removeAllValues(final K key, final Collection values) { if (CollUtil.isEmpty(values)) { return false; } - Collection coll = get(key); + final Collection coll = get(key); return ObjUtil.isNotNull(coll) && coll.removeAll(values); } @@ -133,10 +133,10 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 当前实例 */ @Override - public MultiValueMap filterAllValues(BiPredicate filter) { + public MultiValueMap filterAllValues(final BiPredicate filter) { entrySet().forEach(e -> { - K k = e.getKey(); - Collection coll = e.getValue().stream() + final K k = e.getKey(); + final Collection coll = e.getValue().stream() .filter(v -> filter.test(k, v)) .collect(Collectors.toCollection(this::createCollection)); e.setValue(coll); @@ -151,10 +151,10 @@ public abstract class AbsCollValueMap extends MapWrapper> * @return 当前实例 */ @Override - public MultiValueMap replaceAllValues(BiFunction operate) { + public MultiValueMap replaceAllValues(final BiFunction operate) { entrySet().forEach(e -> { - K k = e.getKey(); - Collection coll = e.getValue().stream() + final K k = e.getKey(); + final Collection coll = e.getValue().stream() .map(v -> operate.apply(k, v)) .collect(Collectors.toCollection(this::createCollection)); e.setValue(coll); diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/Graph.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/Graph.java index 681b6b6f0..4300ba9c2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/multi/Graph.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/Graph.java @@ -14,6 +14,7 @@ import java.util.function.Predicate; * @since 6.0.0 */ public class Graph extends SetValueMap { + private static final long serialVersionUID = 1L; /** * 添加边 diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java b/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java index b8cbec6dd..e5263816b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java +++ b/hutool-core/src/main/java/cn/hutool/core/thread/SyncFinisher.java @@ -3,7 +3,6 @@ package cn.hutool.core.thread; import cn.hutool.core.exceptions.UtilException; import java.io.Closeable; -import java.io.IOException; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -70,6 +69,7 @@ public class SyncFinisher implements Closeable { * @param runnable 工作线程 * @return this */ + @SuppressWarnings("resource") public SyncFinisher addRepeatWorker(final Runnable runnable) { for (int i = 0; i < this.threadSize; i++) { addWorker(new Worker() { @@ -197,7 +197,7 @@ public class SyncFinisher implements Closeable { } @Override - public void close() throws IOException { + public void close() { stop(); } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java index 78070ef39..b6d69725b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotatedElementUtilTest.java @@ -593,7 +593,7 @@ public class AnnotatedElementUtilTest { private @interface Annotation4 {} @Annotation4 - private static class Super {}; + private static class Super {} // ================= interface ================= @@ -608,7 +608,7 @@ public class AnnotatedElementUtilTest { private @interface Annotation6 {} @Annotation6 - private interface Interface {}; + private interface Interface {} // ================= foo ================= diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java index 46b5cea04..6edb2f018 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/GenericAnnotationMappingTest.java @@ -115,6 +115,6 @@ public class GenericAnnotationMappingTest { } @Annotation1("foo") - private static class Foo {}; + private static class Foo {} } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java index 62f577fd1..38a73bc71 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/HierarchicalAnnotatedElementTest.java @@ -203,6 +203,6 @@ public class HierarchicalAnnotatedElementTest { public String method() { return null; } @Annotation1 public static String method2() { return null; } - }; + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java index ff79d53f9..a5d3f0449 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/MetaAnnotatedElementTest.java @@ -211,6 +211,6 @@ public class MetaAnnotatedElementTest { @Annotation3(name = "foo") @Annotation4("foo") - private static class Foo {}; + private static class Foo {} } diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java index 5da4e047b..7527a4c09 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/ResolvedAnnotationMappingTest.java @@ -296,6 +296,6 @@ public class ResolvedAnnotationMappingTest { @Annotation3(value = "Annotation3", alias = 312) @Annotation2(value = "Annotation2") @Annotation1(value = "Annotation1", alias = "goo", unDefVal = "foo", unDefVal2 = "foo") - private static class Foo {}; + private static class Foo {} } diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/Base32Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/Base32Test.java index 63a0560d1..cb6effd74 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/Base32Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/Base32Test.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base32; +import cn.hutool.core.codec.binary.Base32; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.text.StrUtil; import org.junit.Assert; diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/Base58Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/Base58Test.java index 6f7d00855..23256a084 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/Base58Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/Base58Test.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base58; +import cn.hutool.core.codec.binary.Base58; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/Base62Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/Base62Test.java index b7ba61508..b3e22526b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/Base62Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/Base62Test.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base62; +import cn.hutool.core.codec.binary.Base62; import cn.hutool.core.util.RandomUtil; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java index 664dea589..103fc4a2a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java @@ -1,6 +1,6 @@ package cn.hutool.core.codec; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java index f3d1b883c..951bc8454 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollStreamUtilTest.java @@ -152,7 +152,9 @@ public class CollStreamUtilTest { // 对null友好 final Map> termIdClassIdStudentMap = CollStreamUtil.group2Map(Arrays.asList(null, new Student(2, 2, 1, "王五")), Student::getTermId, Student::getClassId); - final Map> termIdClassIdStudentCompareMap = new HashMap>() {{ + final Map> termIdClassIdStudentCompareMap = new HashMap>() { + private static final long serialVersionUID = 1L; + { put(null, MapUtil.empty()); put(2L, MapUtil.of(2L, new Student(2, 2, 1, "王五"))); }}; @@ -269,6 +271,7 @@ public class CollStreamUtilTest { Assert.assertEquals(set, compare); } + @SuppressWarnings("ConstantValue") @Test public void testMerge() { Map map1 = null; diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java index 462478ece..429c7de15 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java @@ -152,8 +152,8 @@ public class NumberChineseFormatterTest { @Test public void formatTest3() { -// String f1 = NumberChineseFormatter.format(5000_8000, false, false); -// Assert.assertEquals("五千万零八千", f1); + final String f1 = NumberChineseFormatter.format(5000_8000, false, false); + Assert.assertEquals("五千万零八千", f1); final String f2 = NumberChineseFormatter.format(1_0035_0089, false, false); Assert.assertEquals("一亿零三十五万零八十九", f2); diff --git a/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java index cacfbfafe..8a15c9f3b 100755 --- a/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/NioUtilTest.java @@ -28,7 +28,7 @@ public class NioUtilTest { @Test @Ignore - public void copyByNIOTest2() throws IOException { + public void copyByNIOTest2() { final File file = FileUtil.file("d:/test/logo.jpg"); final BufferedInputStream in = FileUtil.getInputStream(file); final BufferedOutputStream out = FileUtil.getOutputStream("d:/test/2logo.jpg"); diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java index 7b070c707..82ddf0bfa 100755 --- a/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/AssertTest.java @@ -11,12 +11,14 @@ import java.util.Map; public class AssertTest { + @SuppressWarnings("ConstantValue") @Test public void isNullTest() { final String a = null; Assert.isNull(a); } + @SuppressWarnings("ConstantValue") @Test public void notNullTest() { final String a = null; @@ -113,10 +115,9 @@ public class AssertTest { Assert.isTrue(i > 0, () -> new IndexOutOfBoundsException("relation message to return")); } + @SuppressWarnings("ConstantValue") @Test public void equalsTest() { - //String a="ab"; - //final String b = new String("abc"); final String a = null; final String b = null; Assert.equals(a, b); @@ -124,18 +125,16 @@ public class AssertTest { Assert.equals(a, b, () -> new RuntimeException(StrUtil.format("{}和{}不相等", a, b))); } + @SuppressWarnings("ConstantValue") @Test public void notEqualsTest() { - //String c="19"; - //final String d = new String("19"); final String c = null; final String d = "null"; - //Assert.notEquals(c,d); - //Assert.notEquals(c,d,"{}等于{}",c,d); Assert.notEquals(c, d, () -> new RuntimeException(StrUtil.format("{}和{}相等", c, d))); } + @SuppressWarnings("ConstantValue") @Test public void notEqualsTest2() { final Object c = null; diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EntryStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EntryStreamTest.java index 25c87915b..ff2c5d6bd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/EntryStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/EntryStreamTest.java @@ -162,16 +162,25 @@ public class EntryStreamTest { @Test public void testAppend() { - final Map map1 = new HashMap(){{ + final Map map1 = new HashMap(){ + private static final long serialVersionUID = 2091911960221937275L; + + { put(1, 1); put(2, 2); }}; - final Map map2 = new HashMap(){{ + final Map map2 = new HashMap(){ + private static final long serialVersionUID = 4802315578432177802L; + + { put(3, 3); put(4, 4); }}; Assert.assertEquals( - new ArrayList>(){{ + new ArrayList>(){ + private static final long serialVersionUID = -4045530648496761947L; + + { addAll(map1.entrySet()); addAll(map2.entrySet()); }}, @@ -184,16 +193,25 @@ public class EntryStreamTest { @Test public void testPrepend() { - final Map map1 = new HashMap(){{ + final Map map1 = new HashMap(){ + private static final long serialVersionUID = -8772310525807986780L; + + { put(1, 1); put(2, 2); }}; - final Map map2 = new HashMap(){{ + final Map map2 = new HashMap(){ + private static final long serialVersionUID = -8453400649627773936L; + + { put(3, 3); put(4, 4); }}; Assert.assertEquals( - new ArrayList>(){{ + new ArrayList>(){ + private static final long serialVersionUID = 7564826138581563332L; + + { addAll(map2.entrySet()); addAll(map1.entrySet()); }}, @@ -254,7 +272,7 @@ public class EntryStreamTest { map.put(1, 1); map.put(2, 2); map.put(3, 3); - List keys = EntryStream.of(map).collectKeys(Collectors.toList()); + final List keys = EntryStream.of(map).collectKeys(Collectors.toList()); Assert.assertEquals(new ArrayList<>(map.keySet()), keys); } @@ -264,7 +282,7 @@ public class EntryStreamTest { map.put(1, 1); map.put(2, 2); map.put(3, 3); - List keys = EntryStream.of(map).collectValues(Collectors.toList()); + final List keys = EntryStream.of(map).collectValues(Collectors.toList()); Assert.assertEquals(new ArrayList<>(map.keySet()), keys); } @@ -324,7 +342,7 @@ public class EntryStreamTest { map.put(1, 1); map.put(2, 2); map.put(3, 3); - List list = EntryStream.of(map) + final List list = EntryStream.of(map) .flatMap(e -> Stream.of(e.getKey(), e.getKey() + 1)) .collect(Collectors.toList()); Assert.assertEquals(Arrays.asList(1, 2, 2, 3, 3, 4), list); @@ -567,7 +585,7 @@ public class EntryStreamTest { private final K key; private final V value; - public Entry(K key, V value) { + public Entry(final K key, final V value) { this.key = key; this.value = value; } @@ -583,7 +601,7 @@ public class EntryStreamTest { } @Override - public V setValue(V value) { + public V setValue(final V value) { return null; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java index cb6a25aa1..98baca4dd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java @@ -20,6 +20,7 @@ import java.util.function.Function; */ public class ObjUtilTest { + @SuppressWarnings("ConstantValue") @Test public void equalsTest() { Object a = null; @@ -109,6 +110,7 @@ public class ObjUtilTest { Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyIterator())); } + @SuppressWarnings("ConstantValue") @Test public void defaultIfNullTest() { final Object val1 = new Object(); @@ -227,7 +229,7 @@ public class ObjUtilTest { private final Integer id; @Override protected Object clone() throws CloneNotSupportedException { - throw new RuntimeException("can not clone this object"); + throw new CloneNotSupportedException("can not clone this object"); } } @@ -255,6 +257,6 @@ public class ObjUtilTest { } @SuppressWarnings("unused") - private interface TypeArgument {}; + private interface TypeArgument {} } diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java index b4cbffa93..a27b8403f 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java @@ -53,9 +53,6 @@ public class TaskExecutorManager implements Serializable { synchronized (this.executors) { this.executors.add(executor); } - // 子线程是否为deamon线程取决于父线程,因此此处无需显示调用 - // executor.setDaemon(this.scheduler.daemon); -// executor.start(); this.scheduler.threadExecutor.execute(executor); return executor; } diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncherManager.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncherManager.java index a6ff22646..1e0959efc 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncherManager.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncherManager.java @@ -17,6 +17,10 @@ public class TaskLauncherManager implements Serializable { /** 启动器列表 */ protected final List launchers = new ArrayList<>(); + /** + * 构造 + * @param scheduler {@link Scheduler} + */ public TaskLauncherManager(final Scheduler scheduler) { this.scheduler = scheduler; } @@ -31,9 +35,6 @@ public class TaskLauncherManager implements Serializable { synchronized (this.launchers) { this.launchers.add(launcher); } - //子线程是否为deamon线程取决于父线程,因此此处无需显示调用 - //launcher.setDaemon(this.scheduler.daemon); -// launcher.start(); this.scheduler.threadExecutor.execute(launcher); return launcher; } diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java index 7d2e87923..935b1025a 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java @@ -1,6 +1,6 @@ package cn.hutool.crypto; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java index 1a530dafe..43f3c1d85 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java @@ -1,6 +1,6 @@ package cn.hutool.crypto; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.codec.HexUtil; import cn.hutool.core.lang.Validator; import cn.hutool.core.text.StrUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricCrypto.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricCrypto.java index 4019b3050..e2fac8afa 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricCrypto.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricCrypto.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.stream.FastByteArrayOutputStream; import cn.hutool.crypto.CipherWrapper; import cn.hutool.crypto.CryptoException; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricEncryptor.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricEncryptor.java index 02d1922f8..cfbdaa914 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricEncryptor.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/AsymmetricEncryptor.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.codec.HexUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java index 5023289fd..e4dea6a48 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.lang.Assert; import cn.hutool.crypto.CryptoException; import cn.hutool.crypto.KeyUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java index f0f21ce3d..5fe14ddd0 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java index 8b5c4e7cb..c2dd56498 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/mac/Mac.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.digest.mac; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/otp/HOTP.java b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/otp/HOTP.java index 2e8c64f6f..35de09bab 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/otp/HOTP.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/otp/HOTP.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.digest.otp; -import cn.hutool.core.codec.BaseN.Base32; +import cn.hutool.core.codec.binary.Base32; import cn.hutool.core.util.RandomUtil; import cn.hutool.crypto.digest.HMac; import cn.hutool.crypto.digest.HmacAlgorithm; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java index d7207b465..41be5aed3 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.symmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.codec.HexUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricEncryptor.java b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricEncryptor.java index 3b3e91e42..fabe9e3ce 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricEncryptor.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/SymmetricEncryptor.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.symmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.CharsetUtil; diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/RSATest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/RSATest.java index 2f8cc80ec..98614a4cc 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/RSATest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/RSATest.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.codec.HexUtil; diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java index 2aa251d37..bbbb2ae03 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.asymmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.codec.HexUtil; import cn.hutool.core.text.StrUtil; diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/digest/OTPTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/digest/OTPTest.java index 36c39aad4..71e694da0 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/digest/OTPTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/digest/OTPTest.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.digest; -import cn.hutool.core.codec.BaseN.Base32; +import cn.hutool.core.codec.binary.Base32; import cn.hutool.crypto.digest.otp.HOTP; import cn.hutool.crypto.digest.otp.TOTP; import org.junit.Assert; diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/AESTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/AESTest.java index 0273947f1..ed35a56e7 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/AESTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/AESTest.java @@ -1,6 +1,6 @@ package cn.hutool.crypto.symmetric; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.codec.HexUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.crypto.KeyUtil; diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java b/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java index 6187ea5ef..3db44b795 100644 --- a/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java +++ b/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java @@ -151,17 +151,16 @@ public class ResultColumn { return className; } - public static enum ColumnNullable { + public enum ColumnNullable { NO_NULLS(ResultSetMetaData.columnNoNulls), NULLABLE(ResultSetMetaData.columnNullable), UNKNOWN(ResultSetMetaData.columnNullableUnknown); - final int value; - - private ColumnNullable(final int value) { - this.value = value; - } - + /** + * ResultSetMetaData中的int值转枚举 + * @param nullable nullable值 + * @return ColumnNullable + */ public static ColumnNullable of(final int nullable) { switch (nullable) { case ResultSetMetaData.columnNoNulls: @@ -172,5 +171,10 @@ public class ResultColumn { return UNKNOWN; } } + + final int value; + ColumnNullable(final int value) { + this.value = value; + } } } diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java index ff817a1df..07584d818 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java @@ -13,6 +13,7 @@ import java.util.List; * @since 5.7.21 */ public class ConditionGroup extends Condition { + private static final long serialVersionUID = 1L; /** * 条件列表 */ diff --git a/hutool-db/src/test/java/cn/hutool/db/DerbyTest.java b/hutool-db/src/test/java/cn/hutool/db/DerbyTest.java index ed410c89b..7c7dc10db 100644 --- a/hutool-db/src/test/java/cn/hutool/db/DerbyTest.java +++ b/hutool-db/src/test/java/cn/hutool/db/DerbyTest.java @@ -5,7 +5,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import java.sql.SQLException; import java.util.List; /** @@ -19,7 +18,7 @@ public class DerbyTest { private static final String DS_GROUP_NAME = "derby"; @BeforeClass - public static void init() throws SQLException { + public static void init() { final Db db = Db.of(DS_GROUP_NAME); db.execute("CREATE TABLE test(a INTEGER, b BIGINT)"); @@ -31,14 +30,14 @@ public class DerbyTest { @Test @Ignore - public void queryTest() throws SQLException { + public void queryTest() { final List query = Db.of(DS_GROUP_NAME).query("select * from test"); Assert.assertEquals(4, query.size()); } @Test @Ignore - public void findTest() throws SQLException { + public void findTest() { final List query = Db.of(DS_GROUP_NAME).find(Entity.of("test")); Assert.assertEquals(4, query.size()); } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java index f5efacde3..7bc4e7896 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java @@ -37,12 +37,13 @@ public class MailAccount implements Serializable { // System Properties private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters"; - //private static final String ENCODE_FILE_NAME = "mail.mime.encodefilename"; - //private static final String CHARSET = "mail.mime.charset"; // 其他 private static final String MAIL_DEBUG = "mail.debug"; + /** + * 默认mail配置查询路径 + */ public static final String[] MAIL_SETTING_PATHS = new String[]{"config/mail.setting", "config/mailAccount.setting", "mail.setting"}; /** diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java index 975c5c54c..522bce87d 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java @@ -1,6 +1,6 @@ package cn.hutool.extra.qrcode; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.ObjUtil; import cn.hutool.swing.img.ImgUtil; import com.google.zxing.BarcodeFormat; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java index bd01b8da7..20663b39b 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java @@ -499,6 +499,7 @@ public class Sftp extends AbstractFtp { } } + @SuppressWarnings("resource") @Override public boolean uploadFile(final String destPath, final File file) { if(false == FileUtil.isFile(file)){ @@ -521,13 +522,11 @@ public class Sftp extends AbstractFtp { * @param destPath 服务端路径,可以为{@code null} 或者相对路径或绝对路径 * @param fileName 文件名 * @param fileStream 文件流 - * @return 是否上传成功 * @since 5.7.16 */ - public boolean uploadFile(String destPath, final String fileName, final InputStream fileStream) { + public void uploadFile(String destPath, final String fileName, final InputStream fileStream) { destPath = StrUtil.addSuffixIfNot(destPath, StrUtil.SLASH) + StrUtil.removePrefix(fileName, StrUtil.SLASH); put(fileStream, destPath, null, Mode.OVERWRITE); - return true; } /** diff --git a/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java b/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java index fb18662ef..b867c7004 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/ftp/FtpTest.java @@ -105,7 +105,7 @@ public class FtpTest { @Test @Ignore - public void existSftpTest() throws Exception { + public void existSftpTest() { try (final Sftp ftp = new Sftp("127.0.0.1", 22, "test", "test")) { Console.log(ftp.pwd()); Console.log(ftp.exist(null)); diff --git a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java index 807405e88..02d3b42f0 100755 --- a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java @@ -1,6 +1,6 @@ package cn.hutool.extra.qrcode; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java index 6894ec120..300886ca9 100755 --- a/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java @@ -27,18 +27,16 @@ public class JschUtilTest { @Test @Ignore - public void bindRemotePort() throws InterruptedException { + public void bindRemotePort() { // 建立会话 final Session session = JschUtil.getSession("looly.centos", 22, "test", "123456"); // 绑定ssh服务端8089端口到本机的8000端口上 final boolean b = JschUtil.bindRemotePort(session, 8089, "localhost", 8000); Assert.assertTrue(b); // 保证一直运行 -// while (true){ -// Thread.sleep(3000); -// } } + @SuppressWarnings("resource") @Test @Ignore public void sftpTest() { diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java index c79b36d6f..48faf4389 100755 --- a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java @@ -1,6 +1,6 @@ package cn.hutool.http; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.net.url.UrlQueryUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.http.client.ClientConfig; diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java index b2f3ce07b..6ffe0319c 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java @@ -4,7 +4,6 @@ import cn.hutool.http.client.body.BytesBody; import cn.hutool.http.client.body.HttpBody; import org.apache.hc.core5.http.io.entity.AbstractHttpEntity; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; @@ -50,8 +49,8 @@ public class HttpClient5BodyEntity extends AbstractHttpEntity { } @Override - public void close() throws IOException { - + public void close() { + // do nothing } @Override diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java index c03afbeb1..4f0ce59a2 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java @@ -403,10 +403,6 @@ public class HttpConnection implements HeaderOperation { final StringBuilder sb = StrUtil.builder(); sb.append("Request URL: ").append(this.url).append(StrUtil.CRLF); sb.append("Request Method: ").append(this.getMethod()).append(StrUtil.CRLF); - // sb.append("Request Headers: ").append(StrUtil.CRLF); - // for (Entry> entry : this.conn.getHeaderFields().entrySet()) { - // sb.append(" ").append(entry).append(StrUtil.CRLF); - // } return sb.toString(); } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java index c079f416f..61d704b08 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java @@ -79,7 +79,7 @@ public class JdkClientEngine implements ClientEngine { } @Override - public void close() throws IOException { + public void close() { if (null != conn) { conn.disconnectQuietly(); } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java index 0eff77c41..97f5507bd 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpEngine.java @@ -1,7 +1,6 @@ package cn.hutool.http.client.engine.okhttp; import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.util.ObjUtil; import cn.hutool.http.client.ClientConfig; import cn.hutool.http.client.ClientEngine; import cn.hutool.http.client.Request; @@ -60,8 +59,8 @@ public class OkHttpEngine implements ClientEngine { } @Override - public void close() throws IOException { - // ignore + public void close() { + // do nothing } /** diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpResponse.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpResponse.java index c5d13e56d..a5dd104ec 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpResponse.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/okhttp/OkHttpResponse.java @@ -7,14 +7,9 @@ import kotlin.Pair; import okhttp3.Headers; import okhttp3.ResponseBody; -import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * OkHttp3的{@link okhttp3.Response} 响应包装 @@ -74,7 +69,9 @@ public class OkHttpResponse implements Response { } @Override - public void close() throws IOException { - rawRes.close(); + public void close() { + if(null != this.rawRes){ + rawRes.close(); + } } } diff --git a/hutool-http/src/main/java/cn/hutool/http/html/HTMLFilter.java b/hutool-http/src/main/java/cn/hutool/http/html/HTMLFilter.java index 2df015628..d83ab2462 100644 --- a/hutool-http/src/main/java/cn/hutool/http/html/HTMLFilter.java +++ b/hutool-http/src/main/java/cn/hutool/http/html/HTMLFilter.java @@ -201,12 +201,16 @@ public final class HTMLFilter { } } + // --------------------------------------------------------------- // my versions of some PHP library functions - public static String chr(final int decimal) { - return String.valueOf((char) decimal); - } + /** + * HTML特殊字符替换 + * + * @param s HTML + * @return 替换后的HTML + */ public static String htmlSpecialChars(final String s) { String result = s; result = regexReplace(P_AMP, "&", result); @@ -250,10 +254,22 @@ public final class HTMLFilter { return s; } + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>" becomes "<b> text </g>"). + * If set to false, unbalanced angle brackets will be + * html escaped. + * + * @return alwaysMakeTags + */ public boolean isAlwaysMakeTags() { return alwaysMakeTags; } + /** + * flag determining whether comments are allowed in input String. + * + * @return stripComment + */ public boolean isStripComments() { return stripComment; } @@ -364,7 +380,6 @@ public final class HTMLFilter { final String body = m.group(2); String ending = m.group(3); - // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); if (allowed(name)) { final StringBuilder params = new StringBuilder(); @@ -386,10 +401,6 @@ public final class HTMLFilter { paramName = paramNames.get(ii).toLowerCase(); paramValue = paramValues.get(ii); - // debug( "paramName='" + paramName + "'" ); - // debug( "paramValue='" + paramValue + "'" ); - // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); - if (allowedAttribute(name, paramName)) { if (inArray(paramName, vProtocolAtts)) { paramValue = processParamProtocol(paramValue); @@ -454,7 +465,7 @@ public final class HTMLFilter { while (m.find()) { final String match = m.group(1); final int decimal = Integer.decode(match); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + m.appendReplacement(buf, Matcher.quoteReplacement(CharUtil.toString((char) decimal))); } m.appendTail(buf); s = buf.toString(); @@ -464,7 +475,7 @@ public final class HTMLFilter { while (m.find()) { final String match = m.group(1); final int decimal = Integer.parseInt(match, 16); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + m.appendReplacement(buf, Matcher.quoteReplacement(CharUtil.toString((char) decimal))); } m.appendTail(buf); s = buf.toString(); @@ -474,7 +485,7 @@ public final class HTMLFilter { while (m.find()) { final String match = m.group(1); final int decimal = Integer.parseInt(match, 16); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + m.appendReplacement(buf, Matcher.quoteReplacement(CharUtil.toString((char) decimal))); } m.appendTail(buf); s = buf.toString(); diff --git a/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java b/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java index ec5e36eb7..d30928f7d 100644 --- a/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/DownloadTest.java @@ -1,6 +1,6 @@ package cn.hutool.http; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.StreamProgress; diff --git a/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java b/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java index af10857ce..fe398cb48 100755 --- a/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java +++ b/hutool-json/src/main/java/cn/hutool/json/jwt/Claims.java @@ -1,6 +1,6 @@ package cn.hutool.json.jwt; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; diff --git a/hutool-json/src/main/java/cn/hutool/json/jwt/JWT.java b/hutool-json/src/main/java/cn/hutool/json/jwt/JWT.java index 60ef63612..5cf7f63f3 100755 --- a/hutool-json/src/main/java/cn/hutool/json/jwt/JWT.java +++ b/hutool-json/src/main/java/cn/hutool/json/jwt/JWT.java @@ -1,6 +1,6 @@ package cn.hutool.json.jwt; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.exceptions.ValidateException; diff --git a/hutool-json/src/main/java/cn/hutool/json/jwt/signers/AsymmetricJWTSigner.java b/hutool-json/src/main/java/cn/hutool/json/jwt/signers/AsymmetricJWTSigner.java index 993a8c06c..c59f1c668 100755 --- a/hutool-json/src/main/java/cn/hutool/json/jwt/signers/AsymmetricJWTSigner.java +++ b/hutool-json/src/main/java/cn/hutool/json/jwt/signers/AsymmetricJWTSigner.java @@ -1,6 +1,6 @@ package cn.hutool.json.jwt.signers; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.text.StrUtil; import cn.hutool.crypto.asymmetric.Sign; diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/logtube/LogTubeLog.java b/hutool-log/src/main/java/cn/hutool/log/dialect/logtube/LogTubeLog.java index e5471b3c1..11df073a7 100644 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/logtube/LogTubeLog.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/logtube/LogTubeLog.java @@ -14,6 +14,7 @@ import io.github.logtube.core.IEventLogger; * @since 5.6.6 */ public class LogTubeLog extends AbstractLog { + private static final long serialVersionUID = 1L; private final IEventLogger logger; diff --git a/hutool-log/src/test/java/cn/hutool/log/LogTest.java b/hutool-log/src/test/java/cn/hutool/log/LogTest.java index c6977d4cf..abb30c59c 100644 --- a/hutool-log/src/test/java/cn/hutool/log/LogTest.java +++ b/hutool-log/src/test/java/cn/hutool/log/LogTest.java @@ -19,9 +19,6 @@ public class LogTest { log.debug("This is {} log", Level.DEBUG); log.info("This is {} log", Level.INFO); log.warn("This is {} log", Level.WARN); - -// Exception e = new Exception("test Exception"); -// log.error(e, "This is {} log", Level.ERROR); } /** diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvParser.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvParser.java index 8813f46fb..35ce2d864 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvParser.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvParser.java @@ -12,12 +12,7 @@ import java.io.Closeable; import java.io.IOException; import java.io.Reader; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * CSV行解析器,参考:FastCSV @@ -32,7 +27,7 @@ public final class CsvParser extends ComputeIter implements Closeable, S private final Reader reader; private final CsvReadConfig config; - private final Buffer buf = new Buffer(IoUtil.DEFAULT_LARGE_BUFFER_SIZE); + private final Buffer buf; /** * 前一个特殊分界字符 */ @@ -78,8 +73,20 @@ public final class CsvParser extends ComputeIter implements Closeable, S * @param config 配置,null则为默认配置 */ public CsvParser(final Reader reader, final CsvReadConfig config) { + this(reader, config, IoUtil.DEFAULT_LARGE_BUFFER_SIZE); + } + + /** + * CSV解析器 + * + * @param reader Reader + * @param config 配置,null则为默认配置 + * @param bufferSize 默认缓存大小 + */ + public CsvParser(final Reader reader, final CsvReadConfig config, final int bufferSize) { this.reader = Objects.requireNonNull(reader, "reader must not be null"); this.config = ObjUtil.defaultIfNull(config, CsvReadConfig::defaultConfig); + this.buf = new Buffer(bufferSize); } /** diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java index 86f98424e..9589ddcbe 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvReader.java @@ -1,13 +1,12 @@ package cn.hutool.poi.csv; -import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.func.SerConsumer; import java.io.Closeable; import java.io.File; -import java.io.IOException; import java.io.Reader; import java.nio.charset.Charset; import java.nio.file.Path; @@ -132,14 +131,9 @@ public class CsvReader extends CsvBaseReader implements Iterable, Closea * @since 5.7.14 */ public Stream stream() { - return StreamSupport.stream(spliterator(), false) - .onClose(() -> { - try { - close(); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - }); + return StreamSupport + .stream(spliterator(), false) + .onClose(this::close); } @Override @@ -148,7 +142,7 @@ public class CsvReader extends CsvBaseReader implements Iterable, Closea } @Override - public void close() throws IOException { + public void close() { IoUtil.close(this.reader); } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/NullCell.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/NullCell.java index 1f729dcde..8c7fef9a1 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/NullCell.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/NullCell.java @@ -73,21 +73,11 @@ public class NullCell implements Cell { return null; } - @Deprecated - public CellType getCellTypeEnum() { - return null; - } - @Override public CellType getCachedFormulaResultType() { return null; } - @Deprecated - public CellType getCachedFormulaResultTypeEnum() { - return null; - } - @Override public void setCellValue(final double value) { throw new UnsupportedOperationException("Can not set any thing to null cell!"); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java b/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java index 101dd6937..59d5dad01 100755 --- a/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/csv/Issue2783Test.java @@ -11,12 +11,14 @@ public class Issue2783Test { @Test @Ignore public void readTest() { -// final CsvWriter writer = CsvUtil.getWriter("d:/test/big.csv", CharsetUtil.UTF_8); -// for (int i = 0; i < Integer.MAX_VALUE; i++) { -// writer.writeLine("aaaa", "bbbb", "ccccc", "dddd"); -// } -// writer.close(); + // 测试数据 + final CsvWriter writer = CsvUtil.getWriter("d:/test/big.csv", CharsetUtil.UTF_8); + for (int i = 0; i < Integer.MAX_VALUE; i++) { + writer.writeLine("aaaa", "bbbb", "ccccc", "dddd"); + } + writer.close(); + // 读取 final CsvReader reader = CsvUtil.getReader(FileUtil.getReader("d:/test/big.csv", CharsetUtil.UTF_8)); reader.read((SerConsumer) strings -> { diff --git a/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java b/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java index 011b54d43..c6db13f82 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/GroupedSet.java @@ -1,7 +1,6 @@ package cn.hutool.setting; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.net.url.URLUtil; import cn.hutool.core.text.StrUtil; @@ -183,10 +182,9 @@ public class GroupedSet extends HashMap> { * 加载设置文件。 此方法不会关闭流对象 * * @param settingStream 文件流 - * @return 加载成功与否 * @throws IOException IO异常 */ - public boolean load(final InputStream settingStream) throws IOException { + public void load(final InputStream settingStream) throws IOException { super.clear(); BufferedReader reader = null; try { @@ -233,7 +231,6 @@ public class GroupedSet extends HashMap> { } finally { IoUtil.close(reader); } - return true; } /** diff --git a/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java b/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java index 7715aeb86..ad0747554 100755 --- a/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/SettingLoader.java @@ -96,10 +96,9 @@ public class SettingLoader { * 加载设置文件。 此方法不会关闭流对象 * * @param settingStream 文件流 - * @return 加载成功与否 * @throws IOException IO异常 */ - synchronized public boolean load(final InputStream settingStream) throws IOException { + synchronized public void load(final InputStream settingStream) throws IOException { this.groupedMap.clear(); LineReader reader = null; try { @@ -141,7 +140,6 @@ public class SettingLoader { } finally { IoUtil.close(reader); } - return true; } /** diff --git a/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java b/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java index e3202d6c7..3953c457a 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/captcha/AbstractCaptcha.java @@ -1,6 +1,6 @@ package cn.hutool.swing.captcha; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; diff --git a/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardMonitor.java b/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardMonitor.java index f4978fe82..a4582b6ce 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardMonitor.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardMonitor.java @@ -16,21 +16,16 @@ import java.util.Set; * @author looly * @since 4.5.6 */ -public enum ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { - /** - * 监听器单例 - */ - INSTANCE; - +public class ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { /** 默认重试此时:10 */ public static final int DEFAULT_TRY_COUNT = 10; /** 默认重试等待:100 */ public static final long DEFAULT_DELAY = 100; /** 重试次数 */ - private int tryCount; + private final int tryCount; /** 重试等待 */ - private long delay; + private final long delay; /** 系统剪贴板对象 */ private final Clipboard clipboard; /** 监听事件处理 */ @@ -42,7 +37,7 @@ public enum ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { /** * 构造,尝试获取剪贴板内容的次数为10,第二次之后延迟100毫秒 */ - ClipboardMonitor() { + public ClipboardMonitor() { this(DEFAULT_TRY_COUNT, DEFAULT_DELAY); } @@ -52,7 +47,7 @@ public enum ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { * @param tryCount 尝试获取剪贴板内容的次数 * @param delay 响应延迟,当从第二次开始,延迟一定毫秒数等待剪贴板可以获取,当tryCount小于2时无效 */ - ClipboardMonitor(final int tryCount, final long delay) { + public ClipboardMonitor(final int tryCount, final long delay) { this(tryCount, delay, ClipboardUtil.getClipboard()); } @@ -69,29 +64,6 @@ public enum ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { this.clipboard = clipboard; } // ---------------------------------------------------------------------------------------------------------- Constructor end - - /** - * 设置重试次数 - * - * @param tryCount 重试次数 - * @return this - */ - public ClipboardMonitor setTryCount(final int tryCount) { - this.tryCount = tryCount; - return this; - } - - /** - * 设置重试等待 - * - * @param delay 重试等待 - * @return this - */ - public ClipboardMonitor setDelay(final long delay) { - this.delay = delay; - return this; - } - /** * 设置 监听事件处理 * @@ -192,7 +164,6 @@ public enum ClipboardMonitor implements ClipboardOwner, Runnable, Closeable { for (int i = 0; i < this.tryCount; i++) { if (this.delay > 0 && i > 0) { // 第一次获取不等待,只有从第二次获取时才开始等待 - //noinspection BusyWait Thread.sleep(this.delay); } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardUtil.java index 2b7108614..1644ace46 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/clipboard/ClipboardUtil.java @@ -134,6 +134,7 @@ public class ClipboardUtil { return (Image) get(content, DataFlavor.imageFlavor); } + // region ----- listen /** * 监听剪贴板修改事件 * @@ -161,17 +162,27 @@ public class ClipboardUtil { * 监听剪贴板修改事件 * * @param tryCount 尝试获取剪贴板内容的次数 - * @param delay 响应延迟,当从第二次开始,延迟一定毫秒数等待剪贴板可以获取 + * @param delay 响应延迟,当从第二次开始,延迟一定毫秒数等待剪贴板可以获取,当tryCount小于2时无效 * @param listener 监听处理接口 * @param sync 是否同步阻塞 * @since 4.5.6 * @see ClipboardMonitor#listen(boolean) */ public static void listen(final int tryCount, final long delay, final ClipboardListener listener, final boolean sync) { - ClipboardMonitor.INSTANCE// - .setTryCount(tryCount)// - .setDelay(delay)// - .addListener(listener)// - .listen(sync); + getMonitor(tryCount, delay, listener).listen(sync); } + + /** + * 获取一个{@link ClipboardMonitor} + * @param tryCount 尝试获取剪贴板内容的次数 + * @param delay 响应延迟,当从第二次开始,延迟一定毫秒数等待剪贴板可以获取,当tryCount小于2时无效 + * @param listener 监听处理接口 + * @return {@link ClipboardMonitor} + */ + @SuppressWarnings("resource") + public static ClipboardMonitor getMonitor(final int tryCount, final long delay, final ClipboardListener listener){ + return new ClipboardMonitor(tryCount, delay, null) + .addListener(listener); + } + // endregion } diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java index f4c81603c..fccd96d5a 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java @@ -1,6 +1,6 @@ package cn.hutool.swing.img; -import cn.hutool.core.codec.BaseN.Base64; +import cn.hutool.core.codec.binary.Base64; import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; From 48eec2a8ae6056c044e0b4ef6d476eb6cb6441bd Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 05:04:50 +0800 Subject: [PATCH 113/125] fix code --- hutool-all/pom.xml | 63 +++++ .../src/main/java/cn/hutool/Hutool.java | 3 + .../core/annotation/AnnotatedElementUtil.java | 2 +- .../RepeatableAnnotationCollector.java | 14 +- .../annotation/ResolvedAnnotationMapping.java | 19 +- .../cn/hutool/core/bean/copier/AbsCopier.java | 7 + .../java/cn/hutool/core/codec/HexUtil.java | 8 +- .../hutool/core/codec/binary/Base16Codec.java | 2 +- .../hutool/core/codec/binary/Base32Codec.java | 16 +- .../hutool/core/codec/binary/Base58Codec.java | 9 + .../hutool/core/codec/binary/Base62Codec.java | 15 ++ .../cn/hutool/core/codec/hash/HashUtil.java | 26 +- .../cn/hutool/core/codec/hash/MetroHash.java | 237 ------------------ .../codec/hash/metro/AbstractMetroHash.java | 63 +++++ .../core/codec/hash/metro/MetroHash.java | 56 +++++ .../core/codec/hash/metro/MetroHash128.java | 182 ++++++++++++++ .../core/codec/hash/metro/MetroHash64.java | 158 ++++++++++++ .../hash/metro/MetroHashInternalUtil.java | 51 ++++ .../core/codec/hash/metro/package-info.java | 8 + .../hutool/core/collection/iter/LineIter.java | 1 + .../core/comparator/ComparatorChain.java | 29 +-- .../java/cn/hutool/core/convert/Convert.java | 1 + .../core/convert/impl/ArrayConverter.java | 3 + .../java/cn/hutool/core/date/Quarter.java | 30 ++- .../java/cn/hutool/core/date/SystemClock.java | 2 +- .../core/date/format/FastDatePrinter.java | 108 -------- .../cn/hutool/core/io/AppendableWriter.java | 5 + .../core/io/file/visitor/DelVisitor.java | 5 +- .../core/io/watch/watchers/DelayWatcher.java | 2 +- .../core/io/watch/watchers/WatcherChain.java | 5 +- .../main/java/cn/hutool/core/lang/Opt.java | 5 +- .../cn/hutool/core/lang/ansi/AnsiStyle.java | 2 +- .../java/cn/hutool/core/lang/range/Bound.java | 4 +- .../core/lang/range/NoneLowerBound.java | 5 +- .../core/lang/range/NoneUpperBound.java | 2 +- .../cn/hutool/core/map/multi/RowKeyTable.java | 2 +- .../cn/hutool/core/math/BitStatusUtil.java | 2 +- .../hutool/core/reflect/MethodHandleUtil.java | 6 +- .../java/cn/hutool/core/regex/ReUtil.java | 4 +- .../cn/hutool/core/text/AntPathMatcher.java | 7 + .../hutool/core/text/escape/Html4Escape.java | 5 + .../cn/hutool/core/thread/BlockPolicy.java | 2 +- .../java/cn/hutool/core/util/BooleanUtil.java | 1 - .../java/cn/hutool/core/util/ByteUtil.java | 4 +- .../codec/hash/metro/MetroHash128Test.java | 119 +++++++++ .../codec/hash/metro/MetroHash64Test.java | 118 +++++++++ .../codec/hash/{ => metro}/MetroHashTest.java | 37 ++- .../hutool/core/collection/IterUtilTest.java | 8 +- .../collection/partition/PartitionTest.java | 1 - .../java/cn/hutool/core/io/IoUtilTest.java | 12 +- .../builder/GenericBuilderTest.java | 3 +- .../cn/hutool/core/lang/range/BoundTest.java | 8 +- .../reflect/ActualTypeMapperPoolTest.java | 3 +- .../AbstractEnhancedWrappedStreamTest.java | 4 +- .../core/text/CharSequenceUtilTest.java | 2 + ...ueI5Q4HDTest.java => IssueI5Q4HDTest.java} | 2 +- .../cn/hutool/core/util/CharUtilTest.java | 2 + .../pattern/matcher/AlwaysTrueMatcher.java | 3 + .../java/cn/hutool/crypto/SecureUtil.java | 2 +- .../cn/hutool/crypto/asymmetric/Sign.java | 4 +- .../crypto/symmetric/{fpe => }/FPE.java | 5 +- .../hutool/crypto/symmetric/fpe/FPETest.java | 1 + .../main/java/cn/hutool/db/AbstractDb.java | 17 +- .../hutool/db/ds/pooled/PooledDataSource.java | 4 +- .../java/cn/hutool/db/handler/RsHandler.java | 6 +- .../main/java/cn/hutool/db/meta/JdbcType.java | 234 +++++++++++++---- .../java/cn/hutool/db/meta/ResultColumn.java | 128 ++++++++++ .../java/cn/hutool/extra/aop/ProxyUtil.java | 2 +- .../cn/hutool/extra/management/JavaInfo.java | 4 +- .../cn/hutool/extra/qrcode/QrAsciiArt.java | 1 + .../engine/httpclient4/HttpClient4Engine.java | 4 - .../engine/httpclient5/HttpClient5Engine.java | 1 - .../http/ssl/CustomProtocolsSSLFactory.java | 2 - .../java/cn/hutool/http/ContentTypeTest.java | 2 +- .../{ => client}/body/MultipartBodyTest.java | 5 +- .../java/cn/hutool/json/InternalJSONUtil.java | 1 + .../java/cn/hutool/json/Issue1200Test.java | 2 +- ...{IssueI1F8M2.java => IssueI1F8M2Test.java} | 2 +- ...{IssueI1H2VN.java => IssueI1H2VNTest.java} | 2 +- ...{IssueI3BS4S.java => IssueI3BS4STest.java} | 2 +- ...{IssueI3EGJP.java => IssueI3EGJPTest.java} | 2 +- .../java/cn/hutool/json/JSONUtilTest.java | 7 +- .../writer/GlobalValueWriterMappingTest.java | 5 +- .../log/dialect/commons/ApacheCommonsLog.java | 65 +++-- .../commons/ApacheCommonsLog4JLog.java | 18 +- .../commons/ApacheCommonsLogFactory.java | 3 + .../hutool/log/dialect/tinylog/TinyLog2.java | 69 +++-- .../java/cn/hutool/poi/excel/style/Align.java | 15 +- .../cn/hutool/socket/protocol/MsgDecoder.java | 4 +- .../java/cn/hutool/swing/img/ScaleType.java | 3 +- .../swing/img/color/Ansi4bitMapping.java | 7 + .../swing/img/color/Ansi8bitMapping.java | 6 + 92 files changed, 1487 insertions(+), 651 deletions(-) delete mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/MetroHash.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/package-info.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash64Test.java rename hutool-core/src/test/java/cn/hutool/core/codec/hash/{ => metro}/MetroHashTest.java (70%) mode change 100755 => 100644 rename hutool-core/src/test/java/cn/hutool/core/{ => lang}/builder/GenericBuilderTest.java (97%) rename hutool-core/src/test/java/cn/hutool/core/text/dfa/{issueI5Q4HDTest.java => IssueI5Q4HDTest.java} (97%) rename hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/{fpe => }/FPE.java (98%) rename hutool-http/src/test/java/cn/hutool/http/{ => client}/body/MultipartBodyTest.java (90%) rename hutool-json/src/test/java/cn/hutool/json/{IssueI1F8M2.java => IssueI1F8M2Test.java} (96%) rename hutool-json/src/test/java/cn/hutool/json/{IssueI1H2VN.java => IssueI1H2VNTest.java} (97%) rename hutool-json/src/test/java/cn/hutool/json/{IssueI3BS4S.java => IssueI3BS4STest.java} (94%) rename hutool-json/src/test/java/cn/hutool/json/{IssueI3EGJP.java => IssueI3EGJPTest.java} (94%) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 7169d0704..5f87a6a2a 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -17,6 +17,69 @@ Hutool是一个优雅而小巧的Java工具类库 https://github.com/looly/hutool + + + cn.hutool + hutool-core + ${project.parent.version} + + + cn.hutool + hutool-crypto + ${project.parent.version} + + + cn.hutool + hutool-db + ${project.parent.version} + + + cn.hutool + hutool-extra + ${project.parent.version} + + + cn.hutool + hutool-http + ${project.parent.version} + + + cn.hutool + hutool-log + ${project.parent.version} + + + cn.hutool + hutool-setting + ${project.parent.version} + + + cn.hutool + hutool-cron + ${project.parent.version} + + + cn.hutool + hutool-json + ${project.parent.version} + + + cn.hutool + hutool-poi + ${project.parent.version} + + + cn.hutool + hutool-socket + ${project.parent.version} + + + cn.hutool + hutool-swing + ${project.parent.version} + + + diff --git a/hutool-all/src/main/java/cn/hutool/Hutool.java b/hutool-all/src/main/java/cn/hutool/Hutool.java index 2469d1e2d..83c7370c1 100644 --- a/hutool-all/src/main/java/cn/hutool/Hutool.java +++ b/hutool-all/src/main/java/cn/hutool/Hutool.java @@ -42,6 +42,9 @@ import java.util.Set; */ public class Hutool { + /** + * 作者(贡献者) + */ public static final String AUTHOR = "Looly"; private Hutool() { diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotatedElementUtil.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotatedElementUtil.java index 34ee2974b..f7db8eaca 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotatedElementUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotatedElementUtil.java @@ -703,7 +703,7 @@ public class AnnotatedElementUtil { /** * 清空相关缓存,包括: *
            - *
          • {@link AnnotatedElementUtil}中的{@link AnnotatedElement}及{@link AnnotationMapping}缓存;
          • + *
          • {@code AnnotatedElementUtil}中的{@link AnnotatedElement}及{@link AnnotationMapping}缓存;
          • *
          • {@link AnnotationUtil}中的{@link AnnotatedElement}上直接声明的注解缓存;
          • *
          • {@link RepeatableAnnotationCollector}中单例的注解属性缓存;
          • *
          diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/RepeatableAnnotationCollector.java b/hutool-core/src/main/java/cn/hutool/core/annotation/RepeatableAnnotationCollector.java index cf6fe2bed..a817c0a6a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/RepeatableAnnotationCollector.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/RepeatableAnnotationCollector.java @@ -25,7 +25,7 @@ public interface RepeatableAnnotationCollector { /** * 空实现 * - * @return {@link RepeatableAnnotationCollector}实例 + * @return {@code RepeatableAnnotationCollector}实例 */ static RepeatableAnnotationCollector none() { return None.INSTANCE; @@ -47,7 +47,7 @@ public interface RepeatableAnnotationCollector { * * 解析任意{@code Annotation}注解对象,则可以获得{@code value}属性中的{@code Item}注解对象 * - * @return {@link RepeatableAnnotationCollector}实例 + * @return {@code RepeatableAnnotationCollector}实例 * @see Standard */ static RepeatableAnnotationCollector standard() { @@ -59,7 +59,7 @@ public interface RepeatableAnnotationCollector { * 收集器将返回所有匹配的属性中的可重复注解。 * * @param predicate 是否为容纳可重复注解的属性的判断条件 - * @return {@link RepeatableAnnotationCollector}实例 + * @return {@code RepeatableAnnotationCollector}实例 */ static RepeatableAnnotationCollector condition(final BiPredicate predicate) { return new Condition(predicate); @@ -80,7 +80,7 @@ public interface RepeatableAnnotationCollector { * 则可以获得{@code items1}属性中的{@code Item1}注解对象, * 以及{@code items2}属性中的{@code Item2}注解对象, * - * @return {@link RepeatableAnnotationCollector}实例 + * @return {@code RepeatableAnnotationCollector}实例 */ static RepeatableAnnotationCollector full() { return Full.INSTANCE; @@ -189,7 +189,7 @@ public interface RepeatableAnnotationCollector { } /** - * {@link RepeatableAnnotationCollector}的基本实现 + * {@code RepeatableAnnotationCollector}的基本实现 */ abstract class AbstractCollector implements RepeatableAnnotationCollector { @@ -218,7 +218,7 @@ public interface RepeatableAnnotationCollector { * @return 容器注解中的可重复注解,若{@code annotation}不为容器注解,则数组中仅有其本身一个对象 */ @Override - public List getAllRepeatableAnnotations(Annotation annotation) { + public List getAllRepeatableAnnotations(final Annotation annotation) { return find(annotation, null, true); } @@ -261,7 +261,7 @@ public interface RepeatableAnnotationCollector { final boolean isTarget = hasCondition && condition.test(source); if (CollUtil.isEmpty(repeatableMethods) || isTarget) { // 不是累加的,则仅当正在处理的注解不为可重复注解时才记录 - boolean shouldProcess = !accumulate && (!hasCondition || isTarget); + final boolean shouldProcess = !accumulate && (!hasCondition || isTarget); if (shouldProcess) { results.add(source); } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/ResolvedAnnotationMapping.java b/hutool-core/src/main/java/cn/hutool/core/annotation/ResolvedAnnotationMapping.java index afdc9c543..e0ec6783c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/ResolvedAnnotationMapping.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/ResolvedAnnotationMapping.java @@ -145,10 +145,10 @@ public class ResolvedAnnotationMapping implements AnnotationMapping *
            *
          • 当{@code annotation}已经被代理过时抛出;
          • *
          • 当{@code source}包装的注解对象与{@code annotation}相同时抛出;
          • - *
          • 当{@code annotation}包装的注解对象类型为{@link ResolvedAnnotationMapping}时抛出;
          • + *
          • 当{@code annotation}包装的注解对象类型为{@code ResolvedAnnotationMapping}时抛出;
          • *
          */ - ResolvedAnnotationMapping(final ResolvedAnnotationMapping source, final Annotation annotation, boolean resolveAttribute) { + ResolvedAnnotationMapping(final ResolvedAnnotationMapping source, final Annotation annotation, final boolean resolveAttribute) { Objects.requireNonNull(annotation); Assert.isFalse(AnnotationMappingProxy.isProxied(annotation), "annotation has been proxied"); Assert.isFalse(annotation instanceof ResolvedAnnotationMapping, "annotation has been wrapped"); @@ -254,7 +254,6 @@ public class ResolvedAnnotationMapping implements AnnotationMapping * * @return 所需的注解,若{@link ResolvedAnnotationMapping#isResolved()}为{@code false}则返回的是原始的注解对象 */ - @SuppressWarnings("unchecked") @Override public Annotation getResolvedAnnotation() { if (!isResolved()) { @@ -399,7 +398,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping } // 获取除自己外的全部子注解 final Deque sources = new LinkedList<>(); - Set> accessed = new HashSet<>(); + final Set> accessed = new HashSet<>(); accessed.add(this.annotationType()); ResolvedAnnotationMapping sourceMapping = this.source; while (Objects.nonNull(sourceMapping)) { @@ -444,7 +443,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping * 更新需要覆写的属性的相关映射关系,若该属性存在别名,则将别名的映射关系一并覆写 */ private void overwriteAttribute( - final ResolvedAnnotationMapping overwriteMapping, final int overwriteIndex, final int targetIndex, boolean overwriteAliases) { + final ResolvedAnnotationMapping overwriteMapping, final int overwriteIndex, final int targetIndex, final boolean overwriteAliases) { // 若目标属性已被覆写,则不允许再次覆写 if (isOverwrittenAttribute(targetIndex)) { return; @@ -463,7 +462,7 @@ public class ResolvedAnnotationMapping implements AnnotationMapping /** * 判断该属性是否已被覆写 */ - private boolean isOverwrittenAttribute(int index) { + private boolean isOverwrittenAttribute(final int index) { // 若属性未发生过解析,则必然未被覆写 return NOT_FOUND_INDEX != resolvedAttributes[index] // 若属性发生过解析,且指向其他实例,则说明已被覆写 @@ -567,14 +566,14 @@ public class ResolvedAnnotationMapping implements AnnotationMapping * @return 是否 */ @Override - public boolean equals(Object o) { + public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } - ResolvedAnnotationMapping that = (ResolvedAnnotationMapping)o; + final ResolvedAnnotationMapping that = (ResolvedAnnotationMapping)o; return resolved == that.resolved && annotation.equals(that.annotation); } @@ -671,8 +670,8 @@ public class ResolvedAnnotationMapping implements AnnotationMapping /** * 遍历下标 */ - void forEach(IntConsumer consumer) { - for (int index : indexes) { + void forEach(final IntConsumer consumer) { + for (final int index : indexes) { consumer.accept(index); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java index 7f6d49215..2165be49e 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/AbsCopier.java @@ -20,6 +20,13 @@ public abstract class AbsCopier implements Copier { */ protected final CopyOptions copyOptions; + /** + * 构造 + * + * @param source 源对象 + * @param target 目标对象 + * @param copyOptions 拷贝选项 + */ public AbsCopier(final S source, final T target, final CopyOptions copyOptions) { this.source = source; this.target = target; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java b/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java index 4562f8d74..8821fa1cb 100755 --- a/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/HexUtil.java @@ -31,7 +31,7 @@ public class HexUtil { * @return 是否为16进制 */ public static boolean isHexNumber(final String value) { - if(StrUtil.startWith(value, '-')){ + if (StrUtil.startWith(value, '-')) { // issue#2875 return false; } @@ -39,7 +39,7 @@ public class HexUtil { if (value.startsWith("0x", index) || value.startsWith("0X", index)) { index += 2; } else if (value.startsWith("#", index)) { - index ++; + index++; } try { new BigInteger(value.substring(index), 16); @@ -253,7 +253,7 @@ public class HexUtil { * 转换的字符串如果u后不足4位,则前面用0填充,例如: * *
          -	 * '你' =》\u4f60
          +	 * 你 =》 \u4f60
           	 * 
          * * @param value int值,也可以是char @@ -278,7 +278,7 @@ public class HexUtil { * 转换的字符串如果u后不足4位,则前面用0填充,例如: * *
          -	 * '你' =》'\u4f60'
          +	 * 你 =》 \u4f60
           	 * 
          * * @param ch char值 diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java index 715a6a5cb..3fa9dc553 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base16Codec.java @@ -81,7 +81,7 @@ public class Base16Codec implements Encoder, Decoder - * '你' =》'\u4f60' + * 你 =》\u4f60 * * * @param ch char值 diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java index ea39c76d1..ac193a88e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base32Codec.java @@ -7,7 +7,7 @@ import java.util.Arrays; /** * Base32 - encodes and decodes RFC4648 Base32
          - * (see https://datatracker.ietf.org/doc/html/rfc4648#section-6 )
          + * (see https://datatracker.ietf.org/doc/html/rfc4648#section-6 )
          * base32就是用32(2的5次方)个特定ASCII码来表示256个ASCII码。
          * 所以,5个ASCII字符经过base32编码后会变为8个字符(公约数为40),长度增加3/5.不足8n用“=”补足。
          * 根据RFC4648 Base32规范,支持两种模式: @@ -69,7 +69,13 @@ public class Base32Codec implements Encoder, Decoder, Decoder { private static final char BASE_CHAR = '0'; + /** + * 解码器 + */ public static final Base32Decoder DECODER = new Base32Decoder(Base32Encoder.DEFAULT_ALPHABET); + /** + * 16进制解码器 + */ public static final Base32Decoder HEX_DECODER = new Base32Decoder(Base32Encoder.HEX_ALPHABET); private final byte[] lookupTable; @@ -166,7 +178,7 @@ public class Base32Codec implements Encoder, Decoder= 'A' && c <= 'Z'){ + if (c >= 'A' && c <= 'Z') { lookupTable[Character.toLowerCase(c) - BASE_CHAR] = (byte) i; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java index 0fa479d49..ef14122e2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base58Codec.java @@ -15,6 +15,9 @@ import java.util.Arrays; */ public class Base58Codec implements Encoder, Decoder { + /** + * 单例 + */ public static Base58Codec INSTANCE = new Base58Codec(); /** @@ -48,6 +51,9 @@ public class Base58Codec implements Encoder, Decoder { private static final String DEFAULT_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + /** + * 编码器 + */ public static final Base58Encoder ENCODER = new Base58Encoder(DEFAULT_ALPHABET.toCharArray()); private final char[] alphabet; @@ -105,6 +111,9 @@ public class Base58Codec implements Encoder, Decoder { + /** + * 解码器 + */ public static Base58Decoder DECODER = new Base58Decoder(Base58Encoder.DEFAULT_ALPHABET); private final byte[] lookupTable; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java index 2e6e933fd..9cd01a0bc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/binary/Base62Codec.java @@ -20,6 +20,9 @@ public class Base62Codec implements Encoder, Decoder, Decoder, Decoder { + /** + * GMP风格解码器 + */ public static Base62Decoder GMP_DECODER = new Base62Decoder(Base62Encoder.GMP); + /** + * 反转风格,即将GMP风格中的大小写做转换解码器 + */ public static Base62Decoder INVERTED_DECODER = new Base62Decoder(Base62Encoder.INVERTED); private final byte[] lookupTable; diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/HashUtil.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/HashUtil.java index a54873d8d..ea2e9e8a3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/HashUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/HashUtil.java @@ -1,6 +1,8 @@ package cn.hutool.core.codec.hash; import cn.hutool.core.codec.Number128; +import cn.hutool.core.codec.hash.metro.MetroHash128; +import cn.hutool.core.codec.hash.metro.MetroHash64; /** * Hash算法大全
          @@ -554,17 +556,7 @@ public class HashUtil { * @return hash值 */ public static long metroHash64(final byte[] data, final long seed) { - return MetroHash.INSTANCE.hash64(data, seed); - } - - /** - * MetroHash 算法64-bit实现 - * - * @param data 数据 - * @return hash值 - */ - public static long metroHash64(final byte[] data) { - return MetroHash.INSTANCE.hash64(data); + return MetroHash64.of(seed).hash64(data); } /** @@ -575,17 +567,7 @@ public class HashUtil { * @return hash值,long[0]:低位,long[1]:高位 */ public static long[] metroHash128(final byte[] data, final long seed) { - return MetroHash.INSTANCE.hash128(data, seed).getLongArray(); - } - - /** - * MetroHash 算法128-bit实现 - * - * @param data 数据 - * @return hash值,long[0]:低位,long[1]:高位 - */ - public static long[] metroHash128(final byte[] data) { - return MetroHash.INSTANCE.hash128(data).getLongArray(); + return MetroHash128.of(seed).hash128(data).getLongArray(); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/MetroHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/MetroHash.java deleted file mode 100644 index 56a9388c7..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/MetroHash.java +++ /dev/null @@ -1,237 +0,0 @@ -package cn.hutool.core.codec.hash; - -import cn.hutool.core.codec.Number128; -import cn.hutool.core.util.ByteUtil; - -import java.nio.ByteOrder; -import java.util.Arrays; - -/** - * Apache 发布的MetroHash算法,是一组用于非加密用例的最先进的哈希函数。 - * 除了卓越的性能外,他们还以算法生成而著称。 - * - *

          - * 官方实现:https://github.com/jandrewrogers/MetroHash - * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ - * Go语言实现:https://github.com/linvon/cuckoo-filter/blob/main/vendor/github.com/dgryski/go-metro/ - * - * @author li - */ -public class MetroHash implements Hash64, Hash128 { - public static MetroHash INSTANCE = new MetroHash(); - - @Override - public Number encode(final byte[] bytes) { - return hash64(bytes); - } - - @Override - public long hash64(final byte[] data) { - return hash64(data, 1337); - } - - /** - * 计算64位Hash值 - * - * @param data 数据 - * @param seed 种子 - * @return hash64 - */ - public long hash64(final byte[] data, final long seed) { - final long k0_64 = 0xD6D018F5; - final long k1_64 = 0xA2AA033B; - final long k2_64 = 0x62992FC1; - final long k3_64 = 0x30BC5B29; - - byte[] buffer = data; - long hash = (seed + k2_64) * k0_64; - - long v0, v1, v2, v3; - v0 = hash; - v1 = hash; - v2 = hash; - v3 = hash; - - if (buffer.length >= 32) { - - while (buffer.length >= 32) { - v0 += littleEndian64(buffer, 0) * k0_64; - v0 = rotateLeft64(v0, -29) + v2; - v1 += littleEndian64(buffer, 8) * k1_64; - v1 = rotateLeft64(v1, -29) + v3; - v2 += littleEndian64(buffer, 24) * k2_64; - v2 = rotateLeft64(v2, -29) + v0; - v3 += littleEndian64(buffer, 32) * k3_64; - v3 = rotateLeft64(v3, -29) + v1; - buffer = Arrays.copyOfRange(buffer, 32, buffer.length); - } - - v2 ^= rotateLeft64(((v0 + v3) * k0_64) + v1, -37) * k1_64; - v3 ^= rotateLeft64(((v1 + v2) * k1_64) + v0, -37) * k0_64; - v0 ^= rotateLeft64(((v0 + v2) * k0_64) + v3, -37) * k1_64; - v1 ^= rotateLeft64(((v1 + v3) * k1_64) + v2, -37) * k0_64; - hash += v0 ^ v1; - } - - if (buffer.length >= 16) { - v0 = hash + littleEndian64(buffer, 0) * k2_64; - v0 = rotateLeft64(v0, -29) * k3_64; - v1 = hash + littleEndian64(buffer, 8) * k2_64; - v1 = rotateLeft64(v1, -29) * k3_64; - v0 ^= rotateLeft64(v0 * k0_64, -21) + v1; - v1 ^= rotateLeft64(v1 * k3_64, -21) + v0; - hash += v1; - buffer = Arrays.copyOfRange(buffer, 16, buffer.length); - } - - if (buffer.length >= 8) { - hash += littleEndian64(buffer, 0) * k3_64; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - hash ^= rotateLeft64(hash, -55) * k1_64; - } - - if (buffer.length >= 4) { - hash += (long) littleEndian32(Arrays.copyOfRange(buffer, 0, 4)) * k3_64; - hash ^= rotateLeft64(hash, -26) * k1_64; - buffer = Arrays.copyOfRange(buffer, 4, buffer.length); - } - - if (buffer.length >= 2) { - hash += (long) littleEndian16(Arrays.copyOfRange(buffer, 0, 2)) * k3_64; - buffer = Arrays.copyOfRange(buffer, 2, buffer.length); - hash ^= rotateLeft64(hash, -48) * k1_64; - } - - if (buffer.length >= 1) { - hash += (long) buffer[0] * k3_64; - hash ^= rotateLeft64(hash, -38) * k1_64; - } - - hash ^= rotateLeft64(hash, -28); - hash *= k0_64; - hash ^= rotateLeft64(hash, -29); - - return hash; - } - - @Override - public Number128 hash128(final byte[] data) { - return hash128(data, 1337); - } - - /** - * 计算128位hash值 - * - * @param data 数据 - * @param seed 种子 - * @return hash128 - */ - public Number128 hash128(final byte[] data, final long seed) { - final long k0_128 = 0xC83A91E1; - final long k1_128 = 0x8648DBDB; - final long k2_128 = 0x7BDEC03B; - final long k3_128 = 0x2F5870A5; - - byte[] buffer = data; - - long v0, v1, v2, v3; - - v0 = (seed - k0_128) * k3_128; - v1 = (seed + k1_128) * k2_128; - - if (buffer.length >= 32) { - v2 = (seed + k0_128) * k2_128; - v3 = (seed - k1_128) * k3_128; - - while (buffer.length >= 32) { - v0 += littleEndian64(buffer, 0) * k0_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v0 = rotateRight(v0, 29) + v2; - v1 += littleEndian64(buffer, 0) * k1_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v1 = rotateRight(v1, 29) + v3; - v2 += littleEndian64(buffer, 0) * k2_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v2 = rotateRight(v2, 29) + v0; - v3 = littleEndian64(buffer, 0) * k3_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v3 = rotateRight(v3, 29) + v1; - } - - v2 ^= rotateRight(((v0 + v3) * k0_128) + v1, 21) * k1_128; - v3 ^= rotateRight(((v1 + v2) * k1_128) + v0, 21) * k0_128; - v0 ^= rotateRight(((v0 + v2) * k0_128) + v3, 21) * k1_128; - v1 ^= rotateRight(((v1 + v3) * k1_128) + v2, 21) * k0_128; - } - - if (buffer.length >= 16) { - v0 += littleEndian64(buffer, 0) * k2_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v0 = rotateRight(v0, 33) * k3_128; - v1 += littleEndian64(buffer, 0) * k2_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v1 = rotateRight(v1, 33) * k3_128; - v0 ^= rotateRight((v0 * k2_128) + v1, 45) + k1_128; - v1 ^= rotateRight((v1 * k3_128) + v0, 45) + k0_128; - } - - if (buffer.length >= 8) { - v0 += littleEndian64(buffer, 0) * k2_128; - buffer = Arrays.copyOfRange(buffer, 8, buffer.length); - v0 = rotateRight(v0, 33) * k3_128; - v0 ^= rotateRight((v0 * k2_128) + v1, 27) * k1_128; - } - - if (buffer.length >= 4) { - v1 += (long) littleEndian32(buffer) * k2_128; - buffer = Arrays.copyOfRange(buffer, 4, buffer.length); - v1 = rotateRight(v1, 33) * k3_128; - v1 ^= rotateRight((v1 * k3_128) + v0, 46) * k0_128; - } - - if (buffer.length >= 2) { - v0 += (long) littleEndian16(buffer) * k2_128; - buffer = Arrays.copyOfRange(buffer, 2, buffer.length); - v0 = rotateRight(v0, 33) * k3_128; - v0 ^= rotateRight((v0 * k2_128) * v1, 22) * k1_128; - } - - if (buffer.length >= 1) { - v1 += (long) buffer[0] * k2_128; - v1 = rotateRight(v1, 33) * k3_128; - v1 ^= rotateRight((v1 * k3_128) + v0, 58) * k0_128; - } - - v0 += rotateRight((v0 * k0_128) + v1, 13); - v1 += rotateRight((v1 * k1_128) + v0, 37); - v0 += rotateRight((v0 * k2_128) + v1, 13); - v1 += rotateRight((v1 * k3_128) + v0, 37); - - return new Number128(v0, v1); - } - - - // region =========== Private methods - private static long littleEndian64(final byte[] b, final int start) { - return ByteUtil.bytesToLong(b, start, ByteOrder.LITTLE_ENDIAN); - } - - private static int littleEndian32(final byte[] b) { - return (int) b[0] | (int) b[1] << 8 | (int) b[2] << 16 | (int) b[3] << 24; - } - - private static int littleEndian16(final byte[] b) { - return ByteUtil.bytesToShort(b, ByteOrder.LITTLE_ENDIAN); - } - - private static long rotateLeft64(final long x, final int k) { - final int n = 64; - final int s = k & (n - 1); - return x << s | x >> (n - s); - } - - private static long rotateRight(final long val, final int shift) { - return (val >> shift) | (val << (64 - shift)); - } - // endregion =========== Private methods -} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java new file mode 100644 index 000000000..240f060f0 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java @@ -0,0 +1,63 @@ +package cn.hutool.core.codec.hash.metro; + +import java.nio.ByteBuffer; + +/** + * Apache 发布的MetroHash算法抽象实现,是一组用于非加密用例的最先进的哈希函数。 + * 除了卓越的性能外,他们还以算法生成而著称。 + * + *

          + * 官方实现:https://github.com/jandrewrogers/MetroHash + * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ + * 来自:https://github.com/postamar/java-metrohash/ + * + * @author Marius Posta + * @param 返回值类型,为this类型 + */ +public abstract class AbstractMetroHash> implements MetroHash { + + final long seed; + long v0, v1, v2, v3; + long nChunks; + + /** + * 使用指定种子构造 + * + * @param seed 种子 + */ + public AbstractMetroHash(final long seed) { + this.seed = seed; + reset(); + } + + /** + * Applies the instance's Metro hash function to the bytes in the given buffer. + * This updates this instance's hashing state. + * + * @param input 内容 + * @return this + */ + public R apply(final ByteBuffer input) { + reset(); + while (input.remaining() >= 32) { + partialApply32ByteChunk(input); + } + return partialApplyRemaining(input); + } + + /** + * Consumes a 32-byte chunk from the byte buffer and updates the hashing state. + * + * @param partialInput byte buffer with at least 32 bytes remaining. + * @return this + */ + abstract R partialApply32ByteChunk(ByteBuffer partialInput); + + /** + * Consumes the remaining bytes from the byte buffer and updates the hashing state. + * + * @param partialInput byte buffer with less than 32 bytes remaining. + * @return this + */ + abstract R partialApplyRemaining(ByteBuffer partialInput); +} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java new file mode 100644 index 000000000..940e2e9fc --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java @@ -0,0 +1,56 @@ +package cn.hutool.core.codec.hash.metro; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * Apache 发布的MetroHash算法接口,是一组用于非加密用例的最先进的哈希函数。 + * 除了卓越的性能外,他们还以算法生成而著称。 + * + *

          + * 官方实现:https://github.com/jandrewrogers/MetroHash + * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ + * 来自:https://github.com/postamar/java-metrohash/ + * + * @param 返回值类型,为this类型 + * @author Marius Posta + */ +public interface MetroHash> { + + /** + * 创建 {@code MetroHash}对象 + * + * @param seed 种子 + * @param is128 是否128位 + * @return {@code MetroHash}对象 + */ + static MetroHash of(final long seed, final boolean is128) { + return is128 ? new MetroHash128(seed) : new MetroHash64(seed); + } + + /** + * Applies the instance's Metro hash function to the bytes in the given buffer. + * This updates this instance's hashing state. + * + * @param input 内容 + * @return this + */ + R apply(final ByteBuffer input); + + /** + * Writes the current hash to the given byte buffer in big-endian order. + * 将结果hash值写出到{@link ByteBuffer}中 + * + * @param output 输出 + * @param byteOrder 端序 + * @return this + */ + R write(ByteBuffer output, final ByteOrder byteOrder); + + /** + * 重置,重置后可复用对象开启新的计算 + * + * @return this + */ + R reset(); +} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java new file mode 100644 index 000000000..5a905f696 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java @@ -0,0 +1,182 @@ +package cn.hutool.core.codec.hash.metro; + +import cn.hutool.core.codec.Number128; +import cn.hutool.core.codec.hash.Hash128; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * Apache 发布的MetroHash算法的128位实现,是一组用于非加密用例的最先进的哈希函数。 + * 除了卓越的性能外,他们还以算法生成而著称。 + * + *

          + * 官方实现:https://github.com/jandrewrogers/MetroHash + * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ + * 来自:https://github.com/postamar/java-metrohash/ + * @author Marius Posta + */ +public class MetroHash128 extends AbstractMetroHash implements Hash128 { + + /** + * 创建 {@code MetroHash128}对象 + * + * @param seed 种子 + * @return {@code MetroHash128}对象 + */ + public static MetroHash128 of(final long seed) { + return new MetroHash128(seed); + } + + private static final long K0 = 0xC83A91E1L; + private static final long K1 = 0x8648DBDBL; + private static final long K2 = 0x7BDEC03BL; + private static final long K3 = 0x2F5870A5L; + + /** + * 使用指定种子构造 + * + * @param seed 种子 + */ + public MetroHash128(final long seed) { + super(seed); + } + + @Override + public MetroHash128 reset() { + v0 = (seed - K0) * K3; + v1 = (seed + K1) * K2; + v2 = (seed + K0) * K2; + v3 = (seed - K1) * K3; + nChunks = 0; + return this; + } + + /** + * 获取高64位结果hash值 + * + * @return hash值 + */ + public long getHigh() { + return v0; + } + + /** + * 获取低64位结果hash值 + * + * @return hash值 + */ + public long getLow() { + return v1; + } + + /** + * 获取结果hash值 + * + * @return hash值 + */ + public Number128 get() { + return new Number128(v1, v0); + } + + @Override + public Number128 hash128(final byte[] bytes) { + return apply(ByteBuffer.wrap(bytes)).get(); + } + + @Override + public MetroHash128 write(final ByteBuffer output, final ByteOrder byteOrder) { + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + MetroHashInternalUtil.writeLittleEndian(v0, output); + MetroHashInternalUtil.writeLittleEndian(v1, output); + } else { + output.asLongBuffer().put(v1).put(v0); + } + return this; + } + + @Override + MetroHash128 partialApply32ByteChunk(final ByteBuffer partialInput) { + assert partialInput.remaining() >= 32; + v0 += MetroHashInternalUtil.grab8(partialInput) * K0; + v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2; + v1 += MetroHashInternalUtil.grab8(partialInput) * K1; + v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3; + v2 += MetroHashInternalUtil.grab8(partialInput) * K2; + v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0; + v3 += MetroHashInternalUtil.grab8(partialInput) * K3; + v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1; + ++nChunks; + return this; + } + + @Override + MetroHash128 partialApplyRemaining(final ByteBuffer partialInput) { + assert partialInput.remaining() < 32; + if (nChunks > 0) { + metroHash128_32(); + } + if (partialInput.remaining() >= 16) { + metroHash128_16(partialInput); + } + if (partialInput.remaining() >= 8) { + metroHash128_8(partialInput); + } + if (partialInput.remaining() >= 4) { + metroHash128_4(partialInput); + } + if (partialInput.remaining() >= 2) { + metroHash128_2(partialInput); + } + if (partialInput.remaining() >= 1) { + metroHash128_1(partialInput); + } + v0 += MetroHashInternalUtil.rotateRight64(v0 * K0 + v1, 13); + v1 += MetroHashInternalUtil.rotateRight64(v1 * K1 + v0, 37); + v0 += MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 13); + v1 += MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 37); + return this; + } + + // region ----- private methods + private void metroHash128_32() { + v2 ^= MetroHashInternalUtil.rotateRight64((v0 + v3) * K0 + v1, 21) * K1; + v3 ^= MetroHashInternalUtil.rotateRight64((v1 + v2) * K1 + v0, 21) * K0; + v0 ^= MetroHashInternalUtil.rotateRight64((v0 + v2) * K0 + v3, 21) * K1; + v1 ^= MetroHashInternalUtil.rotateRight64((v1 + v3) * K1 + v2, 21) * K0; + } + + private void metroHash128_16(final ByteBuffer bb) { + v0 += MetroHashInternalUtil.grab8(bb) * K2; + v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; + v1 += MetroHashInternalUtil.grab8(bb) * K2; + v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; + v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 45) * K1; + v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 45) * K0; + } + + private void metroHash128_8(final ByteBuffer bb) { + v0 += MetroHashInternalUtil.grab8(bb) * K2; + v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; + v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 27) * K1; + } + + private void metroHash128_4(final ByteBuffer bb) { + v1 += MetroHashInternalUtil.grab4(bb) * K2; + v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; + v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 46) * K0; + } + + private void metroHash128_2(final ByteBuffer bb) { + v0 += MetroHashInternalUtil.grab2(bb) * K2; + v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; + v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 22) * K1; + } + + private void metroHash128_1(final ByteBuffer bb) { + v1 += MetroHashInternalUtil.grab1(bb) * K2; + v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; + v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 58) * K0; + } + // endregion +} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java new file mode 100644 index 000000000..8f9a78514 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java @@ -0,0 +1,158 @@ +package cn.hutool.core.codec.hash.metro; + +import cn.hutool.core.codec.hash.Hash64; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * Apache 发布的MetroHash算法的64位实现,是一组用于非加密用例的最先进的哈希函数。 + * 除了卓越的性能外,他们还以算法生成而著称。 + * + *

          + * 官方实现:https://github.com/jandrewrogers/MetroHash + * 官方文档:http://www.jandrewrogers.com/2015/05/27/metrohash/ + * 来自:https://github.com/postamar/java-metrohash/ + * @author Marius Posta + */ +public class MetroHash64 extends AbstractMetroHash implements Hash64 { + + /** + * 创建 {@code MetroHash64}对象 + * + * @param seed 种子 + * @return {@code MetroHash64}对象 + */ + public static MetroHash64 of(final long seed) { + return new MetroHash64(seed); + } + + private static final long K0 = 0xD6D018F5L; + private static final long K1 = 0xA2AA033BL; + private static final long K2 = 0x62992FC1L; + private static final long K3 = 0x30BC5B29L; + + private long hash; + + /** + * 使用指定种子构造 + * + * @param seed 种子 + */ + public MetroHash64(final long seed) { + super(seed); + } + + @Override + public MetroHash64 reset() { + v0 = v1 = v2 = v3 = hash = (seed + K2) * K0; + nChunks = 0; + return this; + } + + /** + * 获取计算结果hash值 + * + * @return hash值 + */ + public long get() { + return hash; + } + + @Override + public long hash64(final byte[] bytes) { + return apply(ByteBuffer.wrap(bytes)).get(); + } + + @Override + public MetroHash64 write(final ByteBuffer output, final ByteOrder byteOrder) { + if(ByteOrder.LITTLE_ENDIAN == byteOrder){ + MetroHashInternalUtil.writeLittleEndian(hash, output); + } else{ + output.asLongBuffer().put(hash); + } + return this; + } + + @Override + MetroHash64 partialApply32ByteChunk(final ByteBuffer partialInput) { + assert partialInput.remaining() >= 32; + v0 += MetroHashInternalUtil.grab8(partialInput) * K0; + v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2; + v1 += MetroHashInternalUtil.grab8(partialInput) * K1; + v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3; + v2 += MetroHashInternalUtil.grab8(partialInput) * K2; + v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0; + v3 += MetroHashInternalUtil.grab8(partialInput) * K3; + v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1; + ++nChunks; + return this; + } + + @Override + MetroHash64 partialApplyRemaining(final ByteBuffer partialInput) { + assert partialInput.remaining() < 32; + if (nChunks > 0) { + metroHash64_32(); + } + if (partialInput.remaining() >= 16) { + metroHash64_16(partialInput); + } + if (partialInput.remaining() >= 8) { + metroHash64_8(partialInput); + } + if (partialInput.remaining() >= 4) { + metroHash64_4(partialInput); + } + if (partialInput.remaining() >= 2) { + metroHash64_2(partialInput); + } + if (partialInput.remaining() >= 1) { + metroHash64_1(partialInput); + } + hash ^= MetroHashInternalUtil.rotateRight64(hash, 28); + hash *= K0; + hash ^= MetroHashInternalUtil.rotateRight64(hash, 29); + return this; + } + + // region ----- private methods + private void metroHash64_32() { + v2 ^= MetroHashInternalUtil.rotateRight64(((v0 + v3) * K0) + v1, 37) * K1; + v3 ^= MetroHashInternalUtil.rotateRight64(((v1 + v2) * K1) + v0, 37) * K0; + v0 ^= MetroHashInternalUtil.rotateRight64(((v0 + v2) * K0) + v3, 37) * K1; + v1 ^= MetroHashInternalUtil.rotateRight64(((v1 + v3) * K1) + v2, 37) * K0; + hash += v0 ^ v1; + } + + private void metroHash64_16(final ByteBuffer bb) { + v0 = hash + MetroHashInternalUtil.grab8(bb) * K2; + v0 = MetroHashInternalUtil.rotateRight64(v0, 29) * K3; + v1 = hash + MetroHashInternalUtil.grab8(bb) * K2; + v1 = MetroHashInternalUtil.rotateRight64(v1, 29) * K3; + v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K0, 21) + v1; + v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3, 21) + v0; + hash += v1; + } + + private void metroHash64_8(final ByteBuffer bb) { + hash += MetroHashInternalUtil.grab8(bb) * K3; + hash ^= MetroHashInternalUtil.rotateRight64(hash, 55) * K1; + } + + private void metroHash64_4(final ByteBuffer bb) { + hash += MetroHashInternalUtil.grab4(bb) * K3; + hash ^= MetroHashInternalUtil.rotateRight64(hash, 26) * K1; + } + + private void metroHash64_2(final ByteBuffer bb) { + hash += MetroHashInternalUtil.grab2(bb) * K3; + hash ^= MetroHashInternalUtil.rotateRight64(hash, 48) * K1; + } + + private void metroHash64_1(final ByteBuffer bb) { + hash += MetroHashInternalUtil.grab1(bb) * K3; + hash ^= MetroHashInternalUtil.rotateRight64(hash, 37) * K1; + } + // endregion +} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java new file mode 100644 index 000000000..2a4e49713 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java @@ -0,0 +1,51 @@ +package cn.hutool.core.codec.hash.metro; + +import java.nio.ByteBuffer; + +class MetroHashInternalUtil { + + static void writeLittleEndian(final long hash, final ByteBuffer output) { + output.put((byte) hash); + output.put((byte) (hash >>> 8)); + output.put((byte) (hash >>> 16)); + output.put((byte) (hash >>> 24)); + output.put((byte) (hash >>> 32)); + output.put((byte) (hash >>> 40)); + output.put((byte) (hash >>> 48)); + output.put((byte) (hash >>> 56)); + } + + static long rotateRight64(final long x, final int r) { + return (x >>> r) | (x << (64 - r)); + } + + static long grab1(final ByteBuffer bb) { + return ((long) bb.get() & 0xFFL); + } + + static long grab2(final ByteBuffer bb) { + final long v0 = bb.get(); + final long v1 = bb.get(); + return (v0 & 0xFFL) | (v1 & 0xFFL) << 8; + } + + static long grab4(final ByteBuffer bb) { + final long v0 = bb.get(); + final long v1 = bb.get(); + final long v2 = bb.get(); + final long v3 = bb.get(); + return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24; + } + + static long grab8(final ByteBuffer bb) { + final long v0 = bb.get(); + final long v1 = bb.get(); + final long v2 = bb.get(); + final long v3 = bb.get(); + final long v4 = bb.get(); + final long v5 = bb.get(); + final long v6 = bb.get(); + final long v7 = bb.get(); + return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24 | (v4 & 0xFFL) << 32 | (v5 & 0xFFL) << 40 | (v6 & 0xFFL) << 48 | (v7 & 0xFFL) << 56; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/package-info.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/package-info.java new file mode 100644 index 000000000..56377cadb --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/package-info.java @@ -0,0 +1,8 @@ +/** + * MetroHash算法实现
          + *

          + * 参考:https://github.com/postamar/java-metrohash + * + * @author postamar, looly + */ +package cn.hutool.core.codec.hash.metro; diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/iter/LineIter.java b/hutool-core/src/main/java/cn/hutool/core/collection/iter/LineIter.java index c22c4cce7..9933dfb53 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/iter/LineIter.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/iter/LineIter.java @@ -95,6 +95,7 @@ public class LineIter extends ComputeIter implements IterableIter @@ -18,6 +12,7 @@ import java.util.Objects; * * @author looly * @since 3.0.7 + * @param 被比较的对象 */ public class ComparatorChain implements Chain, ComparatorChain>, Comparator, Serializable { private static final long serialVersionUID = -2426725788913962429L; @@ -38,11 +33,11 @@ public class ComparatorChain implements Chain, ComparatorChain< //------------------------------------------------------------------------------------- Static method start /** - * 构建 {@link ComparatorChain} + * 构建 {@code ComparatorChain} * * @param 被比较对象类型 * @param comparator 比较器 - * @return {@link ComparatorChain} + * @return {@code ComparatorChain} * @since 5.4.3 */ public static ComparatorChain of(final Comparator comparator) { @@ -50,12 +45,12 @@ public class ComparatorChain implements Chain, ComparatorChain< } /** - * 构建 {@link ComparatorChain} + * 构建 {@code ComparatorChain} * * @param 被比较对象类型 * @param comparator 比较器 * @param reverse 是否反向 - * @return {@link ComparatorChain} + * @return {@code ComparatorChain} * @since 5.4.3 */ public static ComparatorChain of(final Comparator comparator, final boolean reverse) { @@ -63,11 +58,11 @@ public class ComparatorChain implements Chain, ComparatorChain< } /** - * 构建 {@link ComparatorChain} + * 构建 {@code ComparatorChain} * * @param 被比较对象类型 * @param comparators 比较器数组 - * @return {@link ComparatorChain} + * @return {@code ComparatorChain} * @since 5.4.3 */ @SafeVarargs @@ -76,11 +71,11 @@ public class ComparatorChain implements Chain, ComparatorChain< } /** - * 构建 {@link ComparatorChain} + * 构建 {@code ComparatorChain} * * @param 被比较对象类型 * @param comparators 比较器列表 - * @return {@link ComparatorChain} + * @return {@code ComparatorChain} * @since 5.4.3 */ public static ComparatorChain of(final List> comparators) { @@ -88,12 +83,12 @@ public class ComparatorChain implements Chain, ComparatorChain< } /** - * 构建 {@link ComparatorChain} + * 构建 {@code ComparatorChain} * * @param 被比较对象类型 * @param comparators 比较器列表 * @param bits {@link Comparator} 列表对应的排序boolean值,true表示正序,false反序 - * @return {@link ComparatorChain} + * @return {@code ComparatorChain} * @since 5.4.3 */ public static ComparatorChain of(final List> comparators, final BitSet bits) { diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java index abcc4eb32..6962446f0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java @@ -830,6 +830,7 @@ public class Convert { * @param notConvertSet 不替换的字符集合 * @return 替换后的字符 */ + @SuppressWarnings("UnnecessaryUnicodeEscape") public static String toDBC(final String text, final Set notConvertSet) { if(StrUtil.isBlank(text)) { return text; diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java index bc089791b..b26209fb7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java @@ -24,6 +24,9 @@ import java.util.List; public class ArrayConverter extends AbstractConverter { private static final long serialVersionUID = 1L; + /** + * 单例 + */ public static final ArrayConverter INSTANCE = new ArrayConverter(); /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/Quarter.java b/hutool-core/src/main/java/cn/hutool/core/date/Quarter.java index 454a2f33d..e1920e2bf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/Quarter.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/Quarter.java @@ -3,23 +3,29 @@ package cn.hutool.core.date; /** * 季度枚举 * + * @author zhfish(https : / / github.com / zhfish) * @see #Q1 * @see #Q2 * @see #Q3 * @see #Q4 - * - * @author zhfish(https://github.com/zhfish) - * */ public enum Quarter { - /** 第一季度 */ + /** + * 第一季度 + */ Q1(1), - /** 第二季度 */ + /** + * 第二季度 + */ Q2(2), - /** 第三季度 */ + /** + * 第三季度 + */ Q3(3), - /** 第四季度 */ + /** + * 第四季度 + */ Q4(4); // --------------------------------------------------------------- @@ -29,6 +35,11 @@ public enum Quarter { this.value = value; } + /** + * 获取季度值 + * + * @return 季度值 + */ public int getValue() { return this.value; } @@ -36,13 +47,12 @@ public enum Quarter { /** * 将 季度int转换为Season枚举对象
          * + * @param intValue 季度int表示 + * @return {@code Quarter} * @see #Q1 * @see #Q2 * @see #Q3 * @see #Q4 - * - * @param intValue 季度int表示 - * @return {@link Quarter} */ public static Quarter of(final int intValue) { switch (intValue) { diff --git a/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java b/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java index 5f9cf30f7..dd6f960e9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java @@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit; * System.currentTimeMillis()的调用比new一个普通对象要耗时的多(具体耗时高出多少我还没测试过,有人说是100倍左右) * System.currentTimeMillis()之所以慢是因为去跟系统打了一次交道 * 后台定时更新时钟,JVM退出时,线程自动回收 - * + *

          * see: http://git.oschina.net/yu120/sequence * @author lry, looly */ diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java index 1d23e0389..11170f4ad 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java @@ -573,17 +573,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mValue = value; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return mValue.length(); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValue); @@ -610,9 +604,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mValues = values; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { int max = 0; @@ -625,9 +616,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { return max; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValues[calendar.get(mField)]); @@ -651,25 +639,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mField = field; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 4; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 10) { @@ -697,25 +676,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { UnpaddedMonthField() { } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 2; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.MONTH) + 1); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 10) { @@ -750,25 +720,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mSize = size; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return mSize; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { appendFullDigits(buffer, value, mSize); @@ -792,25 +753,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mField = field; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 2; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 100) { @@ -835,25 +787,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { TwoDigitYearField() { } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 2; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.YEAR) % 100); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { appendDigits(buffer, value); @@ -874,25 +817,16 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { TwoDigitMonthField() { } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 2; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.MONTH) + 1); } - /** - * {@inheritDoc} - */ @Override public final void appendTo(final Appendable buffer, final int value) throws IOException { appendDigits(buffer, value); @@ -916,17 +850,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mRule = rule; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return mRule.estimateLength(); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int value = calendar.get(Calendar.HOUR); @@ -936,9 +864,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mRule.appendTo(buffer, value); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final int value) throws IOException { mRule.appendTo(buffer, value); @@ -962,17 +887,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mRule = rule; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return mRule.estimateLength(); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int value = calendar.get(Calendar.HOUR_OF_DAY); @@ -982,9 +901,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mRule.appendTo(buffer, value); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final int value) throws IOException { mRule.appendTo(buffer, value); @@ -1103,9 +1019,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { // We have no access to the Calendar object that will be passed to @@ -1114,9 +1027,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { return Math.max(mStandard.length(), mDaylight.length()); } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { final TimeZone zone = calendar.getTimeZone(); @@ -1148,17 +1058,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mColon = colon; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return 5; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { @@ -1227,17 +1131,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { this.length = length; } - /** - * {@inheritDoc} - */ @Override public int estimateLength() { return length; } - /** - * {@inheritDoc} - */ @Override public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); @@ -1298,17 +1196,11 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { mLocale = locale; } - /** - * {@inheritDoc} - */ @Override public int hashCode() { return (mStyle * 31 + mLocale.hashCode()) * 31 + mTimeZone.hashCode(); } - /** - * {@inheritDoc} - */ @Override public boolean equals(final Object obj) { if (this == obj) { diff --git a/hutool-core/src/main/java/cn/hutool/core/io/AppendableWriter.java b/hutool-core/src/main/java/cn/hutool/core/io/AppendableWriter.java index 25b966d54..e339f6fce 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/AppendableWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/AppendableWriter.java @@ -19,6 +19,11 @@ public class AppendableWriter extends Writer implements Appendable { private final boolean flushable; private boolean closed; + /** + * 构造 + * + * @param appendable {@link Appendable} + */ public AppendableWriter(final Appendable appendable) { this.appendable = appendable; this.flushable = appendable instanceof Flushable; diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java index aee176854..a167ad627 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/visitor/DelVisitor.java @@ -1,7 +1,5 @@ package cn.hutool.core.io.file.visitor; -import cn.hutool.core.lang.Console; - import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -17,6 +15,9 @@ import java.nio.file.attribute.BasicFileAttributes; */ public class DelVisitor extends SimpleFileVisitor { + /** + * 单例对象 + */ public static DelVisitor INSTANCE = new DelVisitor(); @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/DelayWatcher.java b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/DelayWatcher.java index b84bb88f2..389b35557 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/DelayWatcher.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/DelayWatcher.java @@ -33,7 +33,7 @@ public class DelayWatcher implements Watcher { //---------------------------------------------------------------------------------------------------------- Constructor start /** * 构造 - * @param watcher 实际处理触发事件的监视器{@link Watcher},不可以是{@link DelayWatcher} + * @param watcher 实际处理触发事件的监视器{@link Watcher},不可以是{@code DelayWatcher} * @param delay 延迟时间,单位毫秒 */ public DelayWatcher(final Watcher watcher, final long delay) { diff --git a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java index 0e572b261..00be41a41 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/watch/watchers/WatcherChain.java @@ -1,6 +1,5 @@ package cn.hutool.core.io.watch.watchers; -import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.watch.Watcher; import cn.hutool.core.lang.Chain; @@ -23,9 +22,9 @@ public class WatcherChain implements Watcher, Chain{ final private List chain; /** - * 创建观察者链{@link WatcherChain} + * 创建观察者链{@code WatcherChain} * @param watchers 观察者列表 - * @return {@link WatcherChain} + * @return {@code WatcherChain} */ public static WatcherChain of(final Watcher... watchers) { return new WatcherChain(watchers); diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java index acc77e781..cb0d81c5e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java @@ -28,11 +28,10 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.text.StrUtil; -import java.util.Objects; -import java.util.Optional; import java.util.Collection; import java.util.NoSuchElementException; -import java.util.concurrent.Callable; +import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ansi/AnsiStyle.java b/hutool-core/src/main/java/cn/hutool/core/lang/ansi/AnsiStyle.java index 9339b0260..17a8987c1 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ansi/AnsiStyle.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ansi/AnsiStyle.java @@ -39,7 +39,7 @@ public enum AnsiStyle implements AnsiElement { private final int code; - AnsiStyle(int code) { + AnsiStyle(final int code) { this.code = code; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java index b17f51234..eb32fef71 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/Bound.java @@ -41,12 +41,12 @@ public interface Bound> extends Predicate, Co /** * 无穷小的描述 */ - String INFINITE_MIN = "-\u221e"; + String INFINITE_MIN = "-∞"; /** * 无穷大的藐视 */ - String INFINITE_MAX = "+\u221e"; + String INFINITE_MAX = "+∞"; // region --------------- static methods /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneLowerBound.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneLowerBound.java index b9d69d397..5915e771c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneLowerBound.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneLowerBound.java @@ -54,12 +54,13 @@ class NoneLowerBound> implements Bound { *

            *
          • -1:t1t2的左侧;
          • *
          • 0:t1t2的重合;
          • - *
          • -1:t1t2的右侧;
          • + *
          • -1:t1t2的右侧;(不存在)
          • *
          * * @param bound 边界 * @return 位置 */ + @SuppressWarnings("ComparatorMethodParameterNotUsed") @Override public int compareTo(final Bound bound) { return bound instanceof NoneLowerBound ? 0 : -1; @@ -102,7 +103,7 @@ class NoneLowerBound> implements Bound { */ @Override public String toString() { - return "{x | x > -\u221e}"; + return "{x | x > -∞}"; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneUpperBound.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneUpperBound.java index 8112dbdd1..27429ef0c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneUpperBound.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/NoneUpperBound.java @@ -80,7 +80,7 @@ class NoneUpperBound> implements Bound { */ @Override public String toString() { - return "{x | x < +\u221e}"; + return "{x | x < +∞}"; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/map/multi/RowKeyTable.java b/hutool-core/src/main/java/cn/hutool/core/map/multi/RowKeyTable.java index 043d440e3..2ec36535a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/multi/RowKeyTable.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/multi/RowKeyTable.java @@ -206,7 +206,7 @@ public class RowKeyTable extends AbsTable { final Collection> values = this.raw.values(); final List result = new ArrayList<>(values.size() * 16); for (final Map map : values) { - map.forEach((key, value)->{result.add(key);}); + map.forEach((key, value)-> result.add(key)); } return result; } diff --git a/hutool-core/src/main/java/cn/hutool/core/math/BitStatusUtil.java b/hutool-core/src/main/java/cn/hutool/core/math/BitStatusUtil.java index 522a35861..667ea41e0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/BitStatusUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/BitStatusUtil.java @@ -3,7 +3,7 @@ package cn.hutool.core.math; /** * 通过位运算表示状态的工具类
          * 参数必须是 `偶数` 且 `大于等于0`! - * + *

          * 工具实现见博客:https://blog.starxg.com/2020/11/bit-status/ * * @author huangxingguang,senssic diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java index 063fab56b..4034e9f42 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java @@ -121,7 +121,7 @@ public class MethodHandleUtil { * return "Quack"; * } * } - * + *

          * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, @@ -167,7 +167,7 @@ public class MethodHandleUtil { * return "Quack"; * } * } - * + *

          * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, @@ -193,7 +193,7 @@ public class MethodHandleUtil { * return "Quack"; * } * } - * + *

          * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, diff --git a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java index 87ec9b9f0..3c015c1a9 100755 --- a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java @@ -893,7 +893,7 @@ public class ReUtil { /** * 替换所有正则匹配的文本,并使用自定义函数决定如何替换
          * replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。 - * + *

          *

           	 *     replaceAll(this.content, "(\\d+)", parameters -> "-" + parameters.group(1) + "-")
           	 *     // 结果为:"ZZZaaabbbccc中文-1234-"
          @@ -912,7 +912,7 @@ public class ReUtil {
           	/**
           	 * 替换所有正则匹配的文本,并使用自定义函数决定如何替换
          * replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。 - * + *

          *

           	 *     replaceAll(this.content, "(\\d+)", parameters -> "-" + parameters.group(1) + "-")
           	 *     // 结果为:"ZZZaaabbbccc中文-1234-"
          diff --git a/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java b/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java
          index cffdfa3ae..7fa9b3dd2 100755
          --- a/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java
          +++ b/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java
          @@ -513,6 +513,13 @@ public class AntPathMatcher {
           		return builder.toString();
           	}
           
          +	/**
          +	 * 提取参数
          +	 *
          +	 * @param pattern 模式
          +	 * @param path 路径
          +	 * @return 参数
          +	 */
           	public Map extractUriTemplateVariables(final String pattern, final String path) {
           		final Map variables = new LinkedHashMap<>();
           		final boolean result = doMatch(pattern, path, true, variables);
          diff --git a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
          index 023ab98bc..ee21b2128 100644
          --- a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
          +++ b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
          @@ -12,6 +12,7 @@ import cn.hutool.core.text.replacer.LookupReplacer;
           public class Html4Escape extends XmlEscape {
           	private static final long serialVersionUID = 1L;
           
          +	@SuppressWarnings("UnnecessaryUnicodeEscape")
           	protected static final String[][] ISO8859_1_ESCAPE = { //
           			{ "\u00A0", " " }, // non-breaking space
           			{ "\u00A1", "¡" }, // inverted exclamation mark
          @@ -111,6 +112,7 @@ public class Html4Escape extends XmlEscape {
           			{ "\u00FF", "ÿ" }, // � - lowercase y, umlaut
           	};
           
          +	@SuppressWarnings("UnnecessaryUnicodeEscape")
           	protected static final String[][] HTML40_EXTENDED_ESCAPE = {
           			// 
           			{ "\u0192", "ƒ" }, // latin small f with hook = function= florin, U+0192 ISOtech -->
          @@ -308,6 +310,9 @@ public class Html4Escape extends XmlEscape {
           			{ "\u20AC", "€" }, // -- euro sign, U+20AC NEW -->
           	};
           
          +	/**
          +	 * 构造
          +	 */
           	public Html4Escape() {
           		super();
           		addChain(new LookupReplacer(ISO8859_1_ESCAPE));
          diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/BlockPolicy.java b/hutool-core/src/main/java/cn/hutool/core/thread/BlockPolicy.java
          index 724b9daa8..4729da7db 100755
          --- a/hutool-core/src/main/java/cn/hutool/core/thread/BlockPolicy.java
          +++ b/hutool-core/src/main/java/cn/hutool/core/thread/BlockPolicy.java
          @@ -9,7 +9,7 @@ import java.util.function.Consumer;
            * 当任务队列过长时处于阻塞状态,直到添加到队列中
            * 如果阻塞过程中被中断,就会抛出{@link InterruptedException}异常
          * 有时候在线程池内访问第三方接口,只希望固定并发数去访问,并且不希望丢弃任务时使用此策略,队列满的时候会处于阻塞状态(例如刷库的场景) - * + *

          * 其他系统内置的拒绝策略,见hutool定义的枚举 {@link RejectPolicy} 线程拒绝策略枚举. * * @author luozongle diff --git a/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java index f16e7d81c..6825f0c07 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java @@ -1,7 +1,6 @@ package cn.hutool.core.util; import cn.hutool.core.collection.SetUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.core.text.StrUtil; import java.util.Set; diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java index 1e675cae3..a58668b0e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java @@ -298,12 +298,12 @@ public class ByteUtil { if (ByteOrder.LITTLE_ENDIAN == byteOrder) { for (int i = (Long.BYTES - 1); i >= 0; i--) { values <<= Byte.SIZE; - values |= (bytes[i + start] & 0xff); + values |= (bytes[i + start] & 0xffL); } } else { for (int i = 0; i < Long.BYTES; i++) { values <<= Byte.SIZE; - values |= (bytes[i + start] & 0xff); + values |= (bytes[i + start] & 0xffL); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java new file mode 100644 index 000000000..0f2da98b7 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java @@ -0,0 +1,119 @@ +package cn.hutool.core.codec.hash.metro; + +import cn.hutool.core.codec.HexUtil; +import cn.hutool.core.text.StrUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class MetroHash128Test { + @Test + public void testEmpty() { + Assert.assertEquals("5F3CA3D41D1CB4606B14684C65FB6", h128("")); + } + + @Test + public void test1Low() { + Assert.assertEquals("E84D9EA70174C3184AC6E55552310F85", h128("a")); + } + + @Test + public void test1High() { + Assert.assertEquals("9A5BCED4C3CA98CADE13388E3C14C215", h128("é")); + } + + @Test + public void test2Palindrome() { + Assert.assertEquals("3DDDF558587273E1FD034EC7CC917AC8", h128("aa")); + } + + @Test + public void test2() { + Assert.assertEquals("458E6A18B65C38AD2552335402A068A2", h128("ab")); + } + + @Test + public void test3PalindromeLow() { + Assert.assertEquals("19725A6E67A8DD1A84E3C844A20DA938", h128("aaa")); + } + + @Test + public void test3PalindromeHigh() { + Assert.assertEquals("1DD9CC1D29B5080D5F9F171FB2C50CBB", h128("ééé")); + } + + @Test + public void test3() { + Assert.assertEquals("89AB9CDB9FAF7BA71CD86385C1F801A5", h128("abc")); + } + + @Test + public void test4Palindrome() { + Assert.assertEquals("AFD0BBB3764CA0539E46B914B8CB8911", h128("poop")); + } + + @Test + public void test4() { + Assert.assertEquals("D11B6DB94FE20E3884F3829AD6613D19", h128("fart")); + } + + @Test + public void test5() { + Assert.assertEquals("D45A3A74885F9C842081929D2E9A3A3B", h128("Hello")); + } + + @Test + public void test12() { + Assert.assertEquals("A7CEC59B03A9053BA6009EEEC81E81F5", h128("Hello World!")); + } + + @Test + public void test31() { + Assert.assertEquals("980CA7496A1B26D24E529DFB2B3A870", + h128("The Quick Brown Fox Jumped Over")); + } + + @Test + public void test32() { + Assert.assertEquals("76663CEA442E22F86A6CB41FBA896B9B", + h128("The Quick Brown Fox Jumped Over ")); + } + + @Test + public void testLonger() { + Assert.assertEquals("7010B2D7C8A3515AE3CA4DBBD9ED30D0", + h128("The Quick Brown Fox Jumped Over The Lazy Dog")); + } + + static final byte[] ENDIAN = + StrUtil.utf8Bytes("012345678901234567890123456789012345678901234567890123456789012"); + + @Test + public void testLittleEndian() { + final ByteBuffer output = ByteBuffer.allocate(16); + MetroHash128.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals("C77CE2BFA4ED9F9B0548B2AC5074A297", hex(output.array())); + } + + @Test + public void testBigEndian() { + final ByteBuffer output = ByteBuffer.allocate(16); + MetroHash128.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.BIG_ENDIAN); + Assert.assertEquals("97A27450ACB248059B9FEDA4BFE27CC7", hex(output.array())); + } + + static String h128(final String input) { + final MetroHash128 mh = MetroHash128.of(0).apply(ByteBuffer.wrap(StrUtil.utf8Bytes(input))); + return hex(mh.getHigh()) + hex(mh.getLow()); + } + + private static String hex(final long value){ + return HexUtil.toHex(value).toUpperCase(); + } + + private static String hex(final byte[] bytes){ + return HexUtil.encodeHexStr(bytes).toUpperCase(); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash64Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash64Test.java new file mode 100644 index 000000000..906db1b80 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash64Test.java @@ -0,0 +1,118 @@ +package cn.hutool.core.codec.hash.metro; + +import cn.hutool.core.codec.HexUtil; +import cn.hutool.core.text.StrUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * 来自:https://github.com/postamar/java-metrohash/blob/master/src/test/java/util/hash/MetroHashTest64.java + */ +public class MetroHash64Test { + @Test + public void testEmpty() { + Assert.assertEquals("705FB008071E967D", h64("")); + } + + @Test + public void test1Low() { + Assert.assertEquals("AF6F242B7ED32BCB", h64("a")); + } + + @Test + public void test1High() { + Assert.assertEquals("D51BA21D219C37B3", h64("é")); + } + + @Test + public void test2Palindrome() { + Assert.assertEquals("3CF3A8F204CAE1B6", h64("aa")); + } + + @Test + public void test2() { + Assert.assertEquals("CD2EA2738FC27D98", h64("ab")); + } + + @Test + public void test3PalindromeLow() { + Assert.assertEquals("E59031D8D046D241", h64("aaa")); + } + + @Test + public void test3PalindromeHigh() { + Assert.assertEquals("FE8325DC6F40511D", h64("ééé")); + } + + @Test + public void test3() { + Assert.assertEquals("ED4F5524E6FAFFBB", h64("abc")); + } + + @Test + public void test4Palindrome() { + Assert.assertEquals("CD77F739885CCB2C", h64("poop")); + } + + @Test + public void test4() { + Assert.assertEquals("B642DCB026D9573C", h64("fart")); + } + + @Test + public void test5() { + Assert.assertEquals("A611009FEE6AF8B", h64("Hello")); + } + + @Test + public void test12() { + Assert.assertEquals("14BCB49B74E3B404", h64("Hello World!")); + } + + + @Test + public void test31() { + Assert.assertEquals("D27A7BFACC320E2F", + h64("The Quick Brown Fox Jumped Over")); + } + + @Test + public void test32() { + Assert.assertEquals("C313A3A811EAB43B", + h64("The Quick Brown Fox Jumped Over ")); + } + + @Test + public void testLonger() { + Assert.assertEquals("C7047C2FCA234C05", + h64("The Quick Brown Fox Jumped Over The Lazy Dog")); + } + + static final byte[] ENDIAN = + StrUtil.utf8Bytes("012345678901234567890123456789012345678901234567890123456789012"); + + @Test + public void testLittleEndian() { + final ByteBuffer output = ByteBuffer.allocate(8); + MetroHash64.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals("6B753DAE06704BAD", hex(output.array())); + } + + @Test + public void testBigEndian() { + final ByteBuffer output = ByteBuffer.allocate(8); + MetroHash64.of(0).apply(ByteBuffer.wrap(ENDIAN)).write(output, ByteOrder.BIG_ENDIAN); + Assert.assertEquals("AD4B7006AE3D756B", hex(output.array())); + } + + private String h64(final String value) { + return HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes(value))).toUpperCase(); + } + + private static String hex(final byte[] bytes){ + return HexUtil.encodeHexStr(bytes).toUpperCase(); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/hash/MetroHashTest.java b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHashTest.java old mode 100755 new mode 100644 similarity index 70% rename from hutool-core/src/test/java/cn/hutool/core/codec/hash/MetroHashTest.java rename to hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHashTest.java index 3222ef0ea..a89dceced --- a/hutool-core/src/test/java/cn/hutool/core/codec/hash/MetroHashTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHashTest.java @@ -1,10 +1,11 @@ -package cn.hutool.core.codec.hash; +package cn.hutool.core.codec.hash.metro; -import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.codec.HexUtil; -import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.codec.hash.CityHash; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.RandomUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -16,22 +17,32 @@ public class MetroHashTest { @Test public void testEmpty() { - Assert.assertEquals("31290877cceaea29", HexUtil.toHex(MetroHash.INSTANCE.hash64(StrUtil.utf8Bytes(""), 0))); + Assert.assertEquals("705fb008071e967d", HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes("")))); + } + + @Test + public void test1Low() { + Assert.assertEquals("AF6F242B7ED32BCB", h64("a")); + } + + @Test + public void test1High() { + Assert.assertEquals("D51BA21D219C37B3", h64("é")); } @Test public void metroHash64Test() { final byte[] str = "我是一段测试123".getBytes(CharsetUtil.UTF_8); - final long hash64 = MetroHash.INSTANCE.hash64(str); - Assert.assertEquals(62920234463891865L, hash64); + final long hash64 = MetroHash64.of(0).hash64(str); + Assert.assertEquals(147395857347476456L, hash64); } @Test public void metroHash128Test() { final byte[] str = "我是一段测试123".getBytes(CharsetUtil.UTF_8); - final long[] hash128 = MetroHash.INSTANCE.hash128(str).getLongArray(); - Assert.assertEquals(4956592424592439349L, hash128[0]); - Assert.assertEquals(6301214698325086246L, hash128[1]); + final long[] hash128 = MetroHash128.of(0).hash128(str).getLongArray(); + Assert.assertEquals(228255164667538345L, hash128[0]); + Assert.assertEquals(-6394585948993412256L, hash128[1]); } /** @@ -49,7 +60,7 @@ public class MetroHashTest { final long startMetro = System.currentTimeMillis(); for (final String s : strArray) { - MetroHash.INSTANCE.hash64(StrUtil.utf8Bytes(s)); + MetroHash64.of(0).hash64(StrUtil.utf8Bytes(s)); } final long endMetro = System.currentTimeMillis(); @@ -73,7 +84,7 @@ public class MetroHashTest { final long startMetro = System.currentTimeMillis(); for (final String s : strArray) { - MetroHash.INSTANCE.hash128(StrUtil.utf8Bytes(s)); + MetroHash128.of(0).hash128(StrUtil.utf8Bytes(s)); } final long endMetro = System.currentTimeMillis(); @@ -90,4 +101,8 @@ public class MetroHashTest { } return result; } + + private String h64(final String value) { + return HexUtil.toHex(MetroHash64.of(0).hash64(StrUtil.utf8Bytes(value))).toUpperCase(); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java index 8dd8414e6..4835f593a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/IterUtilTest.java @@ -7,13 +7,7 @@ import lombok.Data; import org.junit.Assert; import org.junit.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; /** * {@link IterUtil} 单元测试 diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java index e3dbf228a..3ecf70dfe 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/partition/PartitionTest.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.ListUtil; import org.junit.Assert; import org.junit.Test; -import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java index dd9ece7f6..b5117c06d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/IoUtilTest.java @@ -11,17 +11,7 @@ import cn.hutool.core.util.RandomUtil; import org.junit.Assert; import org.junit.Test; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PushbackReader; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; +import java.io.*; import java.util.List; public class IoUtilTest { diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/builder/GenericBuilderTest.java similarity index 97% rename from hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java rename to hutool-core/src/test/java/cn/hutool/core/lang/builder/GenericBuilderTest.java index 0703f1848..2b85eb912 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/builder/GenericBuilderTest.java @@ -1,6 +1,5 @@ -package cn.hutool.core.builder; +package cn.hutool.core.lang.builder; -import cn.hutool.core.lang.builder.GenericBuilder; import cn.hutool.core.text.StrUtil; import lombok.Getter; import lombok.Setter; diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java index 0a7ea480e..d12996c0f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/range/BoundTest.java @@ -39,13 +39,13 @@ public class BoundTest { // getValue Assert.assertNull(bound.getValue()); // toString - Assert.assertEquals("(" + "-\u221e", bound.descBound()); + Assert.assertEquals("(" + "-∞", bound.descBound()); // compareTo Assert.assertEquals(0, bound.compareTo(bound)); Assert.assertEquals(-1, bound.compareTo(Bound.atMost(1))); Assert.assertEquals(BoundedRange.all(), bound.toRange()); - Assert.assertEquals("{x | x > -\u221e}", bound.toString()); + Assert.assertEquals("{x | x > -∞}", bound.toString()); } @Test @@ -60,13 +60,13 @@ public class BoundTest { // getValue Assert.assertNull(bound.getValue()); // toString - Assert.assertEquals("+\u221e" + ")", bound.descBound()); + Assert.assertEquals("+∞" + ")", bound.descBound()); // compareTo Assert.assertEquals(0, bound.compareTo(bound)); Assert.assertEquals(1, bound.compareTo(Bound.atMost(1))); Assert.assertEquals(BoundedRange.all(), bound.toRange()); - Assert.assertEquals("{x | x < +\u221e}", bound.toString()); + Assert.assertEquals("{x | x < +∞}", bound.toString()); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/reflect/ActualTypeMapperPoolTest.java b/hutool-core/src/test/java/cn/hutool/core/reflect/ActualTypeMapperPoolTest.java index 7cdd9148f..2ec2ae206 100644 --- a/hutool-core/src/test/java/cn/hutool/core/reflect/ActualTypeMapperPoolTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/reflect/ActualTypeMapperPoolTest.java @@ -1,6 +1,5 @@ package cn.hutool.core.reflect; -import cn.hutool.core.reflect.ActualTypeMapperPool; import org.junit.Assert; import org.junit.Test; @@ -9,7 +8,7 @@ import java.util.Map; /** * 见:https://gitee.com/dromara/hutool/pulls/447/files - * + *

          * TODO 同时继承泛型和实现泛型接口需要解析,此处为F */ public class ActualTypeMapperPoolTest { diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java index afc8a1c4f..7af584b4d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java @@ -591,9 +591,7 @@ public class AbstractEnhancedWrappedStreamTest { public void testMapMulti() { Assert.assertEquals( asList(1, 2, 3), - wrap(1, 2, 3).mapMulti((t, builder) -> { - builder.accept(t); - }).toList() + wrap(1, 2, 3).mapMulti((t, builder) -> builder.accept(t)).toList() ); } diff --git a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java index 871749645..c24d3546b 100755 --- a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java @@ -59,6 +59,7 @@ public class CharSequenceUtilTest { Assert.assertEquals("/", result); } + @SuppressWarnings("UnnecessaryUnicodeEscape") @Test public void normalizeTest() { // https://blog.csdn.net/oscar999/article/details/105326270 @@ -155,6 +156,7 @@ public class CharSequenceUtilTest { Assert.assertNull(CharSequenceUtil.removeSuffixIgnoreCase(null, "ABCdef")); } + @SuppressWarnings("ConstantValue") @Test public void trimToNullTest(){ String a = " "; diff --git a/hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java b/hutool-core/src/test/java/cn/hutool/core/text/dfa/IssueI5Q4HDTest.java similarity index 97% rename from hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java rename to hutool-core/src/test/java/cn/hutool/core/text/dfa/IssueI5Q4HDTest.java index 6cf936efd..1ce0184d7 100755 --- a/hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/dfa/IssueI5Q4HDTest.java @@ -8,7 +8,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -public class issueI5Q4HDTest { +public class IssueI5Q4HDTest { @Test public void matchAllTest(){ diff --git a/hutool-core/src/test/java/cn/hutool/core/util/CharUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/CharUtilTest.java index a9f14d892..14334fc0b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/CharUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/CharUtilTest.java @@ -27,6 +27,7 @@ public class CharUtilTest { Assert.assertTrue(CharUtil.isChar(a)); } + @SuppressWarnings("UnnecessaryUnicodeEscape") @Test public void isBlankCharTest(){ final char a = '\u00A0'; @@ -56,6 +57,7 @@ public class CharUtilTest { Assert.assertEquals('⑳', CharUtil.toCloseByNumber(20)); } + @SuppressWarnings("UnnecessaryUnicodeEscape") @Test public void issueI5UGSQTest(){ char c = '\u3164'; diff --git a/hutool-cron/src/main/java/cn/hutool/cron/pattern/matcher/AlwaysTrueMatcher.java b/hutool-cron/src/main/java/cn/hutool/cron/pattern/matcher/AlwaysTrueMatcher.java index 0c71014de..14f5edfbe 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/pattern/matcher/AlwaysTrueMatcher.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/pattern/matcher/AlwaysTrueMatcher.java @@ -9,6 +9,9 @@ import cn.hutool.core.text.StrUtil; */ public class AlwaysTrueMatcher implements PartMatcher { + /** + * 单例 + */ public static AlwaysTrueMatcher INSTANCE = new AlwaysTrueMatcher(); @Override diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java index 43f3c1d85..ff9a73048 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/SecureUtil.java @@ -18,7 +18,7 @@ import cn.hutool.crypto.symmetric.PBKDF2; import cn.hutool.crypto.symmetric.RC4; import cn.hutool.crypto.symmetric.SymmetricCrypto; import cn.hutool.crypto.symmetric.ZUC; -import cn.hutool.crypto.symmetric.fpe.FPE; +import cn.hutool.crypto.symmetric.FPE; import org.bouncycastle.crypto.AlphabetMapper; import javax.crypto.Cipher; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java index 5fe14ddd0..42d8161a0 100755 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/Sign.java @@ -116,7 +116,7 @@ public class Sign extends BaseAsymmetric { /** * 构造 - * + *

          * 私钥和公钥同时为空时生成一对新的私钥和公钥
          * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证 * @@ -144,7 +144,7 @@ public class Sign extends BaseAsymmetric { /** * 构造 - * + *

          * 私钥和公钥同时为空时生成一对新的私钥和公钥
          * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做签名或验证 * diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/fpe/FPE.java b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/FPE.java similarity index 98% rename from hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/fpe/FPE.java rename to hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/FPE.java index 377f1cb92..e1902fb9f 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/fpe/FPE.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/FPE.java @@ -1,8 +1,7 @@ -package cn.hutool.crypto.symmetric.fpe; +package cn.hutool.crypto.symmetric; import cn.hutool.crypto.KeyUtil; import cn.hutool.crypto.Padding; -import cn.hutool.crypto.symmetric.AES; import org.bouncycastle.crypto.AlphabetMapper; import org.bouncycastle.jcajce.spec.FPEParameterSpec; @@ -24,7 +23,7 @@ import java.io.Serializable; *

        • 数据类型不变,加密前是数字类型,加密后仍然是数字类型
        • *
        • 加密过程可逆,加密后的数据可以通过密钥解密还原原始数据
        • *
        - * + *

        * 此类基于BouncyCastle实现。 * * @author looly diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/fpe/FPETest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/fpe/FPETest.java index 6bfbb71c0..cc68a1408 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/fpe/FPETest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/fpe/FPETest.java @@ -1,6 +1,7 @@ package cn.hutool.crypto.symmetric.fpe; import cn.hutool.core.util.RandomUtil; +import cn.hutool.crypto.symmetric.FPE; import org.bouncycastle.crypto.util.BasicAlphabetMapper; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java index 87056c748..359bc153e 100755 --- a/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java +++ b/hutool-db/src/main/java/cn/hutool/db/AbstractDb.java @@ -1,23 +1,10 @@ package cn.hutool.db; -import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.func.SerFunction; import cn.hutool.db.dialect.Dialect; -import cn.hutool.db.handler.BeanListHandler; -import cn.hutool.db.handler.EntityHandler; -import cn.hutool.db.handler.EntityListHandler; -import cn.hutool.db.handler.NumberHandler; -import cn.hutool.db.handler.ResultSetUtil; -import cn.hutool.db.handler.RsHandler; -import cn.hutool.db.handler.StringHandler; -import cn.hutool.db.sql.Condition; +import cn.hutool.db.handler.*; +import cn.hutool.db.sql.*; import cn.hutool.db.sql.Condition.LikeType; -import cn.hutool.db.sql.LogicalOperator; -import cn.hutool.db.sql.Query; -import cn.hutool.db.sql.SqlBuilder; -import cn.hutool.db.sql.SqlExecutor; -import cn.hutool.db.sql.SqlUtil; -import cn.hutool.db.sql.QuoteWrapper; import javax.sql.DataSource; import java.io.Serializable; diff --git a/hutool-db/src/main/java/cn/hutool/db/ds/pooled/PooledDataSource.java b/hutool-db/src/main/java/cn/hutool/db/ds/pooled/PooledDataSource.java index 85693af1b..74bb2d18d 100644 --- a/hutool-db/src/main/java/cn/hutool/db/ds/pooled/PooledDataSource.java +++ b/hutool-db/src/main/java/cn/hutool/db/ds/pooled/PooledDataSource.java @@ -29,7 +29,7 @@ public class PooledDataSource extends AbstractDataSource { * 获得一个数据源 * * @param group 数据源分组 - * @return {@link PooledDataSource} + * @return {@code PooledDataSource} */ synchronized public static PooledDataSource getDataSource(final String group) { return new PooledDataSource(group); @@ -38,7 +38,7 @@ public class PooledDataSource extends AbstractDataSource { /** * 获得一个数据源,使用空分组 * - * @return {@link PooledDataSource} + * @return {@code PooledDataSource} */ synchronized public static PooledDataSource getDataSource() { return new PooledDataSource(); diff --git a/hutool-db/src/main/java/cn/hutool/db/handler/RsHandler.java b/hutool-db/src/main/java/cn/hutool/db/handler/RsHandler.java index fa907241d..c9f221ef4 100644 --- a/hutool-db/src/main/java/cn/hutool/db/handler/RsHandler.java +++ b/hutool-db/src/main/java/cn/hutool/db/handler/RsHandler.java @@ -7,7 +7,7 @@ import java.sql.SQLException; /** * 结果集处理接口
        * 此接口用于实现{@link ResultSet} 转换或映射为用户指定的pojo对象 - * + *

        * 默认实现有: * @see EntityHandler * @see EntityListHandler @@ -15,13 +15,13 @@ import java.sql.SQLException; * @see EntitySetHandler * @see NumberHandler * @see PageResultHandler - * + * * @author Luxiaolei * */ @FunctionalInterface public interface RsHandler extends Serializable{ - + /** * 处理结果集
        * 结果集处理后不需要关闭 diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/JdbcType.java b/hutool-db/src/main/java/cn/hutool/db/meta/JdbcType.java index cee36bc26..d0507f210 100644 --- a/hutool-db/src/main/java/cn/hutool/db/meta/JdbcType.java +++ b/hutool-db/src/main/java/cn/hutool/db/meta/JdbcType.java @@ -10,64 +10,177 @@ import java.util.Map; * @see java.sql.Types */ public enum JdbcType { - ARRAY(java.sql.Types.ARRAY), // - BIT(java.sql.Types.BIT), // - TINYINT(java.sql.Types.TINYINT), // - SMALLINT(java.sql.Types.SMALLINT), // - INTEGER(java.sql.Types.INTEGER), // - BIGINT(java.sql.Types.BIGINT), // - FLOAT(java.sql.Types.FLOAT), // - REAL(java.sql.Types.REAL), // - DOUBLE(java.sql.Types.DOUBLE), // - NUMERIC(java.sql.Types.NUMERIC), // - DECIMAL(java.sql.Types.DECIMAL), // - CHAR(java.sql.Types.CHAR), // - VARCHAR(java.sql.Types.VARCHAR), // - LONGVARCHAR(java.sql.Types.LONGVARCHAR), // - DATE(java.sql.Types.DATE), // - TIME(java.sql.Types.TIME), // - TIMESTAMP(java.sql.Types.TIMESTAMP), // - BINARY(java.sql.Types.BINARY), // - VARBINARY(java.sql.Types.VARBINARY), // - LONGVARBINARY(java.sql.Types.LONGVARBINARY), // - NULL(java.sql.Types.NULL), // - OTHER(java.sql.Types.OTHER), // - BLOB(java.sql.Types.BLOB), // - CLOB(java.sql.Types.CLOB), // - BOOLEAN(java.sql.Types.BOOLEAN), // - CURSOR(-10), // Oracle - UNDEFINED(Integer.MIN_VALUE + 1000), // - NVARCHAR(java.sql.Types.NVARCHAR), // JDK6 - NCHAR(java.sql.Types.NCHAR), // JDK6 - NCLOB(java.sql.Types.NCLOB), // JDK6 - STRUCT(java.sql.Types.STRUCT), // - JAVA_OBJECT(java.sql.Types.JAVA_OBJECT), // - DISTINCT(java.sql.Types.DISTINCT), // - REF(java.sql.Types.REF), // - DATALINK(java.sql.Types.DATALINK), // - ROWID(java.sql.Types.ROWID), // JDK6 - LONGNVARCHAR(java.sql.Types.LONGNVARCHAR), // JDK6 - SQLXML(java.sql.Types.SQLXML), // JDK6 - DATETIMEOFFSET(-155), // SQL Server 2008 - TIME_WITH_TIMEZONE(2013), // JDBC 4.2 JDK8 - TIMESTAMP_WITH_TIMEZONE(2014); // JDBC 4.2 JDK8 - - public final int typeCode; - /** - * 构造 - * - * @param code {@link java.sql.Types} 中对应的值 + * {@link java.sql.Types#ARRAY} */ - JdbcType(final int code) { - this.typeCode = code; - } + ARRAY(java.sql.Types.ARRAY), // + /** + * {@link java.sql.Types#BIT} + */ + BIT(java.sql.Types.BIT), // + /** + * {@link java.sql.Types#TINYINT} + */ + TINYINT(java.sql.Types.TINYINT), // + /** + * {@link java.sql.Types#SMALLINT} + */ + SMALLINT(java.sql.Types.SMALLINT), // + /** + * {@link java.sql.Types#INTEGER} + */ + INTEGER(java.sql.Types.INTEGER), // + /** + * {@link java.sql.Types#BIGINT} + */ + BIGINT(java.sql.Types.BIGINT), // + /** + * {@link java.sql.Types#FLOAT} + */ + FLOAT(java.sql.Types.FLOAT), // + /** + * {@link java.sql.Types#REAL} + */ + REAL(java.sql.Types.REAL), // + /** + * {@link java.sql.Types#DOUBLE} + */ + DOUBLE(java.sql.Types.DOUBLE), // + /** + * {@link java.sql.Types#NUMERIC} + */ + NUMERIC(java.sql.Types.NUMERIC), // + /** + * {@link java.sql.Types#DECIMAL} + */ + DECIMAL(java.sql.Types.DECIMAL), // + /** + * {@link java.sql.Types#CHAR} + */ + CHAR(java.sql.Types.CHAR), // + /** + * {@link java.sql.Types#VARCHAR} + */ + VARCHAR(java.sql.Types.VARCHAR), // + /** + * {@link java.sql.Types#LONGVARCHAR} + */ + LONGVARCHAR(java.sql.Types.LONGVARCHAR), // + /** + * {@link java.sql.Types#DATE} + */ + DATE(java.sql.Types.DATE), // + /** + * {@link java.sql.Types#TIME} + */ + TIME(java.sql.Types.TIME), // + /** + * {@link java.sql.Types#TIMESTAMP} + */ + TIMESTAMP(java.sql.Types.TIMESTAMP), // + /** + * {@link java.sql.Types#BINARY} + */ + BINARY(java.sql.Types.BINARY), // + /** + * {@link java.sql.Types#VARBINARY} + */ + VARBINARY(java.sql.Types.VARBINARY), // + /** + * {@link java.sql.Types#LONGVARBINARY} + */ + LONGVARBINARY(java.sql.Types.LONGVARBINARY), // + /** + * {@link java.sql.Types#NULL} + */ + NULL(java.sql.Types.NULL), // + /** + * {@link java.sql.Types#OTHER} + */ + OTHER(java.sql.Types.OTHER), // + /** + * {@link java.sql.Types#BLOB} + */ + BLOB(java.sql.Types.BLOB), // + /** + * {@link java.sql.Types#CLOB} + */ + CLOB(java.sql.Types.CLOB), // + /** + * {@link java.sql.Types#BOOLEAN} + */ + BOOLEAN(java.sql.Types.BOOLEAN), // + /** + * Oracle Cursor + */ + CURSOR(-10), // Oracle + /** + * UNDEFINED + */ + UNDEFINED(Integer.MIN_VALUE + 1000), // + /** + * {@link java.sql.Types#NVARCHAR} + */ + NVARCHAR(java.sql.Types.NVARCHAR), // JDK6 + /** + * {@link java.sql.Types#NCHAR} + */ + NCHAR(java.sql.Types.NCHAR), // JDK6 + /** + * {@link java.sql.Types#NCLOB} + */ + NCLOB(java.sql.Types.NCLOB), // JDK6 + /** + * {@link java.sql.Types#STRUCT} + */ + STRUCT(java.sql.Types.STRUCT), + /** + * {@link java.sql.Types#JAVA_OBJECT} + */ + JAVA_OBJECT(java.sql.Types.JAVA_OBJECT), + /** + * {@link java.sql.Types#DISTINCT} + */ + DISTINCT(java.sql.Types.DISTINCT), + /** + * {@link java.sql.Types#REF} + */ + REF(java.sql.Types.REF), + /** + * {@link java.sql.Types#BOOLEAN} + */ + DATALINK(java.sql.Types.DATALINK), // + /** + * {@link java.sql.Types#ROWID} + */ + ROWID(java.sql.Types.ROWID), // JDK6 + /** + * {@link java.sql.Types#LONGNVARCHAR} + */ + LONGNVARCHAR(java.sql.Types.LONGNVARCHAR), // JDK6 + /** + * {@link java.sql.Types#SQLXML} + */ + SQLXML(java.sql.Types.SQLXML), // JDK6 + /** + * SQL Server 2008 DateTimeOffset + */ + DATETIMEOFFSET(-155), // SQL Server 2008 + /** + * Time With TimeZone + */ + TIME_WITH_TIMEZONE(2013), // JDBC 4.2 JDK8 + /** + * TimeStamp With TimeZone + */ + TIMESTAMP_WITH_TIMEZONE(2014); // JDBC 4.2 JDK8 // 此处无写操作,使用HashMap没有线程安全问题 private static final Map CODE_MAP = new HashMap<>(128, 1); + static { for (final JdbcType type : JdbcType.values()) { - CODE_MAP.put(type.typeCode, type); + CODE_MAP.put(type.value, type); } } @@ -81,4 +194,23 @@ public enum JdbcType { return CODE_MAP.get(code); } + private final int value; + + /** + * 构造 + * + * @param code {@link java.sql.Types} 中对应的值 + */ + JdbcType(final int code) { + this.value = code; + } + + /** + * 获取枚举值,即JDBC字段类型代码 + * + * @return 字段类型代码 + */ + public int getValue() { + return this.value; + } } diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java b/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java index 3db44b795..a530be47d 100644 --- a/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java +++ b/hutool-db/src/main/java/cn/hutool/db/meta/ResultColumn.java @@ -67,97 +67,215 @@ public class ResultColumn { } } + /** + * 是否自增 + * + * @return 是否自增 + */ public boolean isAutoIncrement() { return autoIncrement; } + /** + * 是否大小写敏感 + * + * @return 是否大小写敏感 + */ public boolean isCaseSensitive() { return caseSensitive; } + /** + * 是否可搜索 + * + * @return 是否可搜索 + */ public boolean isSearchable() { return searchable; } + /** + * 是否为货币 + * + * @return 是否为货币 + */ public boolean isCurrency() { return currency; } + /** + * 获取null值选项,即是否可以为{@code null} + * + * @return null值选项,是否可以为{@code null} + */ public int getNullable() { return nullable; } + /** + * 获取列null值选项枚举,即是否可以为{@code null} + * + * @return 列null值选项枚举,即是否可以为{@code null} + */ public ColumnNullable getNullableEnum() { return ColumnNullable.of(getNullable()); } + /** + * 是否为带正负号的数字 + * + * @return 是否为带正负号的数字 + */ public boolean isSigned() { return signed; } + /** + * 获取正常最大宽度(以字符数计) + * + * @return 正常最大宽度 + */ public int getDisplaySize() { return displaySize; } + /** + * 获取列标签 + * + * @return 标签 + */ public String getLabel() { return label; } + /** + * 获取列名称 + * + * @return 列名称 + */ public String getName() { return name; } + /** + * 获取表架构名称 + * + * @return 表架构名称 + */ public String getSchemaName() { return schemaName; } + /** + * 获取小数位数 + * + * @return 小数位数 + */ public int getPrecision() { return precision; } + /** + * 小数点右侧的位数 + * + * @return 小数点右侧的位数 + */ public int getScale() { return scale; } + /** + * 获取表名 + * + * @return 表名 + */ public String getTableName() { return tableName; } + /** + * 获取表的目录名称 + * + * @return 表的目录名称 + */ public String getCatalogName() { return catalogName; } + /** + * 获取SQL类型 + * + * @return SQL类型 + */ public int getType() { return type; } + /** + * 获取类型名称 + * + * @return 类型名称 + */ public String getTypeName() { return typeName; } + /** + * 是否只读(不可写入) + * + * @return 是否只读(不可写入) + */ public boolean isReadOnly() { return readOnly; } + /** + * 是否能够成功在指定列上写入 + * + * @return 是否能够成功在指定列上写入 + */ public boolean isWritable() { return writable; } + /** + * 写入操作是否将一定成功 + * + * @return 写入操作是否将一定成功 + */ public boolean isDefinitelyWritable() { return definitelyWritable; } + /** + * 如果调用getObject方法来从列中检索值,则返回生成其实例的 Java 类的完全限定名称 + * + * @return 包含类的完全限定名称 + */ public String getClassName() { return className; } + /** + * 列null值选项 + */ public enum ColumnNullable { + /** + * 列不允许有null + */ NO_NULLS(ResultSetMetaData.columnNoNulls), + /** + * 列允许有null + */ NULLABLE(ResultSetMetaData.columnNullable), + /** + * 未知 + */ UNKNOWN(ResultSetMetaData.columnNullableUnknown); /** * ResultSetMetaData中的int值转枚举 + * * @param nullable nullable值 * @return ColumnNullable */ @@ -173,8 +291,18 @@ public class ResultColumn { } final int value; + ColumnNullable(final int value) { this.value = value; } + + /** + * 获取枚举值,即列null值选项代码 + * + * @return 列null值选项代码 + */ + public int getValue() { + return this.value; + } } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/aop/ProxyUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/aop/ProxyUtil.java index 90123a7e3..667b5a8ac 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/aop/ProxyUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/aop/ProxyUtil.java @@ -47,7 +47,7 @@ public final class ProxyUtil { * 3、调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法
        * 4、将$Proxy0的实例返回给客户端。
        * 5、当调用代理类的相应方法时,相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法 - * + *

        * * @param 被代理对象类型 * @param classloader 被代理类对应的ClassLoader diff --git a/hutool-extra/src/main/java/cn/hutool/extra/management/JavaInfo.java b/hutool-extra/src/main/java/cn/hutool/extra/management/JavaInfo.java index 63a392943..a7fcd2eed 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/management/JavaInfo.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/management/JavaInfo.java @@ -305,7 +305,7 @@ public class JavaInfo implements Serializable { * *

        * 例如: - * + *

        * *

          *
        • 测试JDK 1.2:{@code isJavaVersionAtLeast(1.2f)}
        • @@ -324,7 +324,7 @@ public class JavaInfo implements Serializable { * *

          * 例如: - * + *

          * *

            *
          • 测试JDK 1.2:{@code isJavaVersionAtLeast(120)}
          • diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrAsciiArt.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrAsciiArt.java index 6dd6c0ac0..b5f043c24 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrAsciiArt.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrAsciiArt.java @@ -25,6 +25,7 @@ public class QrAsciiArt { this.qrConfig = qrConfig; } + @SuppressWarnings("UnnecessaryUnicodeEscape") @Override public String toString() { final int width = matrix.getWidth(); diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java index 2fe5f828e..357a00b2b 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient4/HttpClient4Engine.java @@ -23,13 +23,9 @@ import org.apache.http.message.BasicHeader; import java.io.IOException; import java.net.URI; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; /** * Apache HttpClient5的HTTP请求引擎 diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index 52502214c..9ab0d8609 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -2,7 +2,6 @@ package cn.hutool.http.client.engine.httpclient5; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.net.ssl.SSLUtil; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.http.GlobalHeaders; import cn.hutool.http.HttpException; diff --git a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java index d45bbeae1..7fd15063c 100644 --- a/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java +++ b/hutool-http/src/main/java/cn/hutool/http/ssl/CustomProtocolsSSLFactory.java @@ -1,7 +1,5 @@ package cn.hutool.http.ssl; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.net.ssl.SSLUtil; import cn.hutool.core.util.ArrayUtil; import javax.net.ssl.SSLSocket; diff --git a/hutool-http/src/test/java/cn/hutool/http/ContentTypeTest.java b/hutool-http/src/test/java/cn/hutool/http/ContentTypeTest.java index de3834ab4..f369296e6 100644 --- a/hutool-http/src/test/java/cn/hutool/http/ContentTypeTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/ContentTypeTest.java @@ -7,7 +7,7 @@ import org.junit.Test; /** * ContentType 单元测试 - * + *

            * */ public class ContentTypeTest { diff --git a/hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java b/hutool-http/src/test/java/cn/hutool/http/client/body/MultipartBodyTest.java similarity index 90% rename from hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java rename to hutool-http/src/test/java/cn/hutool/http/client/body/MultipartBodyTest.java index 86270de53..5fd810889 100644 --- a/hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/client/body/MultipartBodyTest.java @@ -1,9 +1,8 @@ -package cn.hutool.http.body; +package cn.hutool.http.client.body; +import cn.hutool.core.io.resource.HttpResource; import cn.hutool.core.io.resource.StringResource; import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.io.resource.HttpResource; -import cn.hutool.http.client.body.MultipartBody; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index 26da40e64..71a5b2693 100755 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -460,6 +460,7 @@ public final class InternalJSONUtil { * @param c 字符 * @return 转义后的字符串 */ + @SuppressWarnings("UnnecessaryUnicodeEscape") private static String escape(final char c) { switch (c) { case '\b': diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue1200Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue1200Test.java index 466c4a839..b3fa0e8dc 100644 --- a/hutool-json/src/test/java/cn/hutool/json/Issue1200Test.java +++ b/hutool-json/src/test/java/cn/hutool/json/Issue1200Test.java @@ -10,7 +10,7 @@ import org.junit.Test; * 测试在bean转换时使用BeanConverter,默认忽略转换失败的字段。 * 现阶段Converter的问题在于,无法更细粒度的控制转换失败的范围,例如Bean的一个字段为List, * list任意一个item转换失败都会导致这个list为null。 - * + *

            * TODO 需要在Converter中添加ConvertOption,用于更细粒度的控制转换规则 */ public class Issue1200Test { diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java b/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2Test.java similarity index 96% rename from hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java rename to hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2Test.java index c1aa1e08c..7e09aedd5 100644 --- a/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2.java +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI1F8M2Test.java @@ -9,7 +9,7 @@ import java.time.LocalDateTime; /** * https://gitee.com/loolly/dashboard/issues?id=I1F8M2 */ -public class IssueI1F8M2 { +public class IssueI1F8M2Test { @Test public void toBeanTest() { final String jsonStr = "{\"eventType\":\"fee\",\"fwdAlertingTime\":\"2020-04-22 16:34:13\",\"fwdAnswerTime\":\"\"}"; diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI1H2VN.java b/hutool-json/src/test/java/cn/hutool/json/IssueI1H2VNTest.java similarity index 97% rename from hutool-json/src/test/java/cn/hutool/json/IssueI1H2VN.java rename to hutool-json/src/test/java/cn/hutool/json/IssueI1H2VNTest.java index aeea875a0..423bab1e2 100644 --- a/hutool-json/src/test/java/cn/hutool/json/IssueI1H2VN.java +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI1H2VNTest.java @@ -11,7 +11,7 @@ import java.util.List; * 此问题原来出在BeanCopier中,判断循环引用使用了equals,并不严谨。 * 修复后使用==判断循环引用。 */ -public class IssueI1H2VN { +public class IssueI1H2VNTest { @Test public void toBeanTest() { diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI3BS4S.java b/hutool-json/src/test/java/cn/hutool/json/IssueI3BS4STest.java similarity index 94% rename from hutool-json/src/test/java/cn/hutool/json/IssueI3BS4S.java rename to hutool-json/src/test/java/cn/hutool/json/IssueI3BS4STest.java index d7927a4ec..da320e45f 100644 --- a/hutool-json/src/test/java/cn/hutool/json/IssueI3BS4S.java +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI3BS4STest.java @@ -10,7 +10,7 @@ import java.time.LocalDateTime; /** * 测试带毫秒的日期转换 */ -public class IssueI3BS4S { +public class IssueI3BS4STest { @Test public void toBeanTest(){ diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java b/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJPTest.java similarity index 94% rename from hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java rename to hutool-json/src/test/java/cn/hutool/json/IssueI3EGJPTest.java index 7c61f8a30..9d65c78af 100644 --- a/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJPTest.java @@ -5,7 +5,7 @@ import lombok.Data; import org.junit.Assert; import org.junit.Test; -public class IssueI3EGJP { +public class IssueI3EGJPTest { @Test public void hutoolMapToBean() { diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index 6ad70ddb2..e87bda2b1 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -2,7 +2,6 @@ package cn.hutool.json; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import cn.hutool.core.math.NumberUtil; import cn.hutool.json.serialize.JSONStringer; @@ -14,11 +13,7 @@ import org.junit.Assert; import org.junit.Test; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; public class JSONUtilTest { diff --git a/hutool-json/src/test/java/cn/hutool/json/writer/GlobalValueWriterMappingTest.java b/hutool-json/src/test/java/cn/hutool/json/writer/GlobalValueWriterMappingTest.java index 2243a32f5..bccee300e 100644 --- a/hutool-json/src/test/java/cn/hutool/json/writer/GlobalValueWriterMappingTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/writer/GlobalValueWriterMappingTest.java @@ -12,9 +12,8 @@ public class GlobalValueWriterMappingTest { @Before public void init(){ - GlobalValueWriterMapping.put(CustomSubBean.class, (JSONValueWriter) (writer, value) -> { - writer.writeRaw(String.valueOf(value.getId())); - }); + GlobalValueWriterMapping.put(CustomSubBean.class, + (JSONValueWriter) (writer, value) -> writer.writeRaw(String.valueOf(value.getId()))); } @Test diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog.java b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog.java index 18e1eea24..d55915eca 100644 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog.java @@ -9,8 +9,8 @@ import cn.hutool.log.level.Level; /** * Apache Commons Logging - * @author Looly * + * @author Looly */ public class ApacheCommonsLog extends AbstractLog { private static final long serialVersionUID = -6843151523380063975L; @@ -19,15 +19,32 @@ public class ApacheCommonsLog extends AbstractLog { private final String name; // ------------------------------------------------------------------------- Constructor + + /** + * 构造 + * + * @param logger Logger + * @param name 名称 + */ public ApacheCommonsLog(final Log logger, final String name) { this.logger = logger; this.name = name; } + /** + * 构造 + * + * @param clazz 类 + */ public ApacheCommonsLog(final Class clazz) { this(LogFactory.getLog(clazz), null == clazz ? StrUtil.NULL : clazz.getName()); } + /** + * 构造 + * + * @param name 名称 + */ public ApacheCommonsLog(final String name) { this(LogFactory.getLog(name), name); } @@ -46,7 +63,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void trace(final String fqcn, final Throwable t, final String format, final Object... arguments) { // fqcn此处无效 - if(isTraceEnabled()){ + if (isTraceEnabled()) { logger.trace(StrUtil.format(format, arguments), t); } } @@ -60,7 +77,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void debug(final String fqcn, final Throwable t, final String format, final Object... arguments) { // fqcn此处无效 - if(isDebugEnabled()){ + if (isDebugEnabled()) { logger.debug(StrUtil.format(format, arguments), t); } } @@ -74,7 +91,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void info(final String fqcn, final Throwable t, final String format, final Object... arguments) { // fqcn此处无效 - if(isInfoEnabled()){ + if (isInfoEnabled()) { logger.info(StrUtil.format(format, arguments), t); } } @@ -87,7 +104,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void warn(final String format, final Object... arguments) { - if(isWarnEnabled()){ + if (isWarnEnabled()) { logger.warn(StrUtil.format(format, arguments)); } } @@ -99,7 +116,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void warn(final String fqcn, final Throwable t, final String format, final Object... arguments) { // fqcn此处无效 - if(isWarnEnabled()){ + if (isWarnEnabled()) { logger.warn(StrUtil.format(format, arguments), t); } } @@ -113,7 +130,7 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void error(final String fqcn, final Throwable t, final String format, final Object... arguments) { // fqcn此处无效 - if(isErrorEnabled()){ + if (isErrorEnabled()) { logger.warn(StrUtil.format(format, arguments), t); } @@ -123,23 +140,23 @@ public class ApacheCommonsLog extends AbstractLog { @Override public void log(final String fqcn, final Level level, final Throwable t, final String format, final Object... arguments) { switch (level) { - case TRACE: - trace(t, format, arguments); - break; - case DEBUG: - debug(t, format, arguments); - break; - case INFO: - info(t, format, arguments); - break; - case WARN: - warn(t, format, arguments); - break; - case ERROR: - error(t, format, arguments); - break; - default: - throw new Error(StrUtil.format("Can not identify level: {}", level)); + case TRACE: + trace(t, format, arguments); + break; + case DEBUG: + debug(t, format, arguments); + break; + case INFO: + info(t, format, arguments); + break; + case WARN: + warn(t, format, arguments); + break; + case ERROR: + error(t, format, arguments); + break; + default: + throw new Error(StrUtil.format("Can not identify level: {}", level)); } } // ------------------------------------------------------------------------- Private method diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog4JLog.java b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog4JLog.java index 5307cff2f..8973bb270 100644 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog4JLog.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLog4JLog.java @@ -7,21 +7,37 @@ import cn.hutool.log.dialect.log4j.Log4jLog; /** * Apache Commons Logging for Log4j - * @author Looly * + * @author Looly */ public class ApacheCommonsLog4JLog extends Log4jLog { private static final long serialVersionUID = -6843151523380063975L; // ------------------------------------------------------------------------- Constructor + + /** + * 构造 + * + * @param logger Logger + */ public ApacheCommonsLog4JLog(final Log logger) { super(((Log4JLogger) logger).getLogger()); } + /** + * 构造 + * + * @param clazz 类 + */ public ApacheCommonsLog4JLog(final Class clazz) { super(clazz); } + /** + * 构造 + * + * @param name 名称 + */ public ApacheCommonsLog4JLog(final String name) { super(name); } diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLogFactory.java b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLogFactory.java index b589f0374..3ad3ff866 100644 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLogFactory.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/commons/ApacheCommonsLogFactory.java @@ -10,6 +10,9 @@ import cn.hutool.log.LogFactory; */ public class ApacheCommonsLogFactory extends LogFactory{ + /** + * 构造 + */ public ApacheCommonsLogFactory() { super("Apache Common Logging"); checkLogExist(org.apache.commons.logging.LogFactory.class); diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java index 567821f8c..af5ed1b71 100755 --- a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java +++ b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java @@ -14,12 +14,13 @@ import org.tinylog.provider.ProviderRegistry; * tinylog log.
            * * @author Looly - * */ public class TinyLog2 extends AbstractLog { private static final long serialVersionUID = 1L; - /** 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 */ + /** + * 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 + */ private static final int DEPTH = 5; private final int level; @@ -31,10 +32,21 @@ public class TinyLog2 extends AbstractLog { Configuration.getLocale(), Configuration.isEscapingEnabled() ); + + /** + * 构造 + * + * @param clazz class + */ public TinyLog2(final Class clazz) { this(null == clazz ? StrUtil.NULL : clazz.getName()); } + /** + * 构造 + * + * @param name 名称 + */ public TinyLog2(final String name) { this.name = name; this.level = provider.getMinimumLevel().ordinal(); @@ -66,6 +78,7 @@ public class TinyLog2 extends AbstractLog { public void debug(final String fqcn, final Throwable t, final String format, final Object... arguments) { logIfEnabled(fqcn, Level.DEBUG, t, format, arguments); } + // ------------------------------------------------------------------------- Info @Override public boolean isInfoEnabled() { @@ -112,15 +125,17 @@ public class TinyLog2 extends AbstractLog { /** * 在对应日志级别打开情况下打印日志 - * @param fqcn 完全限定类名(Fully Qualified Class Name),用于定位日志位置 - * @param level 日志级别 - * @param t 异常,null则检查最后一个参数是否为Throwable类型,是则取之,否则不打印堆栈 - * @param format 日志消息模板 + * + * @param fqcn 完全限定类名(Fully Qualified Class Name),用于定位日志位置 + * @param level 日志级别 + * @param t 异常,null则检查最后一个参数是否为Throwable类型,是则取之,否则不打印堆栈 + * @param format 日志消息模板 * @param arguments 日志消息参数 */ + @SuppressWarnings("unused") private void logIfEnabled(final String fqcn, final Level level, Throwable t, final String format, final Object... arguments) { // fqcn 无效 - if(null == t){ + if (null == t) { t = getLastArgumentIfThrowable(arguments); } provider.log(DEPTH, null, level, t, formatter, StrUtil.toString(format), arguments); @@ -136,26 +151,26 @@ public class TinyLog2 extends AbstractLog { private Level toTinyLevel(final cn.hutool.log.level.Level level) { final Level tinyLevel; switch (level) { - case TRACE: - tinyLevel = Level.TRACE; - break; - case DEBUG: - tinyLevel = Level.DEBUG; - break; - case INFO: - tinyLevel = Level.INFO; - break; - case WARN: - tinyLevel = Level.WARN; - break; - case ERROR: - tinyLevel = Level.ERROR; - break; - case OFF: - tinyLevel = Level.OFF; - break; - default: - throw new Error(StrUtil.format("Can not identify level: {}", level)); + case TRACE: + tinyLevel = Level.TRACE; + break; + case DEBUG: + tinyLevel = Level.DEBUG; + break; + case INFO: + tinyLevel = Level.INFO; + break; + case WARN: + tinyLevel = Level.WARN; + break; + case ERROR: + tinyLevel = Level.ERROR; + break; + case OFF: + tinyLevel = Level.OFF; + break; + default: + throw new Error(StrUtil.format("Can not identify level: {}", level)); } return tinyLevel; } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/style/Align.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/style/Align.java index 4ecf2dc90..0da6021a0 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/style/Align.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/style/Align.java @@ -2,10 +2,21 @@ package cn.hutool.poi.excel.style; /** * 对齐方式枚举 - * + * * @author looly * @since 4.1.0 */ public enum Align { - LEFT, RIGHT, CENTER + /** + * 左对齐 + */ + LEFT, + /** + * 右对齐 + */ + RIGHT, + /** + * 居中 + */ + CENTER } diff --git a/hutool-socket/src/main/java/cn/hutool/socket/protocol/MsgDecoder.java b/hutool-socket/src/main/java/cn/hutool/socket/protocol/MsgDecoder.java index 828418714..fb2ec3a0c 100644 --- a/hutool-socket/src/main/java/cn/hutool/socket/protocol/MsgDecoder.java +++ b/hutool-socket/src/main/java/cn/hutool/socket/protocol/MsgDecoder.java @@ -6,7 +6,7 @@ import cn.hutool.socket.aio.AioSession; /** * 消息解码器 - * + * * @author looly * * @param 解码后的目标类型 @@ -14,7 +14,7 @@ import cn.hutool.socket.aio.AioSession; public interface MsgDecoder { /** * 对于从Socket流中获取到的数据采用当前MsgDecoder的实现类协议进行解析。 - * + *

            * * @param session 本次需要解码的session * @param readBuffer 待处理的读buffer diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ScaleType.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ScaleType.java index 1d6881a65..f7f5ad023 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/ScaleType.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ScaleType.java @@ -31,6 +31,7 @@ public enum ScaleType { */ AREA_AVERAGING(Image.SCALE_AREA_AVERAGING); + private final int value; /** * 构造 * @@ -45,8 +46,6 @@ public enum ScaleType { this.value = value; } - private final int value; - /** * 获取值 * diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi4bitMapping.java b/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi4bitMapping.java index cd228fafd..bc343c373 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi4bitMapping.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi4bitMapping.java @@ -10,8 +10,15 @@ import java.util.LinkedHashMap; * @author Tom Xin */ public class Ansi4bitMapping extends AnsiLabMapping { + + /** + * 单例 + */ public static final Ansi4bitMapping INSTANCE = new Ansi4bitMapping(); + /** + * 构造 + */ public Ansi4bitMapping() { ansiLabMap = new LinkedHashMap<>(16, 1); ansiLabMap.put(Ansi4BitColor.BLACK, new LabColor(0x000000)); diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi8bitMapping.java b/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi8bitMapping.java index e380138ff..710d764f6 100644 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi8bitMapping.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/color/Ansi8bitMapping.java @@ -38,8 +38,14 @@ public class Ansi8bitMapping extends AnsiLabMapping { 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee }; + /** + * 单例 + */ public static final Ansi8bitMapping INSTANCE = new Ansi8bitMapping(); + /** + * 构造 + */ public Ansi8bitMapping() { ansiLabMap = new LinkedHashMap<>(256, 1); for (int i = 0; i < ANSI_8BIT_COLOR_CODE_LOOKUP.length; i++) { From 9ab3397a2f69334f17e54d61764e740468505e38 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 11:15:47 +0800 Subject: [PATCH 114/125] fix code --- .../cn/hutool/core/codec/hash/CityHash.java | 117 ++++++++---------- .../cn/hutool/core/codec/hash/MurmurHash.java | 3 + .../codec/hash/metro/AbstractMetroHash.java | 30 +++-- .../core/codec/hash/metro/MetroHash.java | 7 +- .../core/codec/hash/metro/MetroHash128.java | 90 ++++++-------- .../core/codec/hash/metro/MetroHash64.java | 58 ++++----- .../hash/metro/MetroHashInternalUtil.java | 51 -------- .../java/cn/hutool/core/math/NumberUtil.java | 1 - .../java/cn/hutool/core/tree/BeanTree.java | 15 ++- .../codec/hash/metro/MetroHash128Test.java | 4 +- .../cn/hutool/core/util/NumberUtilTest.java | 12 +- 11 files changed, 163 insertions(+), 225 deletions(-) delete mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/CityHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/CityHash.java index bd34700c4..cebc5f715 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/CityHash.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/CityHash.java @@ -17,6 +17,9 @@ import java.util.Arrays; * @since 5.2.5 */ public class CityHash implements Hash32, Hash64, Hash128{ + /** + * 单例 + */ public static CityHash INSTANCE = new CityHash(); // Some primes between 2^63 and 2^64 for various uses. @@ -50,46 +53,46 @@ public class CityHash implements Hash32, Hash64, Hash128 // len > 24 int h = len, g = c1 * len, f = g; - int a0 = rotate32(fetch32(data, len - 4) * c1, 17) * c2; - int a1 = rotate32(fetch32(data, len - 8) * c1, 17) * c2; - int a2 = rotate32(fetch32(data, len - 16) * c1, 17) * c2; - int a3 = rotate32(fetch32(data, len - 12) * c1, 17) * c2; - int a4 = rotate32(fetch32(data, len - 20) * c1, 17) * c2; + int a0 = Integer.rotateRight(fetch32(data, len - 4) * c1, 17) * c2; + int a1 = Integer.rotateRight(fetch32(data, len - 8) * c1, 17) * c2; + int a2 = Integer.rotateRight(fetch32(data, len - 16) * c1, 17) * c2; + int a3 = Integer.rotateRight(fetch32(data, len - 12) * c1, 17) * c2; + int a4 = Integer.rotateRight(fetch32(data, len - 20) * c1, 17) * c2; h ^= a0; - h = rotate32(h, 19); + h = Integer.rotateRight(h, 19); h = h * 5 + 0xe6546b64; h ^= a2; - h = rotate32(h, 19); + h = Integer.rotateRight(h, 19); h = h * 5 + 0xe6546b64; g ^= a1; - g = rotate32(g, 19); + g = Integer.rotateRight(g, 19); g = g * 5 + 0xe6546b64; g ^= a3; - g = rotate32(g, 19); + g = Integer.rotateRight(g, 19); g = g * 5 + 0xe6546b64; f += a4; - f = rotate32(f, 19); + f = Integer.rotateRight(f, 19); f = f * 5 + 0xe6546b64; int iters = (len - 1) / 20; int pos = 0; do { - a0 = rotate32(fetch32(data, pos) * c1, 17) * c2; + a0 = Integer.rotateRight(fetch32(data, pos) * c1, 17) * c2; a1 = fetch32(data, pos + 4); - a2 = rotate32(fetch32(data, pos + 8) * c1, 17) * c2; - a3 = rotate32(fetch32(data, pos + 12) * c1, 17) * c2; + a2 = Integer.rotateRight(fetch32(data, pos + 8) * c1, 17) * c2; + a3 = Integer.rotateRight(fetch32(data, pos + 12) * c1, 17) * c2; a4 = fetch32(data, pos + 16); h ^= a0; - h = rotate32(h, 18); + h = Integer.rotateRight(h, 18); h = h * 5 + 0xe6546b64; f += a1; - f = rotate32(f, 19); + f = Integer.rotateRight(f, 19); f = f * c1; g += a2; - g = rotate32(g, 18); + g = Integer.rotateRight(g, 18); g = g * 5 + 0xe6546b64; h ^= a3 + a1; - h = rotate32(h, 19); + h = Integer.rotateRight(h, 19); h = h * 5 + 0xe6546b64; g ^= a4; g = Integer.reverseBytes(g) * 5; @@ -104,16 +107,16 @@ public class CityHash implements Hash32, Hash64, Hash128 pos += 20; } while (--iters != 0); - g = rotate32(g, 11) * c1; - g = rotate32(g, 17) * c1; - f = rotate32(f, 11) * c1; - f = rotate32(f, 17) * c1; - h = rotate32(h + g, 19); + g = Integer.rotateRight(g, 11) * c1; + g = Integer.rotateRight(g, 17) * c1; + f = Integer.rotateRight(f, 11) * c1; + f = Integer.rotateRight(f, 17) * c1; + h = Integer.rotateRight(h + g, 19); h = h * 5 + 0xe6546b64; - h = rotate32(h, 17) * c1; - h = rotate32(h + f, 19); + h = Integer.rotateRight(h, 17) * c1; + h = Integer.rotateRight(h + f, 19); h = h * 5 + 0xe6546b64; - h = rotate32(h, 17) * c1; + h = Integer.rotateRight(h, 17) * c1; return h; } @@ -149,11 +152,11 @@ public class CityHash implements Hash32, Hash64, Hash128 len = (len - 1) & ~63; int pos = 0; do { - x = rotate64(x + y + v.getLowValue() + fetch64(data, pos + 8), 37) * k1; - y = rotate64(y + v.getHighValue() + fetch64(data, pos + 48), 42) * k1; + x = Long.rotateRight(x + y + v.getLowValue() + fetch64(data, pos + 8), 37) * k1; + y = Long.rotateRight(y + v.getHighValue() + fetch64(data, pos + 48), 42) * k1; x ^= w.getHighValue(); y += v.getLowValue() + fetch64(data, pos + 40); - z = rotate64(z + w.getLowValue(), 33) * k1; + z = Long.rotateRight(z + w.getLowValue(), 33) * k1; v = weakHashLen32WithSeeds(data, pos, v.getHighValue() * k1, x + w.getLowValue()); w = weakHashLen32WithSeeds(data, pos + 32, z + w.getHighValue(), y + fetch64(data, pos + 16)); // swap z,x value @@ -231,19 +234,19 @@ public class CityHash implements Hash32, Hash64, Hash128 long x = seed.getLowValue(); long y = seed.getHighValue(); long z = len * k1; - v.setLowValue(rotate64(y ^ k1, 49) * k1 + fetch64(byteArray, start)); - v.setHighValue(rotate64(v.getLowValue(), 42) * k1 + fetch64(byteArray, start + 8)); - w.setLowValue(rotate64(y + z, 35) * k1 + x); - w.setHighValue(rotate64(x + fetch64(byteArray, start + 88), 53) * k1); + v.setLowValue(Long.rotateRight(y ^ k1, 49) * k1 + fetch64(byteArray, start)); + v.setHighValue(Long.rotateRight(v.getLowValue(), 42) * k1 + fetch64(byteArray, start + 8)); + w.setLowValue(Long.rotateRight(y + z, 35) * k1 + x); + w.setHighValue(Long.rotateRight(x + fetch64(byteArray, start + 88), 53) * k1); // This is the same inner loop as CityHash64(), manually unrolled. int pos = start; do { - x = rotate64(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1; - y = rotate64(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1; + x = Long.rotateRight(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1; + y = Long.rotateRight(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1; x ^= w.getHighValue(); y += v.getLowValue() + fetch64(byteArray, pos + 40); - z = rotate64(z + w.getLowValue(), 33) * k1; + z = Long.rotateRight(z + w.getLowValue(), 33) * k1; v = weakHashLen32WithSeeds(byteArray, pos, v.getHighValue() * k1, x + w.getLowValue()); w = weakHashLen32WithSeeds(byteArray, pos + 32, z + w.getHighValue(), y + fetch64(byteArray, pos + 16)); @@ -251,11 +254,11 @@ public class CityHash implements Hash32, Hash64, Hash128 x = z; z = swapValue; pos += 64; - x = rotate64(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1; - y = rotate64(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1; + x = Long.rotateRight(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1; + y = Long.rotateRight(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1; x ^= w.getHighValue(); y += v.getLowValue() + fetch64(byteArray, pos + 40); - z = rotate64(z + w.getLowValue(), 33) * k1; + z = Long.rotateRight(z + w.getLowValue(), 33) * k1; v = weakHashLen32WithSeeds(byteArray, pos, v.getHighValue() * k1, x + w.getLowValue()); w = weakHashLen32WithSeeds(byteArray, pos + 32, z + w.getHighValue(), y + fetch64(byteArray, pos + 16)); swapValue = x; @@ -264,16 +267,16 @@ public class CityHash implements Hash32, Hash64, Hash128 pos += 64; len -= 128; } while (len >= 128); - x += rotate64(v.getLowValue() + z, 49) * k0; - y = y * k0 + rotate64(w.getHighValue(), 37); - z = z * k0 + rotate64(w.getLowValue(), 27); + x += Long.rotateRight(v.getLowValue() + z, 49) * k0; + y = y * k0 + Long.rotateRight(w.getHighValue(), 37); + z = z * k0 + Long.rotateRight(w.getLowValue(), 27); w.setLowValue(w.getLowValue() * 9); v.setLowValue(v.getLowValue() * k0); // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. for (int tail_done = 0; tail_done < len; ) { tail_done += 32; - y = rotate64(x + y, 42) * k0 + v.getHighValue(); + y = Long.rotateRight(x + y, 42) * k0 + v.getHighValue(); w.setLowValue(w.getLowValue() + fetch64(byteArray, pos + len - tail_done + 16)); x = x * k0 + w.getLowValue(); z += w.getHighValue() + fetch64(byteArray, pos + len - tail_done); @@ -333,8 +336,8 @@ public class CityHash implements Hash32, Hash64, Hash128 final long mul = k2 + len * 2L; final long a = fetch64(byteArray, 0) + k2; final long b = fetch64(byteArray, len - 8); - final long c = rotate64(b, 37) * mul + a; - final long d = (rotate64(a, 25) + b) * mul; + final long c = Long.rotateRight(b, 37) * mul + a; + final long d = (Long.rotateRight(a, 25) + b) * mul; return hashLen16(c, d, mul); } if (len >= 4) { @@ -361,8 +364,8 @@ public class CityHash implements Hash32, Hash64, Hash128 final long b = fetch64(byteArray, 8); final long c = fetch64(byteArray, len - 8) * mul; final long d = fetch64(byteArray, len - 16) * k2; - return hashLen16(rotate64(a + b, 43) + rotate64(c, 30) + d, - a + rotate64(b + k2, 18) + c, mul); + return hashLen16(Long.rotateRight(a + b, 43) + Long.rotateRight(c, 30) + d, + a + Long.rotateRight(b + k2, 18) + c, mul); } private long hashLen33to64(final byte[] byteArray) { @@ -376,10 +379,10 @@ public class CityHash implements Hash32, Hash64, Hash128 final long f = fetch64(byteArray, 24) * 9; final long g = fetch64(byteArray, len - 8); final long h = fetch64(byteArray, len - 16) * mul; - final long u = rotate64(a + g, 43) + (rotate64(b, 30) + c) * 9; + final long u = Long.rotateRight(a + g, 43) + (Long.rotateRight(b, 30) + c) * 9; final long v = ((a + g) ^ d) + f + 1; final long w = Long.reverseBytes((u + v) * mul) + h; - final long x = rotate64(e + f, 42) + c; + final long x = Long.rotateRight(e + f, 42) + c; final long y = (Long.reverseBytes((v + w) * mul) + g) * mul; final long z = e + f + c; a = Long.reverseBytes((x + z) * mul + y) + b; @@ -395,16 +398,6 @@ public class CityHash implements Hash32, Hash64, Hash128 return ByteUtil.bytesToInt(byteArray, start, ByteUtil.CPU_ENDIAN); } - private static long rotate64(final long val, final int shift) { - // Avoid shifting by 64: doing so yields an undefined result. - return shift == 0 ? val : ((val >>> shift) | (val << (64 - shift))); - } - - private static int rotate32(final int val, final int shift) { - // Avoid shifting by 32: doing so yields an undefined result. - return shift == 0 ? val : ((val >>> shift) | (val << (32 - shift))); - } - private static long hashLen16(final long u, final long v, final long mul) { // Murmur-inspired hashing. long a = (u ^ v) * mul; @@ -446,21 +439,21 @@ public class CityHash implements Hash32, Hash64, Hash128 private int mur(int a, int h) { // Helper from Murmur3 for combining two 32-bit values. a *= c1; - a = rotate32(a, 17); + a = Integer.rotateRight(a, 17); a *= c2; h ^= a; - h = rotate32(h, 19); + h = Integer.rotateRight(h, 19); return h * 5 + 0xe6546b64; } private static Number128 weakHashLen32WithSeeds( final long w, final long x, final long y, final long z, long a, long b) { a += w; - b = rotate64(b + a + z, 21); + b = Long.rotateRight(b + a + z, 21); final long c = a; a += x; a += y; - b += rotate64(a, 44); + b += Long.rotateRight(a, 44); return new Number128(a + z, b + c); } diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/MurmurHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/MurmurHash.java index 0f3065973..e5d69616c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/MurmurHash.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/MurmurHash.java @@ -21,6 +21,9 @@ import java.nio.charset.Charset; * @since 4.3.3 */ public class MurmurHash implements Hash32, Hash64, Hash128{ + /** + * 单例 + */ public static final MurmurHash INSTANCE = new MurmurHash(); // Constants for 32 bit variant diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java index 240f060f0..ac736d053 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/AbstractMetroHash.java @@ -30,13 +30,7 @@ public abstract class AbstractMetroHash> implemen reset(); } - /** - * Applies the instance's Metro hash function to the bytes in the given buffer. - * This updates this instance's hashing state. - * - * @param input 内容 - * @return this - */ + @Override public R apply(final ByteBuffer input) { reset(); while (input.remaining() >= 32) { @@ -46,18 +40,32 @@ public abstract class AbstractMetroHash> implemen } /** - * Consumes a 32-byte chunk from the byte buffer and updates the hashing state. + * 从byteBuffer中计算32-byte块并更新hash状态 * - * @param partialInput byte buffer with at least 32 bytes remaining. + * @param partialInput byte buffer,至少有32byte的数据 * @return this */ abstract R partialApply32ByteChunk(ByteBuffer partialInput); /** - * Consumes the remaining bytes from the byte buffer and updates the hashing state. + * 从byteBuffer中计算剩余bytes并更新hash状态 * - * @param partialInput byte buffer with less than 32 bytes remaining. + * @param partialInput byte buffer,少于32byte的数据 * @return this */ abstract R partialApplyRemaining(ByteBuffer partialInput); + + static long grab(final ByteBuffer bb, final int length) { + long result = bb.get() & 0xFFL; + for (int i = 1; i < length; i++) { + result |= (bb.get() & 0xFFL) << (i << 3); + } + return result; + } + + static void writeLittleEndian(final long hash, final ByteBuffer output) { + for (int i = 0; i < 8; i++) { + output.put((byte) (hash >>> (i*8))); + } + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java index 940e2e9fc..ba461a8a5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash.java @@ -29,8 +29,8 @@ public interface MetroHash> { } /** - * Applies the instance's Metro hash function to the bytes in the given buffer. - * This updates this instance's hashing state. + * 将给定的{@link ByteBuffer}中的数据追加计算hash值
            + * 此方法会更新hash值状态 * * @param input 内容 * @return this @@ -38,8 +38,7 @@ public interface MetroHash> { R apply(final ByteBuffer input); /** - * Writes the current hash to the given byte buffer in big-endian order. - * 将结果hash值写出到{@link ByteBuffer}中 + * 将结果hash值写出到{@link ByteBuffer}中,可选端序 * * @param output 输出 * @param byteOrder 端序 diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java index 5a905f696..045bd4d5a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash128.java @@ -52,24 +52,6 @@ public class MetroHash128 extends AbstractMetroHash implements Has return this; } - /** - * 获取高64位结果hash值 - * - * @return hash值 - */ - public long getHigh() { - return v0; - } - - /** - * 获取低64位结果hash值 - * - * @return hash值 - */ - public long getLow() { - return v1; - } - /** * 获取结果hash值 * @@ -87,8 +69,8 @@ public class MetroHash128 extends AbstractMetroHash implements Has @Override public MetroHash128 write(final ByteBuffer output, final ByteOrder byteOrder) { if (ByteOrder.LITTLE_ENDIAN == byteOrder) { - MetroHashInternalUtil.writeLittleEndian(v0, output); - MetroHashInternalUtil.writeLittleEndian(v1, output); + writeLittleEndian(v0, output); + writeLittleEndian(v1, output); } else { output.asLongBuffer().put(v1).put(v0); } @@ -98,14 +80,14 @@ public class MetroHash128 extends AbstractMetroHash implements Has @Override MetroHash128 partialApply32ByteChunk(final ByteBuffer partialInput) { assert partialInput.remaining() >= 32; - v0 += MetroHashInternalUtil.grab8(partialInput) * K0; - v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2; - v1 += MetroHashInternalUtil.grab8(partialInput) * K1; - v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3; - v2 += MetroHashInternalUtil.grab8(partialInput) * K2; - v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0; - v3 += MetroHashInternalUtil.grab8(partialInput) * K3; - v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1; + v0 += grab(partialInput, 8) * K0; + v0 = Long.rotateRight(v0, 29) + v2; + v1 += grab(partialInput, 8) * K1; + v1 = Long.rotateRight(v1, 29) + v3; + v2 += grab(partialInput, 8) * K2; + v2 = Long.rotateRight(v2, 29) + v0; + v3 += grab(partialInput, 8) * K3; + v3 = Long.rotateRight(v3, 29) + v1; ++nChunks; return this; } @@ -131,52 +113,52 @@ public class MetroHash128 extends AbstractMetroHash implements Has if (partialInput.remaining() >= 1) { metroHash128_1(partialInput); } - v0 += MetroHashInternalUtil.rotateRight64(v0 * K0 + v1, 13); - v1 += MetroHashInternalUtil.rotateRight64(v1 * K1 + v0, 37); - v0 += MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 13); - v1 += MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 37); + v0 += Long.rotateRight(v0 * K0 + v1, 13); + v1 += Long.rotateRight(v1 * K1 + v0, 37); + v0 += Long.rotateRight(v0 * K2 + v1, 13); + v1 += Long.rotateRight(v1 * K3 + v0, 37); return this; } // region ----- private methods private void metroHash128_32() { - v2 ^= MetroHashInternalUtil.rotateRight64((v0 + v3) * K0 + v1, 21) * K1; - v3 ^= MetroHashInternalUtil.rotateRight64((v1 + v2) * K1 + v0, 21) * K0; - v0 ^= MetroHashInternalUtil.rotateRight64((v0 + v2) * K0 + v3, 21) * K1; - v1 ^= MetroHashInternalUtil.rotateRight64((v1 + v3) * K1 + v2, 21) * K0; + v2 ^= Long.rotateRight((v0 + v3) * K0 + v1, 21) * K1; + v3 ^= Long.rotateRight((v1 + v2) * K1 + v0, 21) * K0; + v0 ^= Long.rotateRight((v0 + v2) * K0 + v3, 21) * K1; + v1 ^= Long.rotateRight((v1 + v3) * K1 + v2, 21) * K0; } private void metroHash128_16(final ByteBuffer bb) { - v0 += MetroHashInternalUtil.grab8(bb) * K2; - v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; - v1 += MetroHashInternalUtil.grab8(bb) * K2; - v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; - v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 45) * K1; - v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 45) * K0; + v0 += grab(bb, 8) * K2; + v0 = Long.rotateRight(v0, 33) * K3; + v1 += grab(bb, 8) * K2; + v1 = Long.rotateRight(v1, 33) * K3; + v0 ^= Long.rotateRight(v0 * K2 + v1, 45) * K1; + v1 ^= Long.rotateRight(v1 * K3 + v0, 45) * K0; } private void metroHash128_8(final ByteBuffer bb) { - v0 += MetroHashInternalUtil.grab8(bb) * K2; - v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; - v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 27) * K1; + v0 += grab(bb, 8) * K2; + v0 = Long.rotateRight(v0, 33) * K3; + v0 ^= Long.rotateRight(v0 * K2 + v1, 27) * K1; } private void metroHash128_4(final ByteBuffer bb) { - v1 += MetroHashInternalUtil.grab4(bb) * K2; - v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; - v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 46) * K0; + v1 += grab(bb, 4) * K2; + v1 = Long.rotateRight(v1, 33) * K3; + v1 ^= Long.rotateRight(v1 * K3 + v0, 46) * K0; } private void metroHash128_2(final ByteBuffer bb) { - v0 += MetroHashInternalUtil.grab2(bb) * K2; - v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3; - v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 22) * K1; + v0 += grab(bb, 2) * K2; + v0 = Long.rotateRight(v0, 33) * K3; + v0 ^= Long.rotateRight(v0 * K2 + v1, 22) * K1; } private void metroHash128_1(final ByteBuffer bb) { - v1 += MetroHashInternalUtil.grab1(bb) * K2; - v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3; - v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 58) * K0; + v1 += grab(bb, 1) * K2; + v1 = Long.rotateRight(v1, 33) * K3; + v1 ^= Long.rotateRight(v1 * K3 + v0, 58) * K0; } // endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java index 8f9a78514..9a2e38703 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHash64.java @@ -67,7 +67,7 @@ public class MetroHash64 extends AbstractMetroHash implements Hash6 @Override public MetroHash64 write(final ByteBuffer output, final ByteOrder byteOrder) { if(ByteOrder.LITTLE_ENDIAN == byteOrder){ - MetroHashInternalUtil.writeLittleEndian(hash, output); + writeLittleEndian(hash, output); } else{ output.asLongBuffer().put(hash); } @@ -77,14 +77,14 @@ public class MetroHash64 extends AbstractMetroHash implements Hash6 @Override MetroHash64 partialApply32ByteChunk(final ByteBuffer partialInput) { assert partialInput.remaining() >= 32; - v0 += MetroHashInternalUtil.grab8(partialInput) * K0; - v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2; - v1 += MetroHashInternalUtil.grab8(partialInput) * K1; - v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3; - v2 += MetroHashInternalUtil.grab8(partialInput) * K2; - v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0; - v3 += MetroHashInternalUtil.grab8(partialInput) * K3; - v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1; + v0 += grab(partialInput, 8) * K0; + v0 = Long.rotateRight(v0, 29) + v2; + v1 += grab(partialInput, 8) * K1; + v1 = Long.rotateRight(v1, 29) + v3; + v2 += grab(partialInput, 8) * K2; + v2 = Long.rotateRight(v2, 29) + v0; + v3 += grab(partialInput, 8) * K3; + v3 = Long.rotateRight(v3, 29) + v1; ++nChunks; return this; } @@ -110,49 +110,49 @@ public class MetroHash64 extends AbstractMetroHash implements Hash6 if (partialInput.remaining() >= 1) { metroHash64_1(partialInput); } - hash ^= MetroHashInternalUtil.rotateRight64(hash, 28); + hash ^= Long.rotateRight(hash, 28); hash *= K0; - hash ^= MetroHashInternalUtil.rotateRight64(hash, 29); + hash ^= Long.rotateRight(hash, 29); return this; } // region ----- private methods private void metroHash64_32() { - v2 ^= MetroHashInternalUtil.rotateRight64(((v0 + v3) * K0) + v1, 37) * K1; - v3 ^= MetroHashInternalUtil.rotateRight64(((v1 + v2) * K1) + v0, 37) * K0; - v0 ^= MetroHashInternalUtil.rotateRight64(((v0 + v2) * K0) + v3, 37) * K1; - v1 ^= MetroHashInternalUtil.rotateRight64(((v1 + v3) * K1) + v2, 37) * K0; + v2 ^= Long.rotateRight(((v0 + v3) * K0) + v1, 37) * K1; + v3 ^= Long.rotateRight(((v1 + v2) * K1) + v0, 37) * K0; + v0 ^= Long.rotateRight(((v0 + v2) * K0) + v3, 37) * K1; + v1 ^= Long.rotateRight(((v1 + v3) * K1) + v2, 37) * K0; hash += v0 ^ v1; } private void metroHash64_16(final ByteBuffer bb) { - v0 = hash + MetroHashInternalUtil.grab8(bb) * K2; - v0 = MetroHashInternalUtil.rotateRight64(v0, 29) * K3; - v1 = hash + MetroHashInternalUtil.grab8(bb) * K2; - v1 = MetroHashInternalUtil.rotateRight64(v1, 29) * K3; - v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K0, 21) + v1; - v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3, 21) + v0; + v0 = hash + grab(bb, 8) * K2; + v0 = Long.rotateRight(v0, 29) * K3; + v1 = hash + grab(bb, 8) * K2; + v1 = Long.rotateRight(v1, 29) * K3; + v0 ^= Long.rotateRight(v0 * K0, 21) + v1; + v1 ^= Long.rotateRight(v1 * K3, 21) + v0; hash += v1; } private void metroHash64_8(final ByteBuffer bb) { - hash += MetroHashInternalUtil.grab8(bb) * K3; - hash ^= MetroHashInternalUtil.rotateRight64(hash, 55) * K1; + hash += grab(bb, 8) * K3; + hash ^= Long.rotateRight(hash, 55) * K1; } private void metroHash64_4(final ByteBuffer bb) { - hash += MetroHashInternalUtil.grab4(bb) * K3; - hash ^= MetroHashInternalUtil.rotateRight64(hash, 26) * K1; + hash += grab(bb, 4) * K3; + hash ^= Long.rotateRight(hash, 26) * K1; } private void metroHash64_2(final ByteBuffer bb) { - hash += MetroHashInternalUtil.grab2(bb) * K3; - hash ^= MetroHashInternalUtil.rotateRight64(hash, 48) * K1; + hash += grab(bb, 2) * K3; + hash ^= Long.rotateRight(hash, 48) * K1; } private void metroHash64_1(final ByteBuffer bb) { - hash += MetroHashInternalUtil.grab1(bb) * K3; - hash ^= MetroHashInternalUtil.rotateRight64(hash, 37) * K1; + hash += grab(bb, 1) * K3; + hash ^= Long.rotateRight(hash, 37) * K1; } // endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java b/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java deleted file mode 100644 index 2a4e49713..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/codec/hash/metro/MetroHashInternalUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.hutool.core.codec.hash.metro; - -import java.nio.ByteBuffer; - -class MetroHashInternalUtil { - - static void writeLittleEndian(final long hash, final ByteBuffer output) { - output.put((byte) hash); - output.put((byte) (hash >>> 8)); - output.put((byte) (hash >>> 16)); - output.put((byte) (hash >>> 24)); - output.put((byte) (hash >>> 32)); - output.put((byte) (hash >>> 40)); - output.put((byte) (hash >>> 48)); - output.put((byte) (hash >>> 56)); - } - - static long rotateRight64(final long x, final int r) { - return (x >>> r) | (x << (64 - r)); - } - - static long grab1(final ByteBuffer bb) { - return ((long) bb.get() & 0xFFL); - } - - static long grab2(final ByteBuffer bb) { - final long v0 = bb.get(); - final long v1 = bb.get(); - return (v0 & 0xFFL) | (v1 & 0xFFL) << 8; - } - - static long grab4(final ByteBuffer bb) { - final long v0 = bb.get(); - final long v1 = bb.get(); - final long v2 = bb.get(); - final long v3 = bb.get(); - return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24; - } - - static long grab8(final ByteBuffer bb) { - final long v0 = bb.get(); - final long v1 = bb.get(); - final long v2 = bb.get(); - final long v3 = bb.get(); - final long v4 = bb.get(); - final long v5 = bb.get(); - final long v6 = bb.get(); - final long v7 = bb.get(); - return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24 | (v4 & 0xFFL) << 32 | (v5 & 0xFFL) << 40 | (v6 & 0xFFL) << 48 | (v7 & 0xFFL) << 56; - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java index 365fdcaf0..f40ae04af 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java @@ -1761,5 +1761,4 @@ public class NumberUtil { public static boolean isEven(final int num) { return false == isOdd(num); } - } diff --git a/hutool-core/src/main/java/cn/hutool/core/tree/BeanTree.java b/hutool-core/src/main/java/cn/hutool/core/tree/BeanTree.java index aa0cf12df..38e9eb05f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/tree/BeanTree.java +++ b/hutool-core/src/main/java/cn/hutool/core/tree/BeanTree.java @@ -30,10 +30,13 @@ import java.util.function.Predicate; * 也可以将已有的树转换为集合,例如: *

            {@code final List javaBeanList = beanTree.flat(originJavaBeanTree);}
            * + *

            最后,引用一句电影经典台词: 无处安放的双手,以及无处安放的灵魂。——《Hello!树先生》

            + * + * @param Bean类型 + * @param 主键、外键类型 * @author VampireAchao * @author emptypoint * @author CreateSequence - * 最后,引用一句电影经典台词: 无处安放的双手,以及无处安放的灵魂。——《Hello!树先生》 */ public class BeanTree> { @@ -126,10 +129,10 @@ public class BeanTree> { if (CollUtil.isEmpty(list)) { return ListUtil.zero(); } - if (Objects.isNull(parentPredicate)) { - final Map> pIdValuesMap = EasyStream.of(list) - .peek(e -> Objects.requireNonNull(idGetter.apply(e), () -> "The id of tree node must not be null " + e)) - .group(pidGetter); + if (Objects.isNull(parentPredicate)) { + final Map> pIdValuesMap = EasyStream.of(list) + .peek(e -> Objects.requireNonNull(idGetter.apply(e), () -> "The id of tree node must not be null " + e)) + .group(pidGetter); final List parents = pIdValuesMap.getOrDefault(pidValue, new ArrayList<>()); findChildren(list, pIdValuesMap); return parents; @@ -206,7 +209,7 @@ public class BeanTree> { * @param pIdValuesMap 父id与子集的映射 */ private void findChildren(final List list, final Map> pIdValuesMap) { - for (T node : list) { + for (final T node : list) { final List children = pIdValuesMap.get(idGetter.apply(node)); if (children != null) { childrenSetter.accept(node, children); diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java index 0f2da98b7..b15f4359a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/hash/metro/MetroHash128Test.java @@ -1,6 +1,7 @@ package cn.hutool.core.codec.hash.metro; import cn.hutool.core.codec.HexUtil; +import cn.hutool.core.codec.Number128; import cn.hutool.core.text.StrUtil; import org.junit.Assert; import org.junit.Test; @@ -106,7 +107,8 @@ public class MetroHash128Test { static String h128(final String input) { final MetroHash128 mh = MetroHash128.of(0).apply(ByteBuffer.wrap(StrUtil.utf8Bytes(input))); - return hex(mh.getHigh()) + hex(mh.getLow()); + final Number128 hash = mh.get(); + return hex(hash.getHighValue()) + hex(hash.getLowValue()); } private static String hex(final long value){ diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 7e2af1963..aa76ecd97 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -82,13 +82,13 @@ public class NumberUtilTest { @Test public void isIntegerTest() { - String[] validNumArr = {"0", "-0", "+0", "12", "+12", "1234567890", "2147483647", "-2147483648", + final String[] validNumArr = {"0", "-0", "+0", "12", "+12", "1234567890", "2147483647", "-2147483648", "0x012345678", "0X012345678", "0xabcdef", "-0xabcdef", "0x12abcdef", "0x7FFFFFFF", "-0x80000000", "01234567", "017777777777", "-020000000000" }; privateIsIntegerTest(validNumArr, true); - String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99L", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3", + final String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99L", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3", "2147483648", "0x80000000", "020000000000", "-2147483649", "-0x80000001", "-020000000001", "-020000000001", "a", "+a", "123abc", "09" }; @@ -96,14 +96,14 @@ public class NumberUtilTest { } private void privateIsIntegerTest(final String[] numStrArr, final boolean expected) { - for (String numStr : numStrArr) { + for (final String numStr : numStrArr) { Assert.assertEquals("未通过的数字为: " + numStr, expected, NumberUtil.isInteger(numStr)); } } @Test public void isLongTest() { - String[] validNumArr = { + final String[] validNumArr = { "0", "0L", "-0L", "+0L", "12", "+12", "1234567890123456789", "99L", "2147483648", "0x80000000", "020000000000", "-2147483649", "-0x80000001", "-020000000001", "-020000000001", "9223372036854775807", "-9223372036854775808", @@ -113,7 +113,7 @@ public class NumberUtilTest { }; privateIsLongTest(validNumArr, true); - String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3", + final String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3", "a", "+a", "123abc", "09", "9223372036854775808", "-9223372036854775809", "0x8000000000000000", "-0x8000000000000001", @@ -123,7 +123,7 @@ public class NumberUtilTest { } private void privateIsLongTest(final String[] numStrArr, final boolean expected) { - for (String numStr : numStrArr) { + for (final String numStr : numStrArr) { Assert.assertEquals("未通过的数字为: " + numStr, expected, NumberUtil.isLong(numStr)); } } From 1ad628f94416d4fc21aca856a05c99d2d9fc4937 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 11:41:20 +0800 Subject: [PATCH 115/125] fix code --- .gitee/ISSUE_TEMPLATE.zh-CN.md | 4 ++-- .github/ISSUE_TEMPLATE.md | 4 ++-- README-EN.md | 6 +++--- README.md | 6 +++--- SECURITY.md | 2 +- bin/replaceVersion.sh | 12 ++++++------ .../cn/hutool/core/annotation/AnnotationMapping.java | 2 +- .../java/cn/hutool/core/date/BetweenFormatter.java | 2 +- .../main/java/cn/hutool/core/io/file/FileReader.java | 3 ++- .../cn/hutool/core/io/resource/ResourceUtil.java | 1 + .../java/cn/hutool/core/lang/range/BoundedRange.java | 2 +- .../hutool/core/stream/TerminableWrappedStream.java | 3 ++- .../java/cn/hutool/core/text/AntPathMatcher.java | 2 +- .../src/main/java/cn/hutool/core/util/ArrayUtil.java | 2 +- .../test/java/cn/hutool/core/text/StrUtilTest.java | 1 + .../test/java/cn/hutool/core/util/ArrayUtilTest.java | 6 +++--- .../test/java/cn/hutool/core/util/ZipUtilTest.java | 7 ++++--- .../src/main/java/cn/hutool/crypto/BCUtil.java | 2 +- .../cn/hutool/crypto/symmetric/Sm4StreamTest.java | 12 ++++++------ .../resources/config/example/db-example-dbcp.setting | 4 ++-- .../hutool/extra/aop/interceptor/JdkInterceptor.java | 6 ++++++ .../cn/hutool/extra/management/oshi/CpuTicks.java | 2 +- .../src/main/java/cn/hutool/poi/csv/CsvRow.java | 10 ++-------- .../src/main/java/cn/hutool/poi/csv/CsvWriter.java | 2 +- .../java/cn/hutool/swing/img/BackgroundRemoval.java | 10 +++++----- 25 files changed, 59 insertions(+), 54 deletions(-) diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md index 6a1c8ee09..920eaa91f 100644 --- a/.gitee/ISSUE_TEMPLATE.zh-CN.md +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -11,8 +11,8 @@ hutool版本: 5.X.X(请确保最新尝试是否还有问题) Console.log("报错了"); ``` -2. 堆栈信息 +1. 堆栈信息 -3. 测试涉及到的文件(注意脱密) +2. 测试涉及到的文件(注意脱密) 比如报错的Excel文件,有问题的图片等。 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 6a1c8ee09..920eaa91f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -11,8 +11,8 @@ hutool版本: 5.X.X(请确保最新尝试是否还有问题) Console.log("报错了"); ``` -2. 堆栈信息 +1. 堆栈信息 -3. 测试涉及到的文件(注意脱密) +2. 测试涉及到的文件(注意脱密) 比如报错的Excel文件,有问题的图片等。 \ No newline at end of file diff --git a/README-EN.md b/README-EN.md index 1acb7eaeb..0aca83d4a 100755 --- a/README-EN.md +++ b/README-EN.md @@ -176,10 +176,10 @@ cd ${hutool} Hutool's source code is divided into two branches: -| branch | description | -|-----------|---------------------------------------------------------------| +| branch | description | +|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | v6-master | The master branch, the branch used by the release version, is the same as the jar committed to the central repository and does not receive any pr or modifications. | -| v6-dev | Development branch, which defaults to the next SNAPSHOT version, accepts modifications or pr | +| v6-dev | Development branch, which defaults to the next SNAPSHOT version, accepts modifications or pr | ### 🐞Provide feedback or suggestions on bugs diff --git a/README.md b/README.md index c24d857fb..dda1ddff4 100755 --- a/README.md +++ b/README.md @@ -180,10 +180,10 @@ implementation 'cn.hutool:hutool-all:6.0.0.M1' Hutool的源码分为两个分支,功能如下: -| 分支 | 作用 | -|-----------|---------------------------------------------------------------| +| 分支 | 作用 | +|-----------|--------------------------------------------| | v6-master | 主分支,release版本使用的分支,与中央库提交的jar一致,不接收任何pr或修改 | -| v6-dev | 开发分支,默认为下个版本的SNAPSHOT版本,接受修改或pr | +| v6-dev | 开发分支,默认为下个版本的SNAPSHOT版本,接受修改或pr | ### 🐞提供bug反馈或建议 diff --git a/SECURITY.md b/SECURITY.md index 0edd9b589..ec97fe9b2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,7 +3,7 @@ ## Supported Versions(支持的版本) | Version | Supported | -|---------| ------------------ | +|---------|--------------------| | 6.x.x | :white_check_mark: | ## Reporting a Vulnerability(报告漏洞) diff --git a/bin/replaceVersion.sh b/bin/replaceVersion.sh index f6f60c81e..8bd8d2d29 100755 --- a/bin/replaceVersion.sh +++ b/bin/replaceVersion.sh @@ -12,7 +12,7 @@ echo "当前路径:${pwd}" if [ -n "$1" ];then new_version="$1" - old_version=`cat ${pwd}/bin/version.txt` + old_version=$(cat "${pwd}"/bin/version.txt) echo "$old_version 替换为新版本 $new_version" else # 参数错误,退出 @@ -20,16 +20,16 @@ else exit fi -if [ ! -n "$old_version" ]; then +if [ -z "$old_version" ]; then echo "ERROR: 旧版本不存在,请确认bin/version.txt中信息正确" exit fi # 替换README.md中的版本 -sed -i "s/${old_version}/${new_version}/g" $pwd/README.md -sed -i "s/${old_version}/${new_version}/g" $pwd/README-EN.md +sed -i "s/${old_version}/${new_version}/g" "$pwd"/README.md +sed -i "s/${old_version}/${new_version}/g" "$pwd"/README-EN.md # 替换docs/js/version.js中的版本 -sed -i "s/${old_version}/${new_version}/g" $pwd/docs/js/version.js +sed -i "s/${old_version}/${new_version}/g" "$pwd"/docs/js/version.js # 保留新版本号 -echo "$new_version" > $pwd/bin/version.txt +echo "$new_version" > "$pwd"/bin/version.txt diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationMapping.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationMapping.java index c177629f6..c9af1d448 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationMapping.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationMapping.java @@ -28,7 +28,7 @@ public interface AnnotationMapping extends Annotation { T getAnnotation(); /** - * 根据当前映射对象,通过动态代理生成一个类型与被包装注解对象一致的合成注解,该注解相对原生注解: + * 根据当前映射对象,通过动态代理生成一个类型与被包装注解对象一致地合成注解,该注解相对原生注解: *
              *
            • 支持同注解内通过{@link Alias}构建的别名机制;
            • *
            • 支持子注解对元注解的同名同类型属性覆盖机制;
            • diff --git a/hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java b/hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java index 51b281a15..b54c05f17 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java @@ -73,7 +73,7 @@ public class BetweenFormatter implements Serializable { final int level = this.level.ordinal(); int levelCount = 0; - if (isLevelCountValid(levelCount) && 0 != day && level >= Level.DAY.ordinal()) { + if (isLevelCountValid(levelCount) && 0 != day) { sb.append(day).append(Level.DAY.name); levelCount++; } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java index f82e9e260..2542e14d3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/FileReader.java @@ -15,6 +15,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -246,7 +247,7 @@ public class FileReader extends FileWrapper { */ public BufferedInputStream getInputStream() throws IORuntimeException { try { - return new BufferedInputStream(new FileInputStream(this.file)); + return new BufferedInputStream(Files.newInputStream(this.file.toPath())); } catch (final IOException e) { throw new IORuntimeException(e); } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java index dc03d3266..c746a1715 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/resource/ResourceUtil.java @@ -123,6 +123,7 @@ public class ResourceUtil { * * @param resource 资源(相对Classpath的路径) * @return 资源URL + * @throws IORuntimeException IO异常 */ public static URL getResourceUrl(final String resource) throws IORuntimeException { return getResourceUrl(resource, null); diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java index 36776bfb4..b6415a54c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/range/BoundedRange.java @@ -24,7 +24,7 @@ import java.util.function.Predicate; * * *

              空区间

              - *

              根据数学定义,当区间中无任何实数时,认为该区间代表的集合为空集, + *

              根据数学定义,当区间中无任何实数时,认为该区间 代表的集合为空集, * 用户可通过{@link #isEmpty}确认当前实例是否为空区间。
              * 若实例上界a,下界为b,则当实例满足下述任意条件时,认为其为一个空区间: *

                diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java index 258518624..bf7de7500 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java @@ -254,6 +254,7 @@ public interface TerminableWrappedStream predicate) { Objects.requireNonNull(predicate); if (isParallel()) { @@ -263,7 +264,7 @@ public interface TerminableWrappedStream { index.increment(); return predicate.test(e); - }).findFirst(); + }).findFirst();// 此处只做计数,不需要值 return index.get(); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java b/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java index 7fa9b3dd2..412b94d84 100755 --- a/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/AntPathMatcher.java @@ -428,7 +428,7 @@ public class AntPathMatcher { } /** - * Test whether or not a string matches against a pattern. + * Test whether a string matches against a pattern. * * @param pattern the pattern to match against (never {@code null}) * @param str the String which must be matched against the pattern (never {@code null}) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index bd8373d44..de1ac4631 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -89,7 +89,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { * 数组是否为非空
                * 此方法会匹配单一对象,如果此对象为{@code null}则返回false
                * 如果此对象为非数组,理解为此对象为数组的第一个元素,则返回true
                - * 如果此对象为数组对象,数组长度大于0情况下返回true,否则返回false + * 如果此对象为数组对象,数组长度大于0的情况下返回true,否则返回false * * @param array 数组 * @return 是否为非空 diff --git a/hutool-core/src/test/java/cn/hutool/core/text/StrUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/StrUtilTest.java index 7f380e5b7..015a6395e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/StrUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/StrUtilTest.java @@ -280,6 +280,7 @@ public class StrUtilTest { Assert.assertEquals("ghigh", pre); } + @SuppressWarnings("SimplifiableAssertion") @Test public void subPreTest() { Assert.assertEquals(StrUtil.subPre(null, 3), null); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 3c009e5c3..f085dbe88 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -216,7 +216,7 @@ public class ArrayUtilTest { final String[] a = {"1", "2", "3", "4"}; final String[] b = {"a", "b", "c"}; - // 在-1位置插入,相当于在3位置插入 + // 在-1的位置插入,相当于在3的位置插入 String[] result = ArrayUtil.insert(a, -1, b); Assert.assertArrayEquals(new String[]{"1", "2", "3", "a", "b", "c", "4"}, result); @@ -232,7 +232,7 @@ public class ArrayUtilTest { result = ArrayUtil.insert(a, 4, b); Assert.assertArrayEquals(new String[]{"1", "2", "3", "4", "a", "b", "c"}, result); - // 在第5个位置插入,由于数组长度为4,因此补null + // 在第5个位置插入,由于数组长度为4,因此补充null result = ArrayUtil.insert(a, 5, b); Assert.assertArrayEquals(new String[]{"1", "2", "3", "4", null, "a", "b", "c"}, result); } @@ -472,7 +472,7 @@ public class ArrayUtilTest { final String[] a = {"1", "2", "3", "4"}; final String[] b = {"a", "b", "c"}; - // 在小于0的位置,-1位置插入,返回b+a,新数组 + // 在小于0的位置,-1的位置插入,返回b+a,新数组 String[] result = ArrayUtil.replace(a, -1, b); Assert.assertArrayEquals(new String[]{"a", "b", "c", "1", "2", "3", "4"}, result); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java index f6011e994..eba84fa3a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java @@ -2,8 +2,8 @@ package cn.hutool.core.util; import cn.hutool.core.compress.ZipReader; import cn.hutool.core.compress.ZipUtil; -import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.file.FileUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.text.StrUtil; import org.junit.Assert; @@ -11,11 +11,12 @@ import org.junit.Ignore; import org.junit.Test; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipFile; @@ -156,7 +157,7 @@ public class ZipUtilTest { //https://github.com/dromara/hutool/issues/944 final String dir = "d:/test"; final String zip = "d:/test.zip"; - try (final OutputStream out = new FileOutputStream(zip)){ + try (final OutputStream out = Files.newOutputStream(Paths.get(zip))){ //实际应用中, out 为 HttpServletResponse.getOutputStream ZipUtil.zip(out, Charset.defaultCharset(), false, null, new File(dir)); } catch (final IOException e) { diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java index 6752c1612..dea2f596b 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java @@ -34,7 +34,7 @@ import java.security.spec.ECPublicKeySpec; public class BCUtil { /** - * 只获取私钥里的d,32字节 + * 只获取私钥里的d,32位字节 * * @param privateKey {@link PublicKey},必须为org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey * @return 压缩得到的X diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/Sm4StreamTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/Sm4StreamTest.java index 8d03f2752..afedd4423 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/Sm4StreamTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/symmetric/Sm4StreamTest.java @@ -3,11 +3,11 @@ package cn.hutool.crypto.symmetric; import org.junit.Ignore; import org.junit.Test; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; /** * https://gitee.com/dromara/hutool/issues/I4EMST @@ -29,8 +29,8 @@ public class Sm4StreamTest { } public static void encrypt(final String source, final String target) { - try (final InputStream input = new FileInputStream(source); - final OutputStream out = new FileOutputStream(target)) { + try (final InputStream input = Files.newInputStream(Paths.get(source)); + final OutputStream out = Files.newOutputStream(Paths.get(target))) { sm4.encrypt(input, out, IS_CLOSE); System.out.println("============encrypt end"); } catch (final IOException e) { @@ -39,8 +39,8 @@ public class Sm4StreamTest { } public static void decrypt(final String source, final String target) { - try (final InputStream input = new FileInputStream(source); - final OutputStream out = new FileOutputStream(target)) { + try (final InputStream input = Files.newInputStream(Paths.get(source)); + final OutputStream out = Files.newOutputStream(Paths.get(target))) { sm4.decrypt(input, out, IS_CLOSE); System.out.println("============decrypt end"); } catch (final IOException e) { diff --git a/hutool-db/src/test/resources/config/example/db-example-dbcp.setting b/hutool-db/src/test/resources/config/example/db-example-dbcp.setting index 8ec36fc75..7d491123f 100644 --- a/hutool-db/src/test/resources/config/example/db-example-dbcp.setting +++ b/hutool-db/src/test/resources/config/example/db-example-dbcp.setting @@ -37,7 +37,7 @@ initialSize = 10 maxActive = 100 # (int) 最大空闲连接: 连接池中容许保持空闲状态的最大连接数量, 超过的空闲连接将被释放, 如果设置为负数表示不限制 如果启用,将定期检查限制连接,如果空闲时间超过minEvictableIdleTimeMillis 则释放连接 ( 参考testWhileIdle ) maxIdle = 8 -# (int) 最小空闲连接: 连接池中容许保持空闲状态的最小连接数量, 低于这个数量将创建新的连接, 如果设置为0 则不创建 如果连接验证失败将缩小这个值( 参考testWhileIdle ) +# (int) 最小空闲连接: 连接池中容许保持空闲状态的最小连接数量, 低于这个数量将创建新连接, 如果设置为0 则不创建 如果连接验证失败将缩小这个值( 参考testWhileIdle ) minIdle = 0 # (int) 最大等待时间: 当没有可用连接时, 连接池等待连接被归还的最大时间( 以毫秒计数), 超过时间则抛出异常, 如果设置为-1 表示无限等待 maxWait = 30000 @@ -48,4 +48,4 @@ testOnBorrow = false # (boolean) 指明是否在归还到池中前进行检验 注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串 testOnReturn = false # (boolean) 指明连接是否被空闲连接回收器( 如果有) 进行检验。 如果检测失败, 则连接将被从池中去除。注意: 设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串 -testWhileIdle = false \ No newline at end of file +testWhileIdle = false diff --git a/hutool-extra/src/main/java/cn/hutool/extra/aop/interceptor/JdkInterceptor.java b/hutool-extra/src/main/java/cn/hutool/extra/aop/interceptor/JdkInterceptor.java index 86f1049ab..a5aacf7ac 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/aop/interceptor/JdkInterceptor.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/aop/interceptor/JdkInterceptor.java @@ -32,10 +32,16 @@ public class JdkInterceptor implements InvocationHandler, Serializable { this.aspect = aspect; } + /** + * 获取目标对象 + * + * @return 目标对象 + */ public Object getTarget() { return this.target; } + @SuppressWarnings("SuspiciousInvocationHandlerImplementation") @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final Object target = this.target; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/management/oshi/CpuTicks.java b/hutool-extra/src/main/java/cn/hutool/extra/management/oshi/CpuTicks.java index 2690bf6e1..0c1ee75a7 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/management/oshi/CpuTicks.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/management/oshi/CpuTicks.java @@ -29,7 +29,7 @@ public class CpuTicks { public CpuTicks(final CentralProcessor processor, final long waitingTime) { // CPU信息 final long[] prevTicks = processor.getSystemCpuLoadTicks(); - // 这里必须要设置延迟 + // 这里必须设置延迟 Util.sleep(waitingTime); final long[] ticks = processor.getSystemCpuLoadTicks(); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java index 5d7b77bf9..823f19f75 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvRow.java @@ -4,12 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.lang.Assert; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; +import java.util.*; /** * CSV中一行的表示 @@ -146,7 +141,6 @@ public final class CsvRow implements List { @Override public T[] toArray(final T[] a) { - //noinspection SuspiciousToArrayCall return this.fields.toArray(a); } @@ -162,7 +156,7 @@ public final class CsvRow implements List { @Override public boolean containsAll(final Collection c) { - return this.fields.containsAll(c); + return new HashSet<>(this.fields).containsAll(c); } @Override diff --git a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java index edab978bb..066951781 100755 --- a/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/csv/CsvWriter.java @@ -320,7 +320,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { Assert.notNull(this.config.commentCharacter, "Comment is disable!"); try { if(isFirstLine){ - // 首行不补换行符 + // 首行不补充换行符 isFirstLine = false; }else { writer.write(config.lineDelimiter); diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java b/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java index 21af9782b..99cfc5e77 100755 --- a/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java +++ b/hutool-swing/src/main/java/cn/hutool/swing/img/BackgroundRemoval.java @@ -40,7 +40,7 @@ public class BackgroundRemoval { * 将 "纯色背景的图片" 还原成 "透明背景的图片" * 将纯色背景的图片转成矢量图 * 取图片边缘的像素点和获取到的图片主题色作为要替换的背景色 - * 再加入一定的容差值,然后将所有像素点与该颜色进行比较 + * 再加入一定地容差值,然后将所有像素点与该颜色进行比较 * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param inputPath 要处理图片的路径 @@ -58,7 +58,7 @@ public class BackgroundRemoval { * 将 "纯色背景的图片" 还原成 "透明背景的图片" * 将纯色背景的图片转成矢量图 * 取图片边缘的像素点和获取到的图片主题色作为要替换的背景色 - * 再加入一定的容差值,然后将所有像素点与该颜色进行比较 + * 再加入一定地容差值,然后将所有像素点与该颜色进行比较 * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param input 需要进行操作的图片 @@ -76,7 +76,7 @@ public class BackgroundRemoval { * 将 "纯色背景的图片" 还原成 "透明背景的图片" * 将纯色背景的图片转成矢量图 * 取图片边缘的像素点和获取到的图片主题色作为要替换的背景色 - * 再加入一定的容差值,然后将所有像素点与该颜色进行比较 + * 再加入一定地容差值,然后将所有像素点与该颜色进行比较 * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param input 需要进行操作的图片 @@ -106,7 +106,7 @@ public class BackgroundRemoval { * 将 "纯色背景的图片" 还原成 "透明背景的图片" * 将纯色背景的图片转成矢量图 * 取图片边缘的像素点和获取到的图片主题色作为要替换的背景色 - * 再加入一定的容差值,然后将所有像素点与该颜色进行比较 + * 再加入一定地容差值,然后将所有像素点与该颜色进行比较 * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param bufferedImage 需要进行处理的图片流 @@ -152,7 +152,7 @@ public class BackgroundRemoval { * 将 "纯色背景的图片" 还原成 "透明背景的图片" * 将纯色背景的图片转成矢量图 * 取图片边缘的像素点和获取到的图片主题色作为要替换的背景色 - * 再加入一定的容差值,然后将所有像素点与该颜色进行比较 + * 再加入一定地容差值,然后将所有像素点与该颜色进行比较 * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param outputStream 需要进行处理的图片字节数组流 From c1a895bce52fb2e3b9780834723beb27f2380f6a Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 12:22:51 +0800 Subject: [PATCH 116/125] fix code --- README-EN.md | 6 +++--- README.md | 6 +++--- bin/version.txt | 2 +- docs/js/version.js | 2 +- hutool-all/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-core/pom.xml | 2 +- .../hutool/core/io/stream/SyncInputStream.java | 12 ++++++------ hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- .../java/cn/hutool/http/client/Response.java | 17 +++++++++++++---- .../hutool/http/client/body/ResponseBody.java | 15 +++++++++++++++ .../http/client/HttpClient4EngineTest.java | 3 +-- .../http/client/HttpClient5EngineTest.java | 4 ++-- hutool-json/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-swing/pom.xml | 2 +- pom.xml | 2 +- 24 files changed, 60 insertions(+), 37 deletions(-) diff --git a/README-EN.md b/README-EN.md index 0aca83d4a..6f7207f02 100755 --- a/README-EN.md +++ b/README-EN.md @@ -138,18 +138,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 6.0.0.M1 + 6.0.0.M2 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:6.0.0.M1' +implementation 'cn.hutool:hutool-all:6.0.0.M2' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/6.0.0.M1/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/6.0.0.M2/) > 🔔️note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index dda1ddff4..40a1b3e99 100755 --- a/README.md +++ b/README.md @@ -141,21 +141,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 6.0.0.M1 + 6.0.0.M2 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:6.0.0.M1' +implementation 'cn.hutool:hutool-all:6.0.0.M2' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/6.0.0.M1/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/6.0.0.M2/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index c946d3d40..95e0d8a6f 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -6.0.0.M1 +6.0.0.M2 diff --git a/docs/js/version.js b/docs/js/version.js index a5763db79..7b755716b 100755 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '6.0.0.M1' \ No newline at end of file +var version = '6.0.0.M2' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 5f87a6a2a..808274d2b 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-all diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 63b187098..e5ab0a02b 100755 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-bom diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 261ff8b03..7db304dc5 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-core diff --git a/hutool-core/src/main/java/cn/hutool/core/io/stream/SyncInputStream.java b/hutool-core/src/main/java/cn/hutool/core/io/stream/SyncInputStream.java index 08b22c990..fd2673db3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/stream/SyncInputStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/stream/SyncInputStream.java @@ -48,15 +48,15 @@ public class SyncInputStream extends FilterInputStream { /** * 同步数据到内存 + * @return this */ - public void sync() { - if (false == asyncFlag) { - // 已经是同步模式 - return; + public SyncInputStream sync() { + if (asyncFlag) { + this.in = new ByteArrayInputStream(readBytes()); + this.asyncFlag = false; } - this.in = new ByteArrayInputStream(readBytes()); - this.asyncFlag = false; + return this; } /** diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 3ddae39f7..0e970ed12 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 8f6f1050e..561ef5c25 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 02d148512..f2a251b9a 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-db diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 1a3a53e81..e2e010190 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index b6470b069..f0701fa19 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-http diff --git a/hutool-http/src/main/java/cn/hutool/http/client/Response.java b/hutool-http/src/main/java/cn/hutool/http/client/Response.java index 991857ff7..3e587e7ca 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/Response.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/Response.java @@ -1,14 +1,15 @@ package cn.hutool.http.client; import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.text.StrUtil; import cn.hutool.http.HttpException; import cn.hutool.http.client.body.ResponseBody; -import cn.hutool.http.html.HtmlUtil; import cn.hutool.http.meta.ContentTypeUtil; import cn.hutool.http.meta.Header; import java.io.Closeable; +import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.List; @@ -79,17 +80,25 @@ public interface Response extends Closeable { * @throws HttpException 包装IO异常 */ default String bodyStr() throws HttpException { - return HtmlUtil.getString(bodyBytes(), charset(), true); + try(final ResponseBody body = body()){ + return body.getString(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } } /** * 获取响应流字节码
                - * 此方法会转为同步模式 + * 此方法会转为同步模式,读取响应流并关闭之 * * @return byte[] */ default byte[] bodyBytes() { - return body().getBytes(); + try(final ResponseBody body = body()){ + return body.getBytes(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } } /** diff --git a/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java b/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java index c1019d73c..c73eea208 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/body/ResponseBody.java @@ -11,6 +11,7 @@ import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.http.HttpException; import cn.hutool.http.client.Response; +import cn.hutool.http.html.HtmlUtil; import cn.hutool.http.meta.Header; import java.io.Closeable; @@ -79,6 +80,15 @@ public class ResponseBody implements HttpBody, Closeable { return this.bodyStream.readBytes(); } + /** + * 获取响应字符串,自动识别判断编码 + * + * @return 响应字符串 + */ + public String getString() { + return HtmlUtil.getString(getBytes(), response.charset(), true); + } + /** * 将响应内容写出到{@link OutputStream}
                * 异步模式下直接读取Http流写出,同步模式下将存储在内存中的响应内容写出
                @@ -189,6 +199,11 @@ public class ResponseBody implements HttpBody, Closeable { this.bodyStream.close(); } + @Override + public String toString() { + return getString(); + } + // region ---------------------------------------------------------------------------- Private Methods /** diff --git a/hutool-http/src/test/java/cn/hutool/http/client/HttpClient4EngineTest.java b/hutool-http/src/test/java/cn/hutool/http/client/HttpClient4EngineTest.java index 2a5ef4f3e..1df07269c 100755 --- a/hutool-http/src/test/java/cn/hutool/http/client/HttpClient4EngineTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/client/HttpClient4EngineTest.java @@ -3,14 +3,13 @@ package cn.hutool.http.client; import cn.hutool.core.lang.Console; import cn.hutool.http.client.engine.httpclient4.HttpClient4Engine; import cn.hutool.http.meta.Method; -import org.junit.Ignore; import org.junit.Test; public class HttpClient4EngineTest { @SuppressWarnings("resource") @Test - @Ignore + //@Ignore public void getTest() { final ClientEngine engine = new HttpClient4Engine(); diff --git a/hutool-http/src/test/java/cn/hutool/http/client/HttpClient5EngineTest.java b/hutool-http/src/test/java/cn/hutool/http/client/HttpClient5EngineTest.java index 6f069722b..c1b447ec0 100755 --- a/hutool-http/src/test/java/cn/hutool/http/client/HttpClient5EngineTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/client/HttpClient5EngineTest.java @@ -1,8 +1,8 @@ package cn.hutool.http.client; import cn.hutool.core.lang.Console; -import cn.hutool.http.meta.Method; import cn.hutool.http.client.engine.httpclient5.HttpClient5Engine; +import cn.hutool.http.meta.Method; import org.junit.Ignore; import org.junit.Test; @@ -18,6 +18,6 @@ public class HttpClient5EngineTest { final Response res = engine.send(req); Console.log(res.getStatus()); - Console.log(res.body()); + Console.log(res.bodyStr()); } } diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 34a39eb72..5bcec276f 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 851b85afd..aa50c611f 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 78911842d..e2fd4b9e4 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-poi diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 62c38a6de..83e805888 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 9bb0b5b37..8ef24bd07 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-socket diff --git a/hutool-swing/pom.xml b/hutool-swing/pom.xml index 7764fdc24..2901b1bac 100755 --- a/hutool-swing/pom.xml +++ b/hutool-swing/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool-swing diff --git a/pom.xml b/pom.xml index f06a4f123..1064a9236 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 6.0.0.M1 + 6.0.0.M2 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool From 5b5209e80156badb506bdad25beea9e9b76e99e8 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 13 Mar 2023 12:51:03 +0800 Subject: [PATCH 117/125] fix name --- .../client/cookie/GlobalCookieManager.java | 18 +++++----- .../client/engine/jdk/JdkClientEngine.java | 20 +++++------ ...Connection.java => JdkHttpConnection.java} | 34 +++++++++---------- ...putStream.java => JdkHttpInputStream.java} | 6 ++-- ...HttpResponse.java => JdkHttpResponse.java} | 12 +++---- .../java/cn/hutool/http/html/HtmlUtil.java | 2 +- 6 files changed, 46 insertions(+), 46 deletions(-) rename hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/{HttpConnection.java => JdkHttpConnection.java} (87%) rename hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/{HttpInputStream.java => JdkHttpInputStream.java} (93%) rename hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/{HttpResponse.java => JdkHttpResponse.java} (93%) mode change 100755 => 100644 diff --git a/hutool-http/src/main/java/cn/hutool/http/client/cookie/GlobalCookieManager.java b/hutool-http/src/main/java/cn/hutool/http/client/cookie/GlobalCookieManager.java index d48de5e7c..700c6583f 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/cookie/GlobalCookieManager.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/cookie/GlobalCookieManager.java @@ -3,7 +3,7 @@ package cn.hutool.http.client.cookie; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.map.MapUtil; import cn.hutool.core.net.url.URLUtil; -import cn.hutool.http.client.engine.jdk.HttpConnection; +import cn.hutool.http.client.engine.jdk.JdkHttpConnection; import java.io.IOException; import java.net.CookieManager; @@ -63,16 +63,16 @@ public class GlobalCookieManager { * @return Cookie信息列表 * @since 4.6.9 */ - public static List getCookies(final HttpConnection conn){ + public static List getCookies(final JdkHttpConnection conn){ return cookieManager.getCookieStore().get(getURI(conn)); } /** * 将本地存储的Cookie信息附带到Http请求中,不覆盖用户定义好的Cookie * - * @param conn {@link HttpConnection} + * @param conn {@link JdkHttpConnection} */ - public static void add(final HttpConnection conn) { + public static void add(final JdkHttpConnection conn) { if(null == cookieManager) { // 全局Cookie管理器关闭 return; @@ -93,9 +93,9 @@ public class GlobalCookieManager { /** * 存储响应的Cookie信息到本地 * - * @param conn {@link HttpConnection} + * @param conn {@link JdkHttpConnection} */ - public static void store(final HttpConnection conn) { + public static void store(final JdkHttpConnection conn) { store(conn, conn.headers()); } @@ -103,10 +103,10 @@ public class GlobalCookieManager { * 存储响应的Cookie信息到本地
                * 通过读取 * - * @param conn {@link HttpConnection} + * @param conn {@link JdkHttpConnection} * @param responseHeaders 头信息Map */ - public static void store(final HttpConnection conn, final Map> responseHeaders) { + public static void store(final JdkHttpConnection conn, final Map> responseHeaders) { if(null == cookieManager || MapUtil.isEmpty(responseHeaders)) { // 全局Cookie管理器关闭或头信息为空 return; @@ -124,7 +124,7 @@ public class GlobalCookieManager { * @param conn HttpConnection * @return URI */ - private static URI getURI(final HttpConnection conn){ + private static URI getURI(final JdkHttpConnection conn){ return URLUtil.toURI(conn.getUrl()); } } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java index 61d704b08..7689f13f2 100755 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkClientEngine.java @@ -27,7 +27,7 @@ import java.net.HttpURLConnection; public class JdkClientEngine implements ClientEngine { private ClientConfig config; - private HttpConnection conn; + private JdkHttpConnection conn; /** * 重定向次数计数器,内部使用 */ @@ -60,7 +60,7 @@ public class JdkClientEngine implements ClientEngine { * @param isAsync 是否异步,异步不会立即读取响应内容 * @return {@link Response} */ - public HttpResponse send(final Request message, final boolean isAsync) { + public JdkHttpResponse send(final Request message, final boolean isAsync) { initConn(message); try { doSend(message); @@ -116,15 +116,15 @@ public class JdkClientEngine implements ClientEngine { } /** - * 构建{@link HttpConnection} + * 构建{@link JdkHttpConnection} * * @param message {@link Request}消息 - * @return {@link HttpConnection} + * @return {@link JdkHttpConnection} */ - private HttpConnection buildConn(final Request message) { + private JdkHttpConnection buildConn(final Request message) { final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); - final HttpConnection conn = HttpConnection + final JdkHttpConnection conn = JdkHttpConnection .of(message.url().toURL(), config.getProxy()) .setConnectTimeout(config.getConnectionTimeout()) .setReadTimeout(config.getReadTimeout()) @@ -149,10 +149,10 @@ public class JdkClientEngine implements ClientEngine { * 调用转发,如果需要转发返回转发结果,否则返回{@code null} * * @param isAsync 最终请求是否异步 - * @return {@link HttpResponse},无转发返回 {@code null} + * @return {@link JdkHttpResponse},无转发返回 {@code null} */ - private HttpResponse sendRedirectIfPossible(final Request message, final boolean isAsync) { - final HttpConnection conn = this.conn; + private JdkHttpResponse sendRedirectIfPossible(final Request message, final boolean isAsync) { + final JdkHttpConnection conn = this.conn; // 手动实现重定向 if (message.maxRedirectCount() > 0) { final int code; @@ -176,7 +176,7 @@ public class JdkClientEngine implements ClientEngine { } // 最终页面 - return new HttpResponse(this.conn, true, message.charset(), isAsync, + return new JdkHttpResponse(this.conn, true, message.charset(), isAsync, isIgnoreResponseBody(message.method())); } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpConnection.java similarity index 87% rename from hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java rename to hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpConnection.java index 4f0ce59a2..997bd8acc 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpConnection.java @@ -25,7 +25,7 @@ import java.util.Map; * * @author Looly */ -public class HttpConnection implements HeaderOperation { +public class JdkHttpConnection implements HeaderOperation { private final URL url; private final Proxy proxy; @@ -38,7 +38,7 @@ public class HttpConnection implements HeaderOperation { * @param proxy 代理,无代理传{@code null} * @return HttpConnection */ - public static HttpConnection of(final String urlStr, final Proxy proxy) { + public static JdkHttpConnection of(final String urlStr, final Proxy proxy) { return of(URLUtil.toUrlForHttp(urlStr), proxy); } @@ -49,8 +49,8 @@ public class HttpConnection implements HeaderOperation { * @param proxy 代理,无代理传{@code null} * @return HttpConnection */ - public static HttpConnection of(final URL url, final Proxy proxy) { - return new HttpConnection(url, proxy); + public static JdkHttpConnection of(final URL url, final Proxy proxy) { + return new JdkHttpConnection(url, proxy); } // region --------------------------------------------------------------- Constructor @@ -61,7 +61,7 @@ public class HttpConnection implements HeaderOperation { * @param url URL * @param proxy 代理 */ - public HttpConnection(final URL url, final Proxy proxy) { + public JdkHttpConnection(final URL url, final Proxy proxy) { this.url = url; this.proxy = proxy; @@ -90,7 +90,7 @@ public class HttpConnection implements HeaderOperation { * @param method 请求方法 * @return 自己 */ - public HttpConnection setMethod(final Method method) { + public JdkHttpConnection setMethod(final Method method) { if (Method.POST.equals(method) // || Method.PUT.equals(method)// || Method.PATCH.equals(method)// @@ -147,7 +147,7 @@ public class HttpConnection implements HeaderOperation { * @return this * @see HttpURLConnection#setUseCaches(boolean) */ - public HttpConnection setDisableCache(final boolean isDisableCache) { + public JdkHttpConnection setDisableCache(final boolean isDisableCache) { this.conn.setUseCaches(!isDisableCache); return this; } @@ -158,7 +158,7 @@ public class HttpConnection implements HeaderOperation { * @param timeout 超时 * @return this */ - public HttpConnection setConnectTimeout(final int timeout) { + public JdkHttpConnection setConnectTimeout(final int timeout) { if (timeout > 0 && null != this.conn) { this.conn.setConnectTimeout(timeout); } @@ -172,7 +172,7 @@ public class HttpConnection implements HeaderOperation { * @param timeout 超时 * @return this */ - public HttpConnection setReadTimeout(final int timeout) { + public JdkHttpConnection setReadTimeout(final int timeout) { if (timeout > 0 && null != this.conn) { this.conn.setReadTimeout(timeout); } @@ -186,7 +186,7 @@ public class HttpConnection implements HeaderOperation { * @param timeout 超时时间 * @return this */ - public HttpConnection setConnectionAndReadTimeout(final int timeout) { + public JdkHttpConnection setConnectionAndReadTimeout(final int timeout) { setConnectTimeout(timeout); setReadTimeout(timeout); @@ -202,7 +202,7 @@ public class HttpConnection implements HeaderOperation { * @throws HttpException KeyManagementException和NoSuchAlgorithmException异常包装 * @since 6.0.0 */ - public HttpConnection setSSLInfo(final SSLInfo sslInfo) throws HttpException { + public JdkHttpConnection setSSLInfo(final SSLInfo sslInfo) throws HttpException { final HttpURLConnection conn = this.conn; if (conn instanceof HttpsURLConnection) { @@ -223,7 +223,7 @@ public class HttpConnection implements HeaderOperation { * @param blockSize 块大小(bytes数),0或小于0表示不设置Chuncked模式 * @return this */ - public HttpConnection setChunkedStreamingMode(final int blockSize) { + public JdkHttpConnection setChunkedStreamingMode(final int blockSize) { if (blockSize > 0) { conn.setChunkedStreamingMode(blockSize); } @@ -236,7 +236,7 @@ public class HttpConnection implements HeaderOperation { * @param isInstanceFollowRedirects 是否自定跳转 * @return this */ - public HttpConnection setInstanceFollowRedirects(final boolean isInstanceFollowRedirects) { + public JdkHttpConnection setInstanceFollowRedirects(final boolean isInstanceFollowRedirects) { conn.setInstanceFollowRedirects(isInstanceFollowRedirects); return this; } @@ -255,7 +255,7 @@ public class HttpConnection implements HeaderOperation { * @return HttpConnection */ @Override - public HttpConnection header(final String header, final String value, final boolean isOverride) { + public JdkHttpConnection header(final String header, final String value, final boolean isOverride) { if (null != this.conn) { if (isOverride) { this.conn.setRequestProperty(header, value); @@ -296,7 +296,7 @@ public class HttpConnection implements HeaderOperation { * @return this * @throws IOException IO异常 */ - public HttpConnection connect() throws IOException { + public JdkHttpConnection connect() throws IOException { if (null != this.conn) { this.conn.connect(); } @@ -309,7 +309,7 @@ public class HttpConnection implements HeaderOperation { * @return this * @since 4.6.0 */ - public HttpConnection disconnectQuietly() { + public JdkHttpConnection disconnectQuietly() { try { disconnect(); } catch (final Throwable e) { @@ -324,7 +324,7 @@ public class HttpConnection implements HeaderOperation { * * @return this */ - public HttpConnection disconnect() { + public JdkHttpConnection disconnect() { if (null != this.conn) { this.conn.disconnect(); } diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpInputStream.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpInputStream.java similarity index 93% rename from hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpInputStream.java rename to hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpInputStream.java index 3c3e2b8a6..cebb094f5 100644 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpInputStream.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpInputStream.java @@ -16,7 +16,7 @@ import java.io.InputStream; * * @author Looly */ -public class HttpInputStream extends InputStream { +public class JdkHttpInputStream extends InputStream { /** * 原始流 @@ -28,7 +28,7 @@ public class HttpInputStream extends InputStream { * * @param response 响应对象 */ - public HttpInputStream(final HttpResponse response) { + public JdkHttpInputStream(final JdkHttpResponse response) { init(response); } @@ -78,7 +78,7 @@ public class HttpInputStream extends InputStream { * * @param response 响应对象 */ - private void init(final HttpResponse response) { + private void init(final JdkHttpResponse response) { try { this.in = (response.status < HttpStatus.HTTP_BAD_REQUEST) ? response.httpConnection.getInputStream() : response.httpConnection.getErrorStream(); } catch (final IOException e) { diff --git a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpResponse.java b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpResponse.java old mode 100755 new mode 100644 similarity index 93% rename from hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpResponse.java rename to hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpResponse.java index d22002d39..18fac5c26 --- a/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/HttpResponse.java +++ b/hutool-http/src/main/java/cn/hutool/http/client/engine/jdk/JdkHttpResponse.java @@ -27,7 +27,7 @@ import java.util.Map.Entry; * * @author Looly */ -public class HttpResponse implements Response, Closeable { +public class JdkHttpResponse implements Response, Closeable { /** * 请求时的默认编码 @@ -49,7 +49,7 @@ public class HttpResponse implements Response, Closeable { /** * 持有连接对象 */ - protected HttpConnection httpConnection; + protected JdkHttpConnection httpConnection; /** * 响应状态码 */ @@ -58,13 +58,13 @@ public class HttpResponse implements Response, Closeable { /** * 构造 * - * @param httpConnection {@link HttpConnection} + * @param httpConnection {@link JdkHttpConnection} * @param ignoreEOFError 是否忽略响应读取时可能的EOF异常 * @param requestCharset 编码,从请求编码中获取默认编码 * @param isAsync 是否异步 * @param isIgnoreBody 是否忽略读取响应体 */ - protected HttpResponse(final HttpConnection httpConnection, final boolean ignoreEOFError, final Charset requestCharset, final boolean isAsync, final boolean isIgnoreBody) { + protected JdkHttpResponse(final JdkHttpConnection httpConnection, final boolean ignoreEOFError, final Charset requestCharset, final boolean isAsync, final boolean isIgnoreBody) { this.httpConnection = httpConnection; this.ignoreEOFError = ignoreEOFError; this.requestCharset = requestCharset; @@ -112,7 +112,7 @@ public class HttpResponse implements Response, Closeable { * * @return this */ - public HttpResponse sync() { + public JdkHttpResponse sync() { if (null != this.body) { this.body.sync(); } @@ -259,7 +259,7 @@ public class HttpResponse implements Response, Closeable { // 获取响应内容流 if (false == isIgnoreBody) { - this.body = new ResponseBody(this, new HttpInputStream(this), isAsync, this.ignoreEOFError); + this.body = new ResponseBody(this, new JdkHttpInputStream(this), isAsync, this.ignoreEOFError); } } // ---------------------------------------------------------------- Private method end diff --git a/hutool-http/src/main/java/cn/hutool/http/html/HtmlUtil.java b/hutool-http/src/main/java/cn/hutool/http/html/HtmlUtil.java index 710dfb6b8..51abacd31 100755 --- a/hutool-http/src/main/java/cn/hutool/http/html/HtmlUtil.java +++ b/hutool-http/src/main/java/cn/hutool/http/html/HtmlUtil.java @@ -29,7 +29,7 @@ public class HtmlUtil { /** * script标签正则 */ - public static final Pattern RE_SCRIPT = Pattern.compile("<[\\s]*?script[^>]*?>.*?<[\\s]*?\\/[\\s]*?script[\\s]*?>", Pattern.CASE_INSENSITIVE); + public static final Pattern RE_SCRIPT = Pattern.compile("<\\s*?script[^>]*?>.*?<\\s*?/\\s*?script\\s*?>", Pattern.CASE_INSENSITIVE); /** * 正则:匹配meta标签的编码信息 */ From a1f8a9e09345dea6455bf57c2b2dadceef45df8c Mon Sep 17 00:00:00 2001 From: youzipi Date: Mon, 13 Mar 2023 16:22:52 +0800 Subject: [PATCH 118/125] feat: CollUtil add groupByFunc --- .../cn/hutool/core/collection/CollUtil.java | 14 +++++++----- .../hutool/core/collection/CollUtilTest.java | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 3ac2129fd..a660dd112 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -2023,8 +2023,12 @@ public class CollUtil { * @return 分组列表 */ public static List> groupByField(final Collection collection, final String fieldName) { + return groupByFunc(collection, t -> BeanUtil.getFieldValue(t, fieldName)); + } + + public static List> groupByFunc(final Collection collection, final Function getter) { return group(collection, new Hash32() { - private final List fieldNameList = new ArrayList<>(); + private final List hashValList = new ArrayList<>(); @Override public int hash32(final T t) { @@ -2032,11 +2036,11 @@ public class CollUtil { // 非Bean放在同一子分组中 return 0; } - final Object value = FieldUtil.getFieldValue(t, fieldName); - final int hash = fieldNameList.indexOf(value); + final D value = getter.apply(t); + final int hash = hashValList.indexOf(value); if (hash < 0) { - fieldNameList.add(value); - return fieldNameList.size() - 1; + hashValList.add(value); + return hashValList.size() - 1; } else { return hash; } diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index fc5f4a2b4..acb7cf236 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -427,6 +427,26 @@ public class CollUtilTest { Assert.assertEquals("李四", groupByField.get(1).get(0).getName()); } + @Test + public void groupByFuncTest() { + final List list = ListUtil.of(new TestBean("张三", 12), new TestBean("李四", 13), new TestBean("王五", 12)); + final List> groupByField = CollUtil.groupByFunc(list, TestBean::getAge); + Assert.assertEquals("张三", groupByField.get(0).get(0).getName()); + Assert.assertEquals("王五", groupByField.get(0).get(1).getName()); + + Assert.assertEquals("李四", groupByField.get(1).get(0).getName()); + } + + @Test + public void groupByFunc2Test() { + final List list = ListUtil.of(new TestBean("张三", 12), new TestBean("李四", 13), new TestBean("王五", 12)); + final List> groupByField = CollUtil.groupByFunc(list, a -> a.getAge() > 12); + Assert.assertEquals("张三", groupByField.get(0).get(0).getName()); + Assert.assertEquals("王五", groupByField.get(0).get(1).getName()); + + Assert.assertEquals("李四", groupByField.get(1).get(0).getName()); + } + @Test public void sortByPropertyTest() { final List list = ListUtil.of( @@ -854,7 +874,7 @@ public class CollUtilTest { final List result = CollUtil.subtractToList(list1, list2); Assert.assertEquals(1, result.size()); - Assert.assertEquals(1L, (long)result.get(0)); + Assert.assertEquals(1L, (long) result.get(0)); } @Test From e4999ca6f6966769a4e8c944aa4aacef3b5d91e0 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 14 Mar 2023 19:07:24 +0800 Subject: [PATCH 119/125] fix code --- .../cn/hutool/core/collection/CollUtil.java | 27 ++-- .../cn/hutool/core/date/CalendarUtil.java | 128 ++++++++---------- .../java/cn/hutool/core/date/DateUtil.java | 36 ++--- .../java/cn/hutool/core/date/StopWatch.java | 4 +- 4 files changed, 87 insertions(+), 108 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index a660dd112..19a76b752 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -363,7 +363,7 @@ public class CollUtil { * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]
                * 结果:[a, b, c],此结果中只保留了一个c * - * @param 集合元素类型 + * @param 集合元素类型 * @param colls 集合列表 * @return 交集的集合,返回 {@link LinkedHashSet} * @since 5.3.9 @@ -2015,7 +2015,7 @@ public class CollUtil { } /** - * 根据元素的指定字段名分组,非Bean都放在第一个分组中 + * 根据元素的指定字段值分组,非Bean都放在第一个分组中 * * @param 元素类型 * @param collection 集合 @@ -2026,7 +2026,19 @@ public class CollUtil { return groupByFunc(collection, t -> BeanUtil.getFieldValue(t, fieldName)); } - public static List> groupByFunc(final Collection collection, final Function getter) { + /** + * 根据元素的指定字段值分组,非Bean都放在第一个分组中
                + * 例如:{@code + * CollUtil.groupByFunc(list, TestBean::getAge) + * } + * + * @param 元素类型 + * @param collection 集合 + * @param getter getter方法引用 + * @return 分组列表 + * @since 6.0.0 + */ + public static List> groupByFunc(final Collection collection, final Function getter) { return group(collection, new Hash32() { private final List hashValList = new ArrayList<>(); @@ -2036,14 +2048,13 @@ public class CollUtil { // 非Bean放在同一子分组中 return 0; } - final D value = getter.apply(t); - final int hash = hashValList.indexOf(value); + final Object value = getter.apply(t); + int hash = hashValList.indexOf(value); if (hash < 0) { hashValList.add(value); - return hashValList.size() - 1; - } else { - return hash; + hash = hashValList.size() - 1; } + return hash; } }); } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index efec80bd6..6c042e540 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -2,12 +2,12 @@ package cn.hutool.core.date; import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.convert.NumberChineseFormatter; +import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.date.format.parser.DateParser; import cn.hutool.core.date.format.parser.FastDateParser; -import cn.hutool.core.date.format.GlobalCustomFormat; import cn.hutool.core.date.format.parser.PositionDateParser; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ObjUtil; import javax.xml.datatype.XMLGregorianCalendar; import java.text.ParsePosition; @@ -15,7 +15,6 @@ import java.time.Instant; import java.time.LocalDateTime; import java.util.Calendar; import java.util.Date; -import java.util.LinkedHashSet; import java.util.Locale; import java.util.TimeZone; @@ -74,7 +73,7 @@ public class CalendarUtil { /** * 转换为Calendar对象 * - * @param millis 时间戳 + * @param millis 时间戳 * @param timeZone 时区 * @return Calendar对象 * @since 5.7.22 @@ -105,6 +104,8 @@ public class CalendarUtil { return Calendar.PM == calendar.get(Calendar.AM_PM); } + // region ----- modify 时间修改 + /** * 修改日期为某个时间字段起始时间 * @@ -355,6 +356,7 @@ public class CalendarUtil { public static Calendar endOfYear(final Calendar calendar) { return ceiling(calendar, DateField.YEAR); } + // endregion /** * 比较两个日期是否为同一天 @@ -375,8 +377,8 @@ public class CalendarUtil { /** * 比较两个日期是否为同一周 * - * @param cal1 日期1 - * @param cal2 日期2 + * @param cal1 日期1 + * @param cal2 日期2 * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日 * @return 是否为同一周 * @since 5.7.21 @@ -443,28 +445,6 @@ public class CalendarUtil { return date1.getTimeInMillis() == date2.getTimeInMillis(); } - /** - * 获得指定日期区间内的年份和季度
                - * - * @param startDate 起始日期(包含) - * @param endDate 结束日期(包含) - * @return 季度列表 ,元素类似于 20132 - * @since 4.1.15 - */ - public static LinkedHashSet yearAndQuarter(long startDate, final long endDate) { - final LinkedHashSet quarters = new LinkedHashSet<>(); - final Calendar cal = calendar(startDate); - while (startDate <= endDate) { - // 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环 - quarters.add(yearAndQuarter(cal)); - - cal.add(Calendar.MONTH, 3); - startDate = cal.getTimeInMillis(); - } - - return quarters; - } - /** * 获得指定日期年份和季度
                * 格式:[20131]表示2013年第一季度 @@ -637,51 +617,7 @@ public class CalendarUtil { return result.toString(); } - /** - * 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄 - * - * @param birthday 生日 - * @param dateToCompare 需要对比的日期 - * @return 年龄 - */ - protected static int age(final long birthday, final long dateToCompare) { - if (birthday > dateToCompare) { - throw new IllegalArgumentException("Birthday is after dateToCompare!"); - } - - final Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(dateToCompare); - - final int year = cal.get(Calendar.YEAR); - final int month = cal.get(Calendar.MONTH); - final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); - final boolean isLastDayOfMonth = dayOfMonth == cal.getActualMaximum(Calendar.DAY_OF_MONTH); - - cal.setTimeInMillis(birthday); - int age = year - cal.get(Calendar.YEAR); - //当前日期,则为0岁 - if (age == 0){ - return 0; - } - - final int monthBirth = cal.get(Calendar.MONTH); - if (month == monthBirth) { - - final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); - final boolean isLastDayOfMonthBirth = dayOfMonthBirth == cal.getActualMaximum(Calendar.DAY_OF_MONTH); - // issue#I6E6ZG,法定生日当天不算年龄,从第二天开始计算 - if ((false == isLastDayOfMonth || false == isLastDayOfMonthBirth) && dayOfMonth <= dayOfMonthBirth) { - // 如果生日在当月,但是未达到生日当天的日期,年龄减一 - age--; - } - } else if (month < monthBirth) { - // 如果当前月份未达到生日的月份,年龄计算减一 - age--; - } - - return age; - } - + // region ----- parse /** * 通过给定的日期格式解析日期时间字符串。
                * 传入的日期格式会逐个尝试,直到解析成功,返回{@link Calendar}对象,否则抛出{@link DateException}异常。 @@ -782,4 +718,50 @@ public class CalendarUtil { return parser.parse(StrUtil.str(str), new ParsePosition(0), calendar) ? calendar : null; } + // endregion + + /** + * 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄 + * + * @param birthday 生日 + * @param dateToCompare 需要对比的日期 + * @return 年龄 + */ + protected static int age(final long birthday, final long dateToCompare) { + if (birthday > dateToCompare) { + throw new IllegalArgumentException("Birthday is after dateToCompare!"); + } + + final Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(dateToCompare); + + final int year = cal.get(Calendar.YEAR); + final int month = cal.get(Calendar.MONTH); + final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); + final boolean isLastDayOfMonth = dayOfMonth == cal.getActualMaximum(Calendar.DAY_OF_MONTH); + + cal.setTimeInMillis(birthday); + int age = year - cal.get(Calendar.YEAR); + //当前日期,则为0岁 + if (age == 0) { + return 0; + } + + final int monthBirth = cal.get(Calendar.MONTH); + if (month == monthBirth) { + + final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); + final boolean isLastDayOfMonthBirth = dayOfMonthBirth == cal.getActualMaximum(Calendar.DAY_OF_MONTH); + // issue#I6E6ZG,法定生日当天不算年龄,从第二天开始计算 + if ((false == isLastDayOfMonth || false == isLastDayOfMonthBirth) && dayOfMonth <= dayOfMonthBirth) { + // 如果生日在当月,但是未达到生日当天的日期,年龄减一 + age--; + } + } else if (month < monthBirth) { + // 如果当前月份未达到生日的月份,年龄计算减一 + age--; + } + + return age; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index dfed3e3db..eb9469610 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -513,21 +513,7 @@ public class DateUtil extends CalendarUtil { return yearAndQuarter(calendar(date)); } - /** - * 获得指定日期区间内的年份和季节
                - * - * @param startDate 起始日期(包含) - * @param endDate 结束日期(包含) - * @return 季度列表 ,元素类似于 20132 - */ - public static LinkedHashSet yearAndQuarter(final Date startDate, final Date endDate) { - if (startDate == null || endDate == null) { - return new LinkedHashSet<>(0); - } - return yearAndQuarter(startDate.getTime(), endDate.getTime()); - } - // ------------------------------------ Format start ---------------------------------------------- - + // region ----- format /** * 格式化日期时间
                * 格式 yyyy-MM-dd HH:mm:ss @@ -696,10 +682,9 @@ public class DateUtil extends CalendarUtil { return CalendarUtil.formatChineseDate(CalendarUtil.calendar(date), withTime); } - // ------------------------------------ Format end ---------------------------------------------- - - // ------------------------------------ Parse start ---------------------------------------------- + // endregion + // region ----- parse /** * 构建DateTime对象 * @@ -853,10 +838,9 @@ public class DateUtil extends CalendarUtil { // 没有更多匹配的时间格式 throw new DateException("No format fit for date String [{}] !", dateStr); } - // ------------------------------------ Parse end ---------------------------------------------- - - // ------------------------------------ Offset start ---------------------------------------------- + // endregion + // region ----- offset /** * 修改日期为某个时间字段起始时间 * @@ -1096,7 +1080,6 @@ public class DateUtil extends CalendarUtil { public static DateTime endOfYear(final Date date) { return new DateTime(endOfYear(calendar(date))); } - // --------------------------------------------------- Offset for now /** * 昨天 @@ -1243,9 +1226,9 @@ public class DateUtil extends CalendarUtil { public static DateTime offset(final Date date, final DateField dateField, final int offset) { return dateNew(date).offset(dateField, offset); } + // endregion - // ------------------------------------ Offset end ---------------------------------------------- - + // region ----- between /** * 判断两个日期相差的时长,只保留绝对值 * @@ -1351,7 +1334,9 @@ public class DateUtil extends CalendarUtil { public static long betweenYear(final Date beginDate, final Date endDate, final boolean isReset) { return new DateBetween(beginDate, endDate).betweenYear(isReset); } + // endregion + // region ----- formatBetween /** * 格式化日期间隔输出 * @@ -1397,6 +1382,7 @@ public class DateUtil extends CalendarUtil { public static String formatBetween(final long betweenMs) { return new BetweenFormatter(betweenMs, BetweenFormatter.Level.MILLISECOND).format(); } + // endregion /** * 当前日期是否在日期指定范围内
                @@ -1992,7 +1978,7 @@ public class DateUtil extends CalendarUtil { * @return 单位简写名称 * @since 5.7.16 */ - public static String getShotName(final TimeUnit unit) { + public static String getShortName(final TimeUnit unit) { switch (unit) { case NANOSECONDS: return "ns"; diff --git a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java index 6213e5b87..d748bf201 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java @@ -352,7 +352,7 @@ public class StopWatch { unit = TimeUnit.NANOSECONDS; } return StrUtil.format("StopWatch '{}': running time = {} {}", - this.id, getTotal(unit), DateUtil.getShotName(unit)); + this.id, getTotal(unit), DateUtil.getShortName(unit)); } /** @@ -382,7 +382,7 @@ public class StopWatch { sb.append("No task info kept"); } else { sb.append("---------------------------------------------").append(FileUtil.getLineSeparator()); - sb.append(DateUtil.getShotName(unit)).append(" % Task name").append(FileUtil.getLineSeparator()); + sb.append(DateUtil.getShortName(unit)).append(" % Task name").append(FileUtil.getLineSeparator()); sb.append("---------------------------------------------").append(FileUtil.getLineSeparator()); final NumberFormat nf = NumberFormat.getNumberInstance(); From 6cd802e9accd623f180112587f3f45cebf5a97d8 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 14 Mar 2023 20:26:26 +0800 Subject: [PATCH 120/125] fix code --- .../java/cn/hutool/core/date/DatePattern.java | 69 ++++++++++--------- .../java/cn/hutool/core/date/TimeUtil.java | 7 +- .../java/cn/hutool/core/date/ZoneUtil.java | 9 +++ .../date/format/parser/UTCDateParser.java | 18 ++--- .../cn/hutool/core/text/split/SplitUtil.java | 8 ++- .../cn/hutool/core/date/DateTimeTest.java | 4 +- .../cn/hutool/core/date/DateUtilTest.java | 28 +------- .../cn/hutool/core/date/Issue2981Test.java | 22 ++++++ .../cn/hutool/core/date/TimeUtilTest.java | 16 ++++- .../core/text/split/StrSplitterTest.java | 10 +++ 10 files changed, 108 insertions(+), 83 deletions(-) create mode 100755 hutool-core/src/test/java/cn/hutool/core/date/Issue2981Test.java diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java b/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java index b59eea778..87edc3e2b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java @@ -31,7 +31,7 @@ import java.util.regex.Pattern; *
              • yyyy-MM-dd HH:mm:ss.SSS 示例:2022-08-05 12:59:59.559
              • *
              • yyyy-MM-dd HH:mm:ss.SSSZ 示例:2022-08-05 12:59:59.559+0800【东八区中国时区】、2022-08-05 04:59:59.559+0000【冰岛0时区】, 年月日 时分秒 毫秒 时区
              • *
              • yyyy-MM-dd HH:mm:ss.SSSz 示例:2022-08-05 12:59:59.559UTC【世界标准时间=0时区】、2022-08-05T12:59:59.599GMT【冰岛0时区】、2022-08-05T12:59:59.599CST【东八区中国时区】、2022-08-23T03:45:00.599EDT【美国东北纽约时间,-0400】 ,年月日 时分秒 毫秒 时区
              • - *
              • yyyy-MM-dd'T'HH:mm:ss.SSS'Z' 示例:2022-08-05T12:59:59.559Z, 其中:''单引号表示转义字符,T:分隔符,Z:一般值UTC,0时区的时间含义
              • + *
              • yyyy-MM-dd'T'HH:mm:ss.SSS'Z' 示例:2022-08-05T12:59:59.559Z, 其中:''单引号表示转义字符,T:分隔符,Z:一般指UTC,0时区的时间含义
              • *
              • yyyy-MM-dd'T'HH:mm:ss.SSSZ 示例:2022-08-05T11:59:59.559+0800, 其中:Z,表示时区
              • *
              • yyyy-MM-dd'T'HH:mm:ss.SSSX 示例:2022-08-05T12:59:59.559+08, 其中:X:两位时区,+08表示:东8区,中国时区
              • *
              • yyyy-MM-dd'T'HH:mm:ss.SSSXX 示例:2022-08-05T12:59:59.559+0800, 其中:XX:四位时区
              • @@ -61,7 +61,7 @@ import java.util.regex.Pattern; * 如:“09:30 UTC”表示为“09:30Z”或“T0930Z”,其中:Z 是 +00:00 的缩写,意思是 UTC(零时分秒的偏移量). *

                *
                  - *
                • yyyy-MM-dd'T'HH:mm:ssZ
                • + *
                • yyyy-MM-dd'T'HH:mm:ss'Z'
                • *
                • 2022-08-23T15:20:46UTC
                • *
                • 2022-08-23T15:20:46 UTC
                • *
                • 2022-08-23T15:20:46+0000
                • @@ -189,15 +189,15 @@ public class DatePattern { /** * ISO8601日期时间格式,精确到毫秒:yyyy-MM-dd HH:mm:ss,SSS */ - public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; + public static final String NORM_DATETIME_COMMA_MS_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; /** * ISO8601日期时间格式,精确到毫秒 {@link FastDateFormat}:yyyy-MM-dd HH:mm:ss,SSS */ - public static final FastDateFormat ISO8601_FORMAT = FastDateFormat.getInstance(ISO8601_PATTERN); + public static final FastDateFormat NORM_DATETIME_COMMA_MS_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_COMMA_MS_PATTERN); /** * 标准日期格式 {@link DateTimeFormatter}:yyyy-MM-dd HH:mm:ss,SSS */ - public static final DateTimeFormatter ISO8601_FORMATTER = createFormatter(ISO8601_PATTERN); + public static final DateTimeFormatter NORM_DATETIME_COMMA_MS_FORMATTER = createFormatter(NORM_DATETIME_COMMA_MS_PATTERN); /** * 标准日期格式:yyyy年MM月dd日 @@ -286,8 +286,7 @@ public class DatePattern { .toFormatter(); // endregion - // region Others - //================================================== Others ================================================== + // region ----- Others /** * HTTP头中日期时间格式:EEE, dd MMM yyyy HH:mm:ss z */ @@ -307,76 +306,78 @@ public class DatePattern { public static final FastDateFormat JDK_DATETIME_FORMAT = FastDateFormat.getInstance(JDK_DATETIME_PATTERN, Locale.US); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ss + * ISO8601日期时间:yyyy-MM-dd'T'HH:mm:ss
                  + * 按照ISO8601规范,默认使用T分隔日期和时间,末尾不加Z表示当地时区 */ - public static final String UTC_SIMPLE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; + public static final String ISO8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss + * ISO8601日期时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss */ - public static final FastDateFormat UTC_SIMPLE_FORMAT = FastDateFormat.getInstance(UTC_SIMPLE_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat ISO8601_FORMAT = FastDateFormat.getInstance(ISO8601_PATTERN); /** * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSS */ - public static final String UTC_SIMPLE_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + public static final String ISO8601_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; /** * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSS */ - public static final FastDateFormat UTC_SIMPLE_MS_FORMAT = FastDateFormat.getInstance(UTC_SIMPLE_MS_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat ISO8601_MS_FORMAT = FastDateFormat.getInstance(ISO8601_MS_PATTERN); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ss'Z' + * UTC时间:yyyy-MM-dd'T'HH:mm:ss'Z'
                  + * 按照ISO8601规范,后缀加Z表示UTC时间 */ public static final String UTC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss'Z' + * ISO8601时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss'Z' */ - public static final FastDateFormat UTC_FORMAT = FastDateFormat.getInstance(UTC_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat UTC_FORMAT = FastDateFormat.getInstance(UTC_PATTERN, ZoneUtil.ZONE_UTC); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ssZ + * ISO8601时间:yyyy-MM-dd'T'HH:mm:ssZ,Z表示一个时间偏移,如+0800 */ - public static final String UTC_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ"; + public static final String ISO8601_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssZ + * ISO8601时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssZ,Z表示一个时间偏移,如+0800 */ - public static final FastDateFormat UTC_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat ISO8601_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(ISO8601_WITH_ZONE_OFFSET_PATTERN); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ssXXX + * ISO8601时间:yyyy-MM-dd'T'HH:mm:ssXXX */ - public static final String UTC_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssXXX"; + public static final String ISO8601_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssXXX"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssXXX + * ISO8601时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssXXX */ - public static final FastDateFormat UTC_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_WITH_XXX_OFFSET_PATTERN); + public static final FastDateFormat ISO8601_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(ISO8601_WITH_XXX_OFFSET_PATTERN); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + * ISO8601时间:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' */ public static final String UTC_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + * ISO8601时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' */ - public static final FastDateFormat UTC_MS_FORMAT = FastDateFormat.getInstance(UTC_MS_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat UTC_MS_FORMAT = FastDateFormat.getInstance(UTC_MS_PATTERN, ZoneUtil.ZONE_UTC); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSSZ + * ISO8601时间:yyyy-MM-dd'T'HH:mm:ss.SSSZ */ - public static final String UTC_MS_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + public static final String ISO8601_MS_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; /** - * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSSZ + * ISO8601时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSSZ */ - public static final FastDateFormat UTC_MS_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat ISO8601_MS_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(ISO8601_MS_WITH_ZONE_OFFSET_PATTERN); /** - * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSSXXX + * ISO8601时间:yyyy-MM-dd'T'HH:mm:ss.SSSXXX */ - public static final String UTC_MS_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; + public static final String ISO8601_MS_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; /** * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSSXXX */ - public static final FastDateFormat UTC_MS_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_XXX_OFFSET_PATTERN); + public static final FastDateFormat ISO8601_MS_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(ISO8601_MS_WITH_XXX_OFFSET_PATTERN); // endregion /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java index b045f2838..291578024 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java @@ -23,11 +23,6 @@ import java.util.function.Function; * @since 6.0.0 */ public class TimeUtil extends TemporalAccessorUtil { - /** - * UTC 的 ZoneID - */ - public static final ZoneId ZONE_ID_UTC = ZoneId.of("UTC"); - /** * 当前时间,默认时区 * @@ -53,7 +48,7 @@ public class TimeUtil extends TemporalAccessorUtil { * @return {@link LocalDateTime} */ public static LocalDateTime ofUTC(final Instant instant) { - return of(instant, ZONE_ID_UTC); + return of(instant, ZoneUtil.ZONE_ID_UTC); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/ZoneUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/ZoneUtil.java index 008e648cc..2f11af19a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/ZoneUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/ZoneUtil.java @@ -11,6 +11,15 @@ import java.util.TimeZone; */ public class ZoneUtil { + /** + * UTC 的 ZoneID + */ + public static final TimeZone ZONE_UTC = TimeZone.getTimeZone("UTC"); + /** + * UTC 的 TimeZone + */ + public static final ZoneId ZONE_ID_UTC = ZONE_UTC.toZoneId(); + /** * {@link ZoneId}转换为{@link TimeZone},{@code null}则返回系统默认值 * diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java index ed295d133..7b3596990 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java @@ -61,10 +61,10 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { if (StrUtil.contains(source, CharUtil.DOT)) { // 带毫秒,格式类似:2018-09-13T05:34:31.999+08:00 source = normalizeMillSeconds(source, ".", "+"); - return new DateTime(source, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT); + return new DateTime(source, DatePattern.ISO8601_MS_WITH_XXX_OFFSET_FORMAT); } else { // 格式类似:2018-09-13T05:34:31+08:00 - return new DateTime(source, DatePattern.UTC_WITH_XXX_OFFSET_FORMAT); + return new DateTime(source, DatePattern.ISO8601_WITH_XXX_OFFSET_FORMAT); } } else if(ReUtil.contains("-\\d{2}:?00", source)){ // Issue#2612,类似 2022-09-14T23:59:00-08:00 或者 2022-09-14T23:59:00-0800 @@ -78,22 +78,22 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { if (StrUtil.contains(source, CharUtil.DOT)) { // 带毫秒,格式类似:2018-09-13T05:34:31.999-08:00 source = normalizeMillSeconds(source, ".", "-"); - return new DateTime(source, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT); + return new DateTime(source, DatePattern.ISO8601_MS_WITH_XXX_OFFSET_FORMAT); } else { // 格式类似:2018-09-13T05:34:31-08:00 - return new DateTime(source, DatePattern.UTC_WITH_XXX_OFFSET_FORMAT); + return new DateTime(source, DatePattern.ISO8601_WITH_XXX_OFFSET_FORMAT); } } else { - if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 2) { + if (length == DatePattern.ISO8601_PATTERN.length() - 2) { // 格式类似:2018-09-13T05:34:31 - return new DateTime(source, DatePattern.UTC_SIMPLE_FORMAT); - } else if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 5) { + return new DateTime(source, DatePattern.ISO8601_FORMAT); + } else if (length == DatePattern.ISO8601_PATTERN.length() - 5) { // 格式类似:2018-09-13T05:34 - return new DateTime(source + ":00", DatePattern.UTC_SIMPLE_FORMAT); + return new DateTime(source + ":00", DatePattern.ISO8601_FORMAT); } else if (StrUtil.contains(source, CharUtil.DOT)) { // 可能为: 2021-03-17T06:31:33.99 source = normalizeMillSeconds(source, ".", null); - return new DateTime(source, DatePattern.UTC_SIMPLE_MS_FORMAT); + return new DateTime(source, DatePattern.ISO8601_MS_FORMAT); } } // 没有更多匹配的时间格式 diff --git a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java index e6505b214..0836700b4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitUtil.java @@ -1,5 +1,6 @@ package cn.hutool.core.text.split; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.regex.PatternPool; import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.finder.CharFinder; @@ -302,7 +303,8 @@ public class SplitUtil { /** * 切分字符串
                  - * 如果为空字符串或者null 则返回空集合 + * 如果提供的字符串为{@code null},则返回一个空的{@link ArrayList}
                  + * 如果提供的字符串为"",则当ignoreEmpty时返回空的{@link ArrayList},否则返回只有一个""元素的{@link ArrayList} * * @param text 被切分的字符串 * @param separator 分隔符字符串 @@ -314,8 +316,10 @@ public class SplitUtil { * @since 3.2.1 */ public static List split(final CharSequence text, final String separator, final int limit, final boolean isTrim, final boolean ignoreEmpty, final boolean ignoreCase) { - if (StrUtil.isEmpty(text)) { + if(null == text){ return new ArrayList<>(0); + } else if (0 == text.length()) { + return ignoreEmpty ? new ArrayList<>(0) : ListUtil.of(StrUtil.EMPTY); } final SplitIter splitIter = new SplitIter(text, new StrFinder(separator, ignoreCase), limit, ignoreEmpty); return splitIter.toList(isTrim); diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateTimeTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateTimeTest.java index 8729ec3ec..4a9122342 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateTimeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateTimeTest.java @@ -109,10 +109,10 @@ public class DateTimeTest { public void toStringTest2() { final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); - String dateStr = dateTime.toString(DatePattern.UTC_WITH_ZONE_OFFSET_PATTERN); + String dateStr = dateTime.toString(DatePattern.ISO8601_WITH_ZONE_OFFSET_PATTERN); Assert.assertEquals("2017-01-05T12:34:23+0800", dateStr); - dateStr = dateTime.toString(DatePattern.UTC_WITH_XXX_OFFSET_PATTERN); + dateStr = dateTime.toString(DatePattern.ISO8601_WITH_XXX_OFFSET_PATTERN); Assert.assertEquals("2017-01-05T12:34:23+08:00", dateStr); } diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 9d2bafeff..167c59c8e 100755 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1,6 +1,5 @@ package cn.hutool.core.date; -import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.BetweenFormatter.Level; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Console; @@ -14,15 +13,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.TimeZone; +import java.util.*; /** * 时间工具单元测试
                  @@ -796,23 +787,6 @@ public class DateUtilTest { Assert.assertEquals(0, DateUtil.compare(date11, date22, DatePattern.NORM_MONTH_PATTERN)); } - @Test - public void yearAndQTest() { - final String yearAndQuarter = DateUtil.yearAndQuarter(DateUtil.parse("2018-12-01")); - Assert.assertEquals("20184", yearAndQuarter); - - final LinkedHashSet yearAndQuarters = DateUtil.yearAndQuarter(DateUtil.parse("2018-09-10"), DateUtil.parse("2018-12-20")); - final List list = ListUtil.of(false, yearAndQuarters); - Assert.assertEquals(2, list.size()); - Assert.assertEquals("20183", list.get(0)); - Assert.assertEquals("20184", list.get(1)); - - final LinkedHashSet yearAndQuarters2 = DateUtil.yearAndQuarter(DateUtil.parse("2018-10-10"), DateUtil.parse("2018-12-10")); - final List list2 = ListUtil.of(false, yearAndQuarters2); - Assert.assertEquals(1, list2.size()); - Assert.assertEquals("20184", list2.get(0)); - } - @Test public void formatHttpDateTest() { final String formatHttpDate = DateUtil.formatHttpDate(DateUtil.parse("2019-01-02 22:32:01")); diff --git a/hutool-core/src/test/java/cn/hutool/core/date/Issue2981Test.java b/hutool-core/src/test/java/cn/hutool/core/date/Issue2981Test.java new file mode 100755 index 000000000..432459ff0 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/date/Issue2981Test.java @@ -0,0 +1,22 @@ +package cn.hutool.core.date; + +import org.junit.Assert; +import org.junit.Test; + +public class Issue2981Test { + /** + * https://github.com/dromara/hutool/issues/2981
                  + * 按照ISO8601规范,以Z结尾表示UTC时间,否则为当地时间 + */ + @SuppressWarnings("DataFlowIssue") + @Test + public void parseUTCTest() { + final String str1 = "2019-01-01T00:00:00.000Z"; + final String str2 = "2019-01-01T00:00:00.000"; + final String str3 = "2019-01-01 00:00:00.000"; + + Assert.assertEquals(1546300800000L, DateUtil.parse(str1).getTime()); + Assert.assertEquals(1546272000000L, DateUtil.parse(str2).getTime()); + Assert.assertEquals(1546272000000L, DateUtil.parse(str3).getTime()); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java index 75f8f8aa1..3ff41ae9f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/TimeUtilTest.java @@ -27,12 +27,22 @@ public class TimeUtilTest { final String dateStr = "2020-01-23T12:23:56"; final DateTime dt = DateUtil.parse(dateStr); - LocalDateTime of = TimeUtil.of(dt); + final LocalDateTime of = TimeUtil.of(dt); Assert.assertNotNull(of); Assert.assertEquals(dateStr, of.toString()); + } - of = TimeUtil.ofUTC(dt.getTime()); - Assert.assertEquals(dateStr, of.toString()); + @SuppressWarnings("DataFlowIssue") + @Test + public void ofUTCTest() { + final String dateStr = "2020-01-23T12:23:56Z"; + final DateTime dt = DateUtil.parse(dateStr); + + final LocalDateTime of = TimeUtil.of(dt); + final LocalDateTime of2 = TimeUtil.ofUTC(dt.getTime()); + Assert.assertNotNull(of); + Assert.assertNotNull(of2); + Assert.assertEquals(of, of2); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/text/split/StrSplitterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/split/StrSplitterTest.java index 0cea8de30..69a059374 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/split/StrSplitterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/split/StrSplitterTest.java @@ -1,5 +1,6 @@ package cn.hutool.core.text.split; +import cn.hutool.core.lang.Console; import org.junit.Assert; import org.junit.Test; @@ -59,16 +60,25 @@ public class StrSplitterTest { final String str = ""; final String[] split = str.split(","); final String[] strings = SplitUtil.splitToArray(str, ",", -1, false, false); + Assert.assertNotNull(strings); Assert.assertArrayEquals(split, strings); + + final String[] strings2 = SplitUtil.splitToArray(str, ",", -1, false, true); + Assert.assertEquals(0, strings2.length); } + @SuppressWarnings("ConstantValue") @Test public void splitNullTest(){ final String str = null; final String[] strings = SplitUtil.splitToArray(str, ",", -1, false, false); Assert.assertNotNull(strings); Assert.assertEquals(0, strings.length); + + final String[] strings2 = SplitUtil.splitToArray(str, ",", -1, false, true); + Assert.assertNotNull(strings2); + Assert.assertEquals(0, strings2.length); } /** From 7adb2d610b252ef55f32c0bddda992eef63961e1 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 14 Mar 2023 20:33:08 +0800 Subject: [PATCH 121/125] fix test --- .../src/test/java/cn/hutool/json/JSONUtilTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index e87bda2b1..d0e52df3b 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -35,12 +35,12 @@ public class JSONUtilTest { } /** - * 数字解析为JSONObject忽略 + * 数字解析为JSONArray报错 */ - @Test + @Test(expected = JSONException.class) public void parseNumberTest2() { final JSONObject json = JSONUtil.parseObj(123L); - Assert.assertEquals(new JSONObject(), json); + Assert.assertNotNull(json); } @Test @@ -85,7 +85,7 @@ public class JSONUtilTest { @Test public void toJsonStrTest3() { // 验证某个字段为JSON字符串时转义是否规范 - final JSONObject object = new JSONObject(true); + final JSONObject object = new JSONObject(JSONConfig.of().setIgnoreError(true)); object.set("name", "123123"); object.set("value", "\\"); object.set("value2", " Date: Tue, 14 Mar 2023 22:16:54 +0800 Subject: [PATCH 122/125] fix code --- .../java/cn/hutool/core/date/DateUtil.java | 20 ++++--------------- ...DateParser.java => ISO8601DateParser.java} | 6 +++--- 2 files changed, 7 insertions(+), 19 deletions(-) rename hutool-core/src/main/java/cn/hutool/core/date/format/parser/{UTCDateParser.java => ISO8601DateParser.java} (95%) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index eb9469610..a20c27a93 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -5,12 +5,7 @@ import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.date.format.DatePrinter; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.date.format.GlobalCustomFormat; -import cn.hutool.core.date.format.parser.CSTDateParser; -import cn.hutool.core.date.format.parser.NormalDateParser; -import cn.hutool.core.date.format.parser.PositionDateParser; -import cn.hutool.core.date.format.parser.PureDateParser; -import cn.hutool.core.date.format.parser.TimeParser; -import cn.hutool.core.date.format.parser.UTCDateParser; +import cn.hutool.core.date.format.parser.*; import cn.hutool.core.lang.Assert; import cn.hutool.core.math.NumberUtil; import cn.hutool.core.regex.PatternPool; @@ -26,14 +21,7 @@ import java.time.LocalDateTime; import java.time.Year; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; @@ -825,8 +813,8 @@ public class DateUtil extends CalendarUtil { // Wed Aug 01 00:00:00 CST 2012 return CSTDateParser.INSTANCE.parse(dateStr); } else if (StrUtil.contains(dateStr, 'T')) { - // UTC时间 - return UTCDateParser.INSTANCE.parse(dateStr); + // ISO8601标准时间 + return ISO8601DateParser.INSTANCE.parse(dateStr); } //标准日期格式(包括单个数字的日期时间) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/ISO8601DateParser.java similarity index 95% rename from hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java rename to hutool-core/src/main/java/cn/hutool/core/date/format/parser/ISO8601DateParser.java index 7b3596990..77fc2cb0b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/ISO8601DateParser.java @@ -9,7 +9,7 @@ import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharUtil; /** - * UTC日期字符串(JDK的Date对象toString默认格式)解析,支持格式; + * ISO8601日期字符串(JDK的Date对象toString默认格式)解析,支持格式; *
                    *
                  1. yyyy-MM-dd'T'HH:mm:ss'Z'
                  2. *
                  3. yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
                  4. @@ -22,13 +22,13 @@ import cn.hutool.core.util.CharUtil; * @author looly * @since 6.0.0 */ -public class UTCDateParser extends DefaultDateBasic implements DateParser { +public class ISO8601DateParser extends DefaultDateBasic implements DateParser { private static final long serialVersionUID = 1L; /** * 单例对象 */ - public static UTCDateParser INSTANCE = new UTCDateParser(); + public static ISO8601DateParser INSTANCE = new ISO8601DateParser(); @Override public DateTime parse(String source) { From b2235e45201ebb7055ecff2833ab508c976e0e31 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 14 Mar 2023 23:15:19 +0800 Subject: [PATCH 123/125] fix code --- .../src/main/java/cn/hutool/core/date/TimeUtil.java | 2 +- .../main/java/cn/hutool/core/map/LinkedForestMap.java | 2 +- .../cn/hutool/core/reflect/ParameterizedTypeImpl.java | 9 +++++---- .../src/main/java/cn/hutool/core/thread/ThreadUtil.java | 4 ++-- .../src/main/java/cn/hutool/core/util/JNDIUtil.java | 4 ++-- .../src/main/java/cn/hutool/core/util/PageUtil.java | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java index 291578024..1fd6b8e0e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TimeUtil.java @@ -217,7 +217,7 @@ public class TimeUtil extends TemporalAccessorUtil { /** * 解析日期时间字符串为{@link LocalDateTime},格式支持日期时间、日期、时间
                    - * 如果formatter为{code null},则使用{@link DateTimeFormatter#ISO_LOCAL_DATE_TIME} + * 如果formatter为{@code null},则使用{@link DateTimeFormatter#ISO_LOCAL_DATE_TIME} * * @param text 日期时间字符串 * @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter} diff --git a/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java b/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java index a0b9fc00e..dbcf2fa18 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java @@ -538,7 +538,7 @@ public class LinkedForestMap implements ForestMap { * 从当前节点开始,按广度优先向下遍历当前节点的所有子节点 * * @param includeCurrent 是否包含当前节点 - * @param consumer 对节点与节点和当前节点的距离的操作,当{code includeCurrent}为false时下标从1开始,否则从0开始 + * @param consumer 对节点与节点和当前节点的距离的操作,当{@code includeCurrent}为false时下标从1开始,否则从0开始 * @param breakTraverse 是否终止遍历,为null时默认总是返回{@code true} * @return 遍历到的最后一个节点 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ParameterizedTypeImpl.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ParameterizedTypeImpl.java index e19891095..d0777c541 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/ParameterizedTypeImpl.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ParameterizedTypeImpl.java @@ -1,12 +1,12 @@ package cn.hutool.core.reflect; +import cn.hutool.core.text.StrUtil; +import cn.hutool.core.util.ArrayUtil; + import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.text.StrUtil; - /** * {@link ParameterizedType} 接口实现,用于重新定义泛型类型 * @@ -70,13 +70,14 @@ public class ParameterizedTypeImpl implements ParameterizedType, Serializable { } /** - * 追加 {@code types} 到 @{code buf},使用 {@code sep} 分隔 + * 追加 {@code types} 到 {@code buf},使用 {@code sep} 分隔 * * @param buf 目标 * @param sep 分隔符 * @param types 加入的类型 * @return {@code buf} */ + @SuppressWarnings("SameParameterValue") private static StringBuilder appendAllTo(final StringBuilder buf, final String sep, final Type... types) { if (ArrayUtil.isNotEmpty(types)) { boolean isFirst = true; diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java index de79b82eb..17d126d08 100644 --- a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java @@ -140,7 +140,7 @@ public class ThreadUtil { *
                     	 *     1. 核心线程数与最大线程数为nThreads指定的大小
                     	 *     2. 默认使用LinkedBlockingQueue,默认队列大小为1024
                    -	 *     3. 如果isBlocked为{code true},当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被{@link Thread#interrupt()}中断
                    +	 *     3. 如果isBlocked为{@code true},当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被{@link Thread#interrupt()}中断
                     	 * 
                    * * @param nThreads 线程池大小 @@ -159,7 +159,7 @@ public class ThreadUtil { *
                     	 *     1. 核心线程数与最大线程数为nThreads指定的大小
                     	 *     2. 默认使用LinkedBlockingQueue
                    -	 *     3. 如果isBlocked为{code true},当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被{@link Thread#interrupt()}中断
                    +	 *     3. 如果isBlocked为{@code true},当执行拒绝策略的时候会处于阻塞状态,直到能添加到队列中或者被{@link Thread#interrupt()}中断
                     	 * 
                    * * @param nThreads 线程池大小 diff --git a/hutool-core/src/main/java/cn/hutool/core/util/JNDIUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/JNDIUtil.java index aca69c6cc..a1b9175ed 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/JNDIUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/JNDIUtil.java @@ -28,7 +28,7 @@ public class JNDIUtil { /** * 创建{@link InitialDirContext} * - * @param environment 环境参数,{code null}表示无参数 + * @param environment 环境参数,{@code null}表示无参数 * @return {@link InitialDirContext} */ public static InitialDirContext createInitialDirContext(final Map environment) { @@ -45,7 +45,7 @@ public class JNDIUtil { /** * 创建{@link InitialContext} * - * @param environment 环境参数,{code null}表示无参数 + * @param environment 环境参数,{@code null}表示无参数 * @return {@link InitialContext} */ public static InitialContext createInitialContext(final Map environment) { diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java index 3c49f1d5e..ff91710f5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java @@ -95,8 +95,8 @@ public class PageUtil { *

                    * 当{@link #setFirstPageNo(int)}设置为1时: *

                    -	 * 页码:1,每页10 =》 9
                    -	 * 页码:2,每页10 =》 19
                    +	 * 页码:1,每页10 =》 10
                    +	 * 页码:2,每页10 =》 20
                     	 * ……
                     	 * 
                    * From 48fdda9fafb85499439faa003f7862b094946e9e Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Mar 2023 03:07:19 +0800 Subject: [PATCH 124/125] fix code --- .../cn/hutool/core/collection/CollUtil.java | 16 +- .../cn/hutool/core/collection/ListUtil.java | 135 ++++---- .../cn/hutool/core/lang/DefaultSegment.java | 22 +- .../java/cn/hutool/core/lang/Segment.java | 4 +- .../cn/hutool/core/math/NavigatePageInfo.java | 71 +++++ .../java/cn/hutool/core/math/PageInfo.java | 291 ++++++++++++++++++ .../hutool/core/text/dfa/SensitiveUtil.java | 2 +- .../java/cn/hutool/core/util/PageUtil.java | 273 ---------------- .../hutool/core/collection/CollUtilTest.java | 2 +- .../hutool/core/collection/ListUtilTest.java | 62 ++-- .../cn/hutool/core/math/PageInfoTest.java | 32 ++ .../java/cn/hutool/core/text/dfa/DfaTest.java | 6 +- .../cn/hutool/core/util/PageUtilTest.java | 35 --- .../src/main/java/cn/hutool/db/Page.java | 20 +- .../main/java/cn/hutool/db/PageResult.java | 8 +- .../src/test/java/cn/hutool/db/DbTest.java | 3 +- 16 files changed, 520 insertions(+), 462 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/math/NavigatePageInfo.java create mode 100644 hutool-core/src/main/java/cn/hutool/core/math/PageInfo.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/math/PageInfoTest.java delete mode 100644 hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 19a76b752..531378f2a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -1735,21 +1735,7 @@ public class CollUtil { list.sort(comparator); } - return page(pageNo, pageSize, list); - } - - /** - * 对指定List分页取值 - * - * @param 集合元素类型 - * @param pageNo 页码,从0开始计数,0表示第一页 - * @param pageSize 每页的条目数 - * @param list 列表 - * @return 分页后的段落内容 - * @since 4.1.20 - */ - public static List page(final int pageNo, final int pageSize, final List list) { - return ListUtil.page(pageNo, pageSize, list); + return ListUtil.page(list, pageNo, pageSize); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index d2cb0d700..d05b98999 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -8,20 +8,11 @@ import cn.hutool.core.collection.partition.RandomAccessPartition; import cn.hutool.core.comparator.PinyinComparator; import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.lang.Assert; +import cn.hutool.core.math.PageInfo; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; -import cn.hutool.core.util.PageUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.RandomAccess; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.function.Predicate; @@ -254,42 +245,53 @@ public class ListUtil { * 对指定List分页取值 * * @param 集合元素类型 - * @param pageNo 页码,第一页的页码取决于{@link PageUtil#getFirstPageNo()},默认0 + * @param pageNo 页码,第一页的页码,从0开始 * @param pageSize 每页的条目数 * @param list 列表 * @return 分页后的段落内容 * @since 4.1.20 */ - public static List page(final int pageNo, final int pageSize, final List list) { + public static List page(final List list, final int pageNo, final int pageSize) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(0); + } + return page(list, PageInfo.of(list.size(), pageSize) + .setFirstPageNo(0).setPageNo(pageNo)); + } + + /** + * 对指定List分页取值 + * + * @param 集合元素类型 + * @param pageInfo 分页信息 + * @param list 列表 + * @return 分页后的段落内容 + * @since 4.1.20 + */ + public static List page(final List list, final PageInfo pageInfo) { if (CollUtil.isEmpty(list)) { return new ArrayList<>(0); } - final int resultSize = list.size(); - // 每页条目数大于总数直接返回所有 - if (resultSize <= pageSize) { - if (pageNo < (PageUtil.getFirstPageNo() + 1)) { + final int total = list.size(); + final int pageSize = pageInfo.getPageSize(); + // 不满一页 + if (total <= pageSize) { + if (pageInfo.isFirstPage()) { + // 页码为1,返回所有 return view(list); } else { // 越界直接返回空 return new ArrayList<>(0); } } - // 相乘可能会导致越界 临时用long - if (((long) (pageNo - PageUtil.getFirstPageNo()) * pageSize) > resultSize) { + + if (pageInfo.getBeginIndex() > total) { // 越界直接返回空 return new ArrayList<>(0); } - final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); - if (startEnd[1] > resultSize) { - startEnd[1] = resultSize; - if (startEnd[0] > startEnd[1]) { - return new ArrayList<>(0); - } - } - - return sub(list, startEnd[0], startEnd[1]); + return sub(list, pageInfo.getBeginIndex(), pageInfo.getEndIndexExclude()); } /** @@ -307,16 +309,11 @@ public class ListUtil { } final int total = list.size(); - final int totalPage = PageUtil.totalPage(total, pageSize); - for (int pageNo = PageUtil.getFirstPageNo(); pageNo < totalPage + PageUtil.getFirstPageNo(); pageNo++) { - // 获取当前页在列表中对应的起止序号 - final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); - if (startEnd[1] > total) { - startEnd[1] = total; - } - + final PageInfo pageInfo = PageInfo.of(total, pageSize); + while(pageInfo.isValidPage()){ // 返回数据 - pageListConsumer.accept(sub(list, startEnd[0], startEnd[1])); + pageListConsumer.accept(sub(list, pageInfo.getBeginIndex(), pageInfo.getEndIndexExclude())); + pageInfo.nextPage(); } } @@ -346,7 +343,7 @@ public class ListUtil { if (CollUtil.isEmpty(list)) { return list; } - if(null == c){ + if (null == c) { c = Comparator.nullsFirst((Comparator) Comparator.naturalOrder()); } list.sort(c); @@ -446,10 +443,10 @@ public class ListUtil { /** * 在指定位置设置元素。当index小于List的长度时,替换指定位置的值,否则追加{@code paddingElement}直到到达index后,设置值 * - * @param 元素类型 - * @param list List列表 - * @param index 位置 - * @param element 新元素 + * @param 元素类型 + * @param list List列表 + * @param index 位置 + * @param element 新元素 * @param paddingElement 填充的值 * @return 原List * @since 5.8.4 @@ -471,29 +468,29 @@ public class ListUtil { /** * 截取集合的部分 * - * @param 集合元素类型 - * @param list 被截取的数组 - * @param start 开始位置(包含) - * @param end 结束位置(不包含) + * @param 集合元素类型 + * @param list 被截取的数组 + * @param begionInclude 开始位置(包含) + * @param endExclude 结束位置(不包含) * @return 截取后的数组,当开始位置超过最大时,返回空的List */ - public static List sub(final List list, final int start, final int end) { - return sub(list, start, end, 1); + public static List sub(final List list, final int begionInclude, final int endExclude) { + return sub(list, begionInclude, endExclude, 1); } /** * 截取集合的部分
                    * 此方法与{@link List#subList(int, int)} 不同在于子列表是新的副本,操作子列表不会影响原列表。 * - * @param 集合元素类型 - * @param list 被截取的数组 - * @param start 开始位置(包含) - * @param end 结束位置(不包含) - * @param step 步进 + * @param 集合元素类型 + * @param list 被截取的数组 + * @param begionInclude 开始位置(包含) + * @param endExclude 结束位置(不包含) + * @param step 步进 * @return 截取后的数组,当开始位置超过最大时,返回空的List * @since 4.0.6 */ - public static List sub(final List list, int start, int end, int step) { + public static List sub(final List list, int begionInclude, int endExclude, int step) { if (list == null) { return null; } @@ -503,25 +500,25 @@ public class ListUtil { } final int size = list.size(); - if (start < 0) { - start += size; + if (begionInclude < 0) { + begionInclude += size; } - if (end < 0) { - end += size; + if (endExclude < 0) { + endExclude += size; } - if (start == size) { + if (begionInclude == size) { return new ArrayList<>(0); } - if (start > end) { - final int tmp = start; - start = end; - end = tmp; + if (begionInclude > endExclude) { + final int tmp = begionInclude; + begionInclude = endExclude; + endExclude = tmp; } - if (end > size) { - if (start >= size) { + if (endExclude > size) { + if (begionInclude >= size) { return new ArrayList<>(0); } - end = size; + endExclude = size; } if (step < 1) { @@ -529,7 +526,7 @@ public class ListUtil { } final List result = new ArrayList<>(); - for (int i = start; i < end; i += step) { + for (int i = begionInclude; i < endExclude; i += step) { result.add(list.get(i)); } return result; @@ -719,8 +716,8 @@ public class ListUtil { * 通过删除或替换现有元素或者原地添加新的元素来修改列表,并以列表形式返回被修改的内容。此方法不会改变原列表。 * 类似js的splice函数 * - * @param 元素类型 - * @param list 列表 + * @param 元素类型 + * @param list 列表 * @param start 指定修改的开始位置(从 0 计数), 可以为负数, -1代表最后一个元素 * @param deleteCount 删除个数,必须是正整数 * @param items 放入的元素 diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/DefaultSegment.java b/hutool-core/src/main/java/cn/hutool/core/lang/DefaultSegment.java index 1e69e28a2..02c8b24fc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/DefaultSegment.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/DefaultSegment.java @@ -1,5 +1,7 @@ package cn.hutool.core.lang; +import cn.hutool.core.text.StrUtil; + /** * 片段默认实现 * @@ -9,26 +11,32 @@ package cn.hutool.core.lang; */ public class DefaultSegment implements Segment { - protected T startIndex; + protected T beginIndex; protected T endIndex; /** * 构造 - * @param startIndex 起始位置 - * @param endIndex 结束位置 + * + * @param beginIndex 起始位置 + * @param endIndex 结束位置 */ - public DefaultSegment(final T startIndex, final T endIndex) { - this.startIndex = startIndex; + public DefaultSegment(final T beginIndex, final T endIndex) { + this.beginIndex = beginIndex; this.endIndex = endIndex; } @Override - public T getStartIndex() { - return this.startIndex; + public T getBeginIndex() { + return this.beginIndex; } @Override public T getEndIndex() { return this.endIndex; } + + @Override + public String toString() { + return StrUtil.format("[{}, {}]", beginIndex, endIndex); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Segment.java b/hutool-core/src/main/java/cn/hutool/core/lang/Segment.java index 92ff0e385..be9a4dbaf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Segment.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Segment.java @@ -19,7 +19,7 @@ public interface Segment { * * @return 起始位置 */ - T getStartIndex(); + T getBeginIndex(); /** * 获取结束位置 @@ -34,7 +34,7 @@ public interface Segment { * @return 片段长度 */ default T length(){ - final T start = Assert.notNull(getStartIndex(), "Start index must be not null!"); + final T start = Assert.notNull(getBeginIndex(), "Start index must be not null!"); final T end = Assert.notNull(getEndIndex(), "End index must be not null!"); return Convert.convert((Type) start.getClass(), NumberUtil.sub(end, start).abs()); } diff --git a/hutool-core/src/main/java/cn/hutool/core/math/NavigatePageInfo.java b/hutool-core/src/main/java/cn/hutool/core/math/NavigatePageInfo.java new file mode 100644 index 000000000..cee14bc65 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/math/NavigatePageInfo.java @@ -0,0 +1,71 @@ +package cn.hutool.core.math; + +public class NavigatePageInfo extends PageInfo{ + + private final int navigatePages = 8; //导航页码数 + private int[] navigatePageNumbers; //所有导航页号 + + public NavigatePageInfo(final int total, final int pageSize) { + super(total, pageSize); + + //基本参数设定之后进行导航页面的计算 + calcNavigatePageNumbers(); + } + + /** + * 得到所有导航页号 + * + * @return {int[]} + */ + public int[] getNavigatePageNumbers() { + return navigatePageNumbers; + } + + public String toString() { + final StringBuilder str = new StringBuilder(super.toString()); + str.append(", {navigatePageNumbers="); + final int len = navigatePageNumbers.length; + if (len > 0) str.append(navigatePageNumbers[0]); + for (int i = 1; i < len; i++) { + str.append(" ").append(navigatePageNumbers[i]); + } + str.append("}"); + return str.toString(); + } + + /** + * 计算导航页 + */ + private void calcNavigatePageNumbers() { + //当总页数小于或等于导航页码数时 + if (pages <= navigatePages) { + navigatePageNumbers = new int[pages]; + for (int i = 0; i < pages; i++) { + navigatePageNumbers[i] = i + 1; + } + } else { //当总页数大于导航页码数时 + navigatePageNumbers = new int[navigatePages]; + int startNum = pageNo - navigatePages / 2; + int endNum = pageNo + navigatePages / 2; + + if (startNum < 1) { + startNum = 1; + //(最前navPageCount页 + for (int i = 0; i < navigatePages; i++) { + navigatePageNumbers[i] = startNum++; + } + } else if (endNum > pages) { + endNum = pages; + //最后navPageCount页 + for (int i = navigatePages - 1; i >= 0; i--) { + navigatePageNumbers[i] = endNum--; + } + } else { + //所有中间页 + for (int i = 0; i < navigatePages; i++) { + navigatePageNumbers[i] = startNum++; + } + } + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/math/PageInfo.java b/hutool-core/src/main/java/cn/hutool/core/math/PageInfo.java new file mode 100644 index 000000000..a84079fff --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/math/PageInfo.java @@ -0,0 +1,291 @@ +package cn.hutool.core.math; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.DefaultSegment; +import cn.hutool.core.lang.Segment; + +/** + * 分页信息,通过提供的总数、页码、每页记录数等信息,计算总页数等信息
                    + * 来自:https://bbs.csdn.net/topics/360010907 + * + * @author 莫取网名 + */ +public class PageInfo { + + private static final int DEFAULT_PAGE_SIZE = 10; + + /** + * 创建{@code PageInfo},默认当前页是1 + * + * @param total 总记录数 + * @param pageSize 每页显示记录数 + * @return {@code PageInfo} + */ + public static PageInfo of(final int total, final int pageSize) { + return new PageInfo(total, pageSize); + } + + /** + * 总记录数 + */ + int total; + /** + * 每页显示记录数 + */ + int pageSize; + /** + * 总页数 + */ + int pages; + /** + * 首页标识 + */ + int firstPageNo = 1; + /** + * 当前页 + */ + int pageNo = firstPageNo; + + /** + * 构造 + * + * @param total 总记录数 + * @param pageSize 每页显示记录数 + */ + public PageInfo(final int total, final int pageSize) { + init(total, pageSize); + } + + /** + * 初始化 + * + * @param total 总记录数 + * @param pageSize 每页显示记录数 + */ + private void init(final int total, int pageSize) { + Assert.isTrue(total >= 0, "Total must >= 0"); + + //设置基本参数 + this.total = total; + + if (pageSize < 1) { + pageSize = DEFAULT_PAGE_SIZE; + } + this.pageSize = pageSize; + // 因为总条数除以页大小的最大余数是页大小数-1, + // 因此加一个最大余数,保证舍弃的余数与最大余数凑1.x,就是一旦有余数则+1页 + this.pages = (total + pageSize - 1) / pageSize; + } + + /** + * 得到记录总数 + * + * @return {int} + */ + public int getTotal() { + return total; + } + + /** + * 得到每页显示多少条记录 + * + * @return {int} + */ + public int getPageSize() { + return pageSize; + } + + /** + * 得到页面总数 + * + * @return {int} + */ + public int getPages() { + return pages; + } + + /** + * 得到当前页号 + * + * @return {int} + */ + public int getPageNo() { + return pageNo; + } + + + /** + * 是否首页 + * + * @return 是否首页 + */ + public boolean isFirstPage() { + return getPageIndexBase1() == 1; + } + + /** + * 是否尾页 + * + * @return 是否尾页 + */ + public boolean isLastPage() { + return getPageIndexBase1() == this.pages; + } + + /** + * 是否有前一页 + * + * @return 是否有前一页 + */ + public boolean hasPreviousPage() { + return getPageIndexBase1() > 1; + } + + /** + * 是否有下一页 + * + * @return 是否有下一页 + */ + public boolean hasNextPage() { + return getBeginIndex() < this.pages; + } + + /** + * 当前页是否可用(是否大于firstPageNum且小于总页数) + * @return 是否可用 + */ + public boolean isValidPage(){ + return this.getPageIndexBase1() <= this.pages; + } + + /** + * 获取当前页的开始记录index(包含) + * + * @return 开始记录index(包含) + */ + public int getBeginIndex() { + return (getPageIndexBase1() -1) * this.pageSize; + } + + /** + * 获取当前页的结束记录index(不包含) + *
                      + *
                    • 当开始index超出total时,返回正常值
                    • + *
                    • 当开始index未超出total但是计算的end超出时,返回total + 1
                    • + *
                    • 当开始index和end都未超出时,返回正常值
                    • + *
                    + * + * @return 结束记录index(不包含) + */ + public int getEndIndexExclude() { + return getEndIndex() + 1; + } + + /** + * 获取当前页的结束记录index(包含) + *
                      + *
                    • 当开始index超出total时,返回正常值
                    • + *
                    • 当开始index未超出total但是计算的end超出时,返回total
                    • + *
                    • 当开始index和end都未超出时,返回正常值
                    • + *
                    + * + * @return 结束记录index(包含) + */ + public int getEndIndex() { + final int begin = getBeginIndex(); + int end = begin + this.pageSize - 1; + if (begin <= this.total && end > this.total) { + end = this.total; + } + return end; + } + + /** + * 将页数和每页条目数转换为开始位置和结束位置
                    + * 此方法用于包括结束位置的分页方法
                    + * 例如: + *
                    +	 * 页码:1,每页10 =》 [0, 9]
                    +	 * 页码:2,每页10 =》 [10, 19]
                    +	 * ……
                    +	 * 
                    + * + * @return {@link Segment} + */ + public Segment getSegment() { + return new DefaultSegment<>(getBeginIndex(), getEndIndex()); + } + + /** + * 获取设置首页编号,即以数字几为第一页标志 + * + * @return 设置首页编号 + */ + public int getFirstPageNo() { + return this.firstPageNo; + } + + /** + * 设置首页编号,即以数字几为第一页标志
                    + * 如设置0,则0表示第一页,1表示第二页 + * + * @param firstPageNo 首页编号 + * @return this + */ + public PageInfo setFirstPageNo(final int firstPageNo) { + this.firstPageNo = firstPageNo; + return this; + } + + /** + * 设置当前页码 + * + * @param pageNo 当前页码 + * @return this + */ + public PageInfo setPageNo(final int pageNo) { + //根据输入可能错误的当前号码进行自动纠正 + // 不判断后边界,因为当页码超出边界,应该返回一个空区间的数据,而非始终保持在最后一页 + this.pageNo = Math.max(pageNo, firstPageNo); + return this; + } + + /** + * 下一页,即当前页码+1 + * + * @return this + */ + public PageInfo nextPage() { + return setPageNo(this.pageNo + 1); + } + + /** + * 上一页,即当前页码-1,直到第一页则始终为第一页 + * + * @return this + */ + public PageInfo PreviousPage() { + return setPageNo(this.pageNo - 1); + } + + public String toString() { + return "{" + + "total=" + total + + ",pages=" + pages + + ",pageNumber=" + pageNo + + ",limit=" + pageSize + + ",isFirstPage=" + isFirstPage() + + ",isLastPage=" + isLastPage() + + ",hasPreviousPage=" + hasPreviousPage() + + ",hasNextPage=" + hasNextPage() + + "}"; + } + + /** + * 获取页码序号,第一个序号就是1 + * @return 页码序号 + */ + private int getPageIndexBase1(){ + return this.pageNo - this.firstPageNo + 1; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/text/dfa/SensitiveUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/dfa/SensitiveUtil.java index 07e1cb64e..ba03bb2a6 100755 --- a/hutool-core/src/main/java/cn/hutool/core/text/dfa/SensitiveUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/dfa/SensitiveUtil.java @@ -171,7 +171,7 @@ public final class SensitiveUtil { } : sensitiveProcessor; final Map foundWordMap = new HashMap<>(foundWordList.size(), 1); - foundWordList.forEach(foundWord -> foundWordMap.put(foundWord.getStartIndex(), foundWord)); + foundWordList.forEach(foundWord -> foundWordMap.put(foundWord.getBeginIndex(), foundWord)); final int length = text.length(); final StringBuilder textStringBuilder = new StringBuilder(); for (int i = 0; i < length; i++) { diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java deleted file mode 100644 index ff91710f5..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java +++ /dev/null @@ -1,273 +0,0 @@ -package cn.hutool.core.util; - -import cn.hutool.core.lang.DefaultSegment; -import cn.hutool.core.lang.Segment; - -/** - * 分页工具类 - * - * @author xiaoleilu - */ -public class PageUtil { - - private static int firstPageNo = 0; - - /** - * 获得首页的页码,可以为0或者1 - * - * @return 首页页码 - */ - public static int getFirstPageNo() { - return firstPageNo; - } - - /** - * 设置首页页码,可以为0或者1 - * - *
                    -	 *     当设置为0时,页码0表示第一页,开始位置为0
                    -	 *     当设置为1时,页码1表示第一页,开始位置为0
                    -	 * 
                    - * - * @param customFirstPageNo 自定义的首页页码,为0或者1 - */ - synchronized public static void setFirstPageNo(final int customFirstPageNo) { - firstPageNo = customFirstPageNo; - } - - /** - * 设置首页页码为1 - * - *
                    -	 *     当设置为1时,页码1表示第一页,开始位置为0
                    -	 * 
                    - */ - public static void setOneAsFirstPageNo() { - setFirstPageNo(1); - } - - /** - * 将页数和每页条目数转换为开始位置
                    - * 此方法用于不包括结束位置的分页方法
                    - * 例如: - * - *
                    -	 * 页码:0,每页10 =》 0
                    -	 * 页码:1,每页10 =》 10
                    -	 * ……
                    -	 * 
                    - * - *

                    - * 当{@link #setFirstPageNo(int)}设置为1时: - *

                    -	 * 页码:1,每页10 =》 0
                    -	 * 页码:2,每页10 =》 10
                    -	 * ……
                    -	 * 
                    - * - * @param pageNo 页码(从0计数) - * @param pageSize 每页条目数 - * @return 开始位置 - */ - public static int getStart(int pageNo, int pageSize) { - if (pageNo < firstPageNo) { - pageNo = firstPageNo; - } - - if (pageSize < 1) { - pageSize = 0; - } - - return (pageNo - firstPageNo) * pageSize; - } - - /** - * 将页数和每页条目数转换为结束位置
                    - * 此方法用于不包括结束位置的分页方法
                    - * 例如: - * - *
                    -	 * 页码:0,每页10 =》 9
                    -	 * 页码:1,每页10 =》 19
                    -	 * ……
                    -	 * 
                    - * - *

                    - * 当{@link #setFirstPageNo(int)}设置为1时: - *

                    -	 * 页码:1,每页10 =》 10
                    -	 * 页码:2,每页10 =》 20
                    -	 * ……
                    -	 * 
                    - * - * @param pageNo 页码(从0计数) - * @param pageSize 每页条目数 - * @return 开始位置 - * @since 5.2.5 - */ - public static int getEnd(final int pageNo, final int pageSize) { - final int start = getStart(pageNo, pageSize); - return getEndByStart(start, pageSize); - } - - /** - * 将页数和每页条目数转换为开始位置和结束位置
                    - * 此方法用于包括结束位置的分页方法
                    - * 例如: - * - *
                    -	 * 页码:0,每页10 =》 [0, 10]
                    -	 * 页码:1,每页10 =》 [10, 20]
                    -	 * ……
                    -	 * 
                    - * - *

                    - * 当{@link #setFirstPageNo(int)}设置为1时: - *

                    -	 * 页码:1,每页10 =》 [0, 10]
                    -	 * 页码:2,每页10 =》 [10, 20]
                    -	 * ……
                    -	 * 
                    - * - * @param pageNo 页码(从0计数) - * @param pageSize 每页条目数 - * @return 第一个数为开始位置,第二个数为结束位置 - */ - public static int[] transToStartEnd(final int pageNo, final int pageSize) { - final int start = getStart(pageNo, pageSize); - return new int[]{start, getEndByStart(start, pageSize)}; - } - - /** - * 将页数和每页条目数转换为开始位置和结束位置
                    - * 此方法用于包括结束位置的分页方法
                    - * 例如: - * - *
                    -	 * 页码:0,每页10 =》 [0, 10]
                    -	 * 页码:1,每页10 =》 [10, 20]
                    -	 * ……
                    -	 * 
                    - * - *

                    - * 当{@link #setFirstPageNo(int)}设置为1时: - *

                    -	 * 页码:1,每页10 =》 [0, 10]
                    -	 * 页码:2,每页10 =》 [10, 20]
                    -	 * ……
                    -	 * 
                    - * - * @param pageNo 页码(从0计数) - * @param pageSize 每页条目数 - * @return {@link Segment} - * @since 5.5.3 - */ - public static Segment toSegment(final int pageNo, final int pageSize) { - final int[] startEnd = transToStartEnd(pageNo, pageSize); - return new DefaultSegment<>(startEnd[0], startEnd[1]); - } - - /** - * 根据总数计算总页数 - * - * @param totalCount 总数 - * @param pageSize 每页数 - * @return 总页数 - */ - public static int totalPage(final int totalCount, final int pageSize) { - return totalPage((long) totalCount, pageSize); - } - - /** - * 根据总数计算总页数 - * - * @param totalCount 总数 - * @param pageSize 每页数 - * @return 总页数 - * @since 5.8.5 - */ - public static int totalPage(final long totalCount, final int pageSize) { - if (pageSize == 0) { - return 0; - } - return Math.toIntExact(totalCount % pageSize == 0 - ? (totalCount / pageSize) : (totalCount / pageSize + 1)); - } - - /** - * 分页彩虹算法
                    - * 来自:https://github.com/iceroot/iceroot/blob/master/src/main/java/com/icexxx/util/IceUtil.java
                    - * 通过传入的信息,生成一个分页列表显示 - * - * @param pageNo 当前页 - * @param totalPage 总页数 - * @param displayCount 每屏展示的页数 - * @return 分页条 - */ - public static int[] rainbow(final int pageNo, final int totalPage, final int displayCount) { - // displayCount % 2 - final boolean isEven = (displayCount & 1) == 0; - final int left = displayCount >> 1; - int right = displayCount >> 1; - - int length = displayCount; - if (isEven) { - right++; - } - if (totalPage < displayCount) { - length = totalPage; - } - final int[] result = new int[length]; - if (totalPage >= displayCount) { - if (pageNo <= left) { - for (int i = 0; i < result.length; i++) { - result[i] = i + 1; - } - } else if (pageNo > totalPage - right) { - for (int i = 0; i < result.length; i++) { - result[i] = i + totalPage - displayCount + 1; - } - } else { - for (int i = 0; i < result.length; i++) { - result[i] = i + pageNo - left + (isEven ? 1 : 0); - } - } - } else { - for (int i = 0; i < result.length; i++) { - result[i] = i + 1; - } - } - return result; - - } - - /** - * 分页彩虹算法(默认展示10页)
                    - * 来自:https://github.com/iceroot/iceroot/blob/master/src/main/java/com/icexxx/util/IceUtil.java - * - * @param currentPage 当前页 - * @param pageCount 总页数 - * @return 分页条 - */ - public static int[] rainbow(final int currentPage, final int pageCount) { - return rainbow(currentPage, pageCount, 10); - } - - //------------------------------------------------------------------------- Private method start - - /** - * 根据起始位置获取结束位置 - * - * @param start 起始位置 - * @param pageSize 每页条目数 - * @return 结束位置 - */ - private static int getEndByStart(final int start, int pageSize) { - if (pageSize < 1) { - pageSize = 0; - } - return start + pageSize; - } - - //------------------------------------------------------------------------- Private method end -} diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index acb7cf236..f87b0586e 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -864,7 +864,7 @@ public class CollUtilTest { objects.add(Dict.of().set("name", "姓名:" + i)); } - Assert.assertEquals(0, CollUtil.page(3, 5, objects).size()); + Assert.assertEquals(0, ListUtil.page(objects, 3, 5).size()); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java index c8d330e88..e4e40d0ac 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java @@ -2,7 +2,7 @@ package cn.hutool.core.collection; import cn.hutool.core.date.StopWatch; import cn.hutool.core.lang.Console; -import cn.hutool.core.util.PageUtil; +import cn.hutool.core.math.PageInfo; import cn.hutool.core.util.RandomUtil; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,11 +10,7 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class ListUtilTest { @@ -105,51 +101,32 @@ public class ListUtilTest { } @Test - public void pageTest() { + public void pageTest1() { final List a = ListUtil.ofLinked(1, 2, 3, 4, 5); - PageUtil.setFirstPageNo(1); - final int[] a_1 = ListUtil.page(1, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] a1 = ListUtil.page(1, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] a2 = ListUtil.page(2, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] a3 = ListUtil.page(3, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] a4 = ListUtil.page(4, 2, a).stream().mapToInt(Integer::valueOf).toArray(); + final int[] a_1 = ListUtil.page(a, 0, 2).stream().mapToInt(Integer::valueOf).toArray(); + final int[] a1 = ListUtil.page(a, 0, 2).stream().mapToInt(Integer::valueOf).toArray(); + final int[] a2 = ListUtil.page(a, 1, 2).stream().mapToInt(Integer::valueOf).toArray(); + final int[] a3 = ListUtil.page(a, 2, 2).stream().mapToInt(Integer::valueOf).toArray(); + final int[] a4 = ListUtil.page(a, 3, 2).stream().mapToInt(Integer::valueOf).toArray(); Assert.assertArrayEquals(new int[]{1, 2}, a_1); Assert.assertArrayEquals(new int[]{1, 2}, a1); Assert.assertArrayEquals(new int[]{3, 4}, a2); Assert.assertArrayEquals(new int[]{5}, a3); Assert.assertArrayEquals(new int[]{}, a4); + } - - PageUtil.setFirstPageNo(2); - final int[] b_1 = ListUtil.page(1, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] b1 = ListUtil.page(2, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] b2 = ListUtil.page(3, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] b3 = ListUtil.page(4, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] b4 = ListUtil.page(5, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - Assert.assertArrayEquals(new int[]{1, 2}, b_1); - Assert.assertArrayEquals(new int[]{1, 2}, b1); - Assert.assertArrayEquals(new int[]{3, 4}, b2); - Assert.assertArrayEquals(new int[]{5}, b3); - Assert.assertArrayEquals(new int[]{}, b4); - - PageUtil.setFirstPageNo(0); - final int[] c_1 = ListUtil.page(-1, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] c1 = ListUtil.page(0, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] c2 = ListUtil.page(1, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] c3 = ListUtil.page(2, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - final int[] c4 = ListUtil.page(3, 2, a).stream().mapToInt(Integer::valueOf).toArray(); - Assert.assertArrayEquals(new int[]{1, 2}, c_1); - Assert.assertArrayEquals(new int[]{1, 2}, c1); - Assert.assertArrayEquals(new int[]{3, 4}, c2); - Assert.assertArrayEquals(new int[]{5}, c3); - Assert.assertArrayEquals(new int[]{}, c4); - - - PageUtil.setFirstPageNo(1); - final int[] d1 = ListUtil.page(0, 8, a).stream().mapToInt(Integer::valueOf).toArray(); + @Test + public void pageTest2() { + final List a = ListUtil.ofLinked(1, 2, 3, 4, 5); + final int[] d1 = ListUtil.page(a, PageInfo.of(a.size(), 8).setFirstPageNo(0).setPageNo(0)) + .stream().mapToInt(Integer::valueOf).toArray(); Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, d1); + } + @Test + public void pageTest3() { + final List a = ListUtil.ofLinked(1, 2, 3, 4, 5); // page with consumer final List> pageListData = new ArrayList<>(); ListUtil.page(a, 2, pageListData::add); @@ -168,9 +145,6 @@ public class ListUtilTest { Assert.assertArrayEquals(new int[]{}, pageListData.get(0).stream().mapToInt(Integer::valueOf).toArray()); Assert.assertArrayEquals(new int[]{3, 4}, pageListData.get(1).stream().mapToInt(Integer::valueOf).toArray()); Assert.assertArrayEquals(new int[]{5}, pageListData.get(2).stream().mapToInt(Integer::valueOf).toArray()); - - // 恢复默认值,避免影响其他测试用例 - PageUtil.setFirstPageNo(0); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/math/PageInfoTest.java b/hutool-core/src/test/java/cn/hutool/core/math/PageInfoTest.java new file mode 100644 index 000000000..a5778a98f --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/math/PageInfoTest.java @@ -0,0 +1,32 @@ +package cn.hutool.core.math; + +import org.junit.Assert; +import org.junit.Test; + +public class PageInfoTest { + @Test + public void pagesTest() { + PageInfo pageInfo = new PageInfo(20, 3); + Assert.assertEquals(7, pageInfo.getPages()); + + pageInfo = new PageInfo(20, 4); + Assert.assertEquals(5, pageInfo.getPages()); + } + + @Test + public void getSegmentTest() { + final PageInfo page = PageInfo.of(20, 10); + Assert.assertEquals("[0, 9]", page.getSegment().toString()); + Assert.assertEquals("[10, 19]", page.nextPage().getSegment().toString()); + Assert.assertEquals("[20, 20]", page.nextPage().getSegment().toString()); + } + + @Test + public void getSegmentTest2() { + final PageInfo page = PageInfo.of(20, 10); + page.setFirstPageNo(0).setPageNo(0); + Assert.assertEquals("[0, 9]", page.getSegment().toString()); + Assert.assertEquals("[10, 19]", page.nextPage().getSegment().toString()); + Assert.assertEquals("[20, 20]", page.nextPage().getSegment().toString()); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/text/dfa/DfaTest.java b/hutool-core/src/test/java/cn/hutool/core/text/dfa/DfaTest.java index 3847800db..739f02fd0 100755 --- a/hutool-core/src/test/java/cn/hutool/core/text/dfa/DfaTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/dfa/DfaTest.java @@ -91,15 +91,15 @@ public class DfaTest { Assert.assertEquals(3, result.size()); Assert.assertEquals("赵", result.get(0).getWord()); - Assert.assertEquals(0, result.get(0).getStartIndex().intValue()); + Assert.assertEquals(0, result.get(0).getBeginIndex().intValue()); Assert.assertEquals(0, result.get(0).getEndIndex().intValue()); Assert.assertEquals("赵阿", result.get(1).getWord()); - Assert.assertEquals(0, result.get(1).getStartIndex().intValue()); + Assert.assertEquals(0, result.get(1).getBeginIndex().intValue()); Assert.assertEquals(1, result.get(1).getEndIndex().intValue()); Assert.assertEquals("赵阿三", result.get(2).getWord()); - Assert.assertEquals(0, result.get(2).getStartIndex().intValue()); + Assert.assertEquals(0, result.get(2).getBeginIndex().intValue()); Assert.assertEquals(2, result.get(2).getEndIndex().intValue()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java deleted file mode 100644 index 10ec440db..000000000 --- a/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.hutool.core.util; - -import org.junit.Assert; -import org.junit.Test; - -/** - * 分页单元测试 - * - * @author Looly - */ -public class PageUtilTest { - - @Test - public void transToStartEndTest() { - final int[] startEnd1 = PageUtil.transToStartEnd(0, 10); - Assert.assertEquals(0, startEnd1[0]); - Assert.assertEquals(10, startEnd1[1]); - - final int[] startEnd2 = PageUtil.transToStartEnd(1, 10); - Assert.assertEquals(10, startEnd2[0]); - Assert.assertEquals(20, startEnd2[1]); - } - - @Test - public void totalPage() { - final int totalPage = PageUtil.totalPage(20, 3); - Assert.assertEquals(7, totalPage); - } - - @Test - public void rainbowTest() { - final int[] rainbow = PageUtil.rainbow(5, 20, 6); - Assert.assertArrayEquals(new int[]{3, 4, 5, 6, 7, 8}, rainbow); - } -} diff --git a/hutool-db/src/main/java/cn/hutool/db/Page.java b/hutool-db/src/main/java/cn/hutool/db/Page.java index 7e0c93836..176d7f42d 100644 --- a/hutool-db/src/main/java/cn/hutool/db/Page.java +++ b/hutool-db/src/main/java/cn/hutool/db/Page.java @@ -1,8 +1,8 @@ package cn.hutool.db; import cn.hutool.core.lang.Segment; +import cn.hutool.core.math.PageInfo; import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.PageUtil; import cn.hutool.db.sql.Order; import java.io.Serializable; @@ -16,6 +16,9 @@ import java.util.Arrays; public class Page implements Segment, Serializable { private static final long serialVersionUID = 97792549823353462L; + /** + * 默认 + */ public static final int DEFAULT_PAGE_SIZE = 20; /** @@ -140,15 +143,16 @@ public class Page implements Segment, Serializable { /** * @return 开始位置 - * @see #getStartIndex() + * @see #getBeginIndex() */ public int getStartPosition() { - return getStartIndex(); + return getBeginIndex(); } @Override - public Integer getStartIndex() { - return PageUtil.getStart(this.pageNumber, this.pageSize); + public Integer getBeginIndex() { + return PageInfo.of(Integer.MAX_VALUE, this.pageSize) + .setFirstPageNo(0).setPageNo(this.pageNumber).getBeginIndex(); } /** @@ -161,7 +165,7 @@ public class Page implements Segment, Serializable { @Override public Integer getEndIndex() { - return PageUtil.getEnd(this.pageNumber, this.pageSize); + return PageInfo.of(Integer.MAX_VALUE, this.pageSize).setFirstPageNo(0).getEndIndex(); } /** @@ -178,7 +182,9 @@ public class Page implements Segment, Serializable { * @return 第一个数为开始位置,第二个数为结束位置 */ public int[] getStartEnd() { - return PageUtil.transToStartEnd(pageNumber, pageSize); + final PageInfo pageInfo = PageInfo.of(Integer.MAX_VALUE, this.pageSize) + .setFirstPageNo(0).setPageNo(this.pageNumber); + return new int[]{pageInfo.getBeginIndex(), pageInfo.getEndIndexExclude()}; } @Override diff --git a/hutool-db/src/main/java/cn/hutool/db/PageResult.java b/hutool-db/src/main/java/cn/hutool/db/PageResult.java index cb410d263..70118f2a6 100644 --- a/hutool-db/src/main/java/cn/hutool/db/PageResult.java +++ b/hutool-db/src/main/java/cn/hutool/db/PageResult.java @@ -1,6 +1,6 @@ package cn.hutool.db; -import cn.hutool.core.util.PageUtil; +import cn.hutool.core.math.PageInfo; import java.util.ArrayList; @@ -16,7 +16,7 @@ public class PageResult extends ArrayList { public static final int DEFAULT_PAGE_SIZE = Page.DEFAULT_PAGE_SIZE; /** - * 页码,{@link PageUtil#getFirstPageNo()}表示第一页 + * 页码 */ private int page; /** @@ -65,7 +65,7 @@ public class PageResult extends ArrayList { this(page, pageSize); this.total = total; - this.totalPage = PageUtil.totalPage(total, pageSize); + this.totalPage = PageInfo.of(total, pageSize).getPages(); } //---------------------------------------------------------- Constructor end @@ -142,7 +142,7 @@ public class PageResult extends ArrayList { * @return 是否第一页 */ public boolean isFirst() { - return this.page == PageUtil.getFirstPageNo(); + return this.page == 0; } /** diff --git a/hutool-db/src/test/java/cn/hutool/db/DbTest.java b/hutool-db/src/test/java/cn/hutool/db/DbTest.java index 1d2f6047c..49d8da933 100644 --- a/hutool-db/src/test/java/cn/hutool/db/DbTest.java +++ b/hutool-db/src/test/java/cn/hutool/db/DbTest.java @@ -34,7 +34,8 @@ public class DbTest { @Test public void pageTest() { // 测试数据库中一共4条数据,第0页有3条,第1页有1条 - final List page0 = Db.of().page(Entity.of("user"), Page.of(0, 3)); + final List page0 = Db.of().page(Entity.of("user"), + Page.of(0, 3)); Assert.assertEquals(3, page0.size()); final List page1 = Db.of().page(Entity.of("user"), Page.of(1, 3)); From a03f12d23b25c93ff1e7dfec78450aed8ad3991f Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 15 Mar 2023 03:11:41 +0800 Subject: [PATCH 125/125] fix comment --- .../java/cn/hutool/core/reflect/MethodHandleUtil.java | 3 --- .../src/main/java/cn/hutool/core/regex/ReUtil.java | 8 +++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java index 4034e9f42..6e7531bec 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/MethodHandleUtil.java @@ -121,7 +121,6 @@ public class MethodHandleUtil { * return "Quack"; * } * } - *

                    * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, @@ -167,7 +166,6 @@ public class MethodHandleUtil { * return "Quack"; * } * } - *

                    * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, @@ -193,7 +191,6 @@ public class MethodHandleUtil { * return "Quack"; * } * } - *

                    * Duck duck = (Duck) Proxy.newProxyInstance( * ClassLoaderUtil.getClassLoader(), * new Class[] { Duck.class }, diff --git a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java index 3c015c1a9..897e118fa 100755 --- a/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/regex/ReUtil.java @@ -197,7 +197,7 @@ public class ReUtil { * @return 匹配后得到的字符串数组,按照分组顺序依次列出,未匹配到返回空列表,任何一个参数为null返回null * @since 4.0.13 */ - public static List getAllGroups(Pattern pattern, CharSequence content, boolean withGroup0) { + public static List getAllGroups(final Pattern pattern, final CharSequence content, final boolean withGroup0) { return getAllGroups(pattern, content, withGroup0, false); } @@ -211,12 +211,12 @@ public class ReUtil { * @return 匹配后得到的字符串数组,按照分组顺序依次列出,未匹配到返回空列表,任何一个参数为null返回null * @since 4.0.13 */ - public static List getAllGroups(Pattern pattern, CharSequence content, boolean withGroup0, boolean findAll) { + public static List getAllGroups(final Pattern pattern, final CharSequence content, final boolean withGroup0, final boolean findAll) { if (null == content || null == pattern) { return null; } - ArrayList result = new ArrayList<>(); + final ArrayList result = new ArrayList<>(); final Matcher matcher = pattern.matcher(content); while (matcher.find()) { final int startGroup = withGroup0 ? 0 : 1; @@ -893,7 +893,6 @@ public class ReUtil { /** * 替换所有正则匹配的文本,并使用自定义函数决定如何替换
                    * replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。 - *

                    *

                     	 *     replaceAll(this.content, "(\\d+)", parameters -> "-" + parameters.group(1) + "-")
                     	 *     // 结果为:"ZZZaaabbbccc中文-1234-"
                    @@ -912,7 +911,6 @@ public class ReUtil {
                     	/**
                     	 * 替换所有正则匹配的文本,并使用自定义函数决定如何替换
                    * replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。 - *

                    *

                     	 *     replaceAll(this.content, "(\\d+)", parameters -> "-" + parameters.group(1) + "-")
                     	 *     // 结果为:"ZZZaaabbbccc中文-1234-"