From c65e928db8f9b63a670ff4c607891292a8008cbd Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 25 Dec 2024 18:50:41 +0800 Subject: [PATCH 01/29] prepare 5.8.36 --- CHANGELOG.md | 6 ++++++ README-EN.md | 6 +++--- README.md | 6 +++--- bin/version.txt | 2 +- docs/js/version.js | 2 +- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-jwt/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 27 files changed, 36 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e384f82ff..a019d4170 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # 🚀Changelog +------------------------------------------------------------------------------------------------------------- +# 5.8.36(2024-12-25) + +### 🐣新特性 +### 🐞Bug修复 + ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) diff --git a/README-EN.md b/README-EN.md index 80a055aef..b22814afe 100755 --- a/README-EN.md +++ b/README-EN.md @@ -153,18 +153,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 5.8.35 + 5.8.36 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.35' +implementation 'cn.hutool:hutool-all:5.8.36' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.35/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.36/) > 🔔️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 9034505b0..02d05218e 100755 --- a/README.md +++ b/README.md @@ -146,20 +146,20 @@ Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,“Hu cn.hutool hutool-all - 5.8.35 + 5.8.36 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.35' +implementation 'cn.hutool:hutool-all:5.8.36' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.35/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.36/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 8ce621ecf..e37cbd6e4 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.8.35 +5.8.36 diff --git a/docs/js/version.js b/docs/js/version.js index d677c5f76..e09850eba 100755 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.8.35' \ No newline at end of file +var version = '5.8.36' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 95a1e8296..ededd708b 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 3b96ca4cd..35f733897 100755 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index ff6d81e10..26d28bfee 100755 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 1b8b92bd4..9995c38fd 100755 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 6e302bf30..024c7bb7e 100755 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 6ab907469..c63b6625a 100755 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index bc1ab47d9..76c631622 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 78263c982..dbae23835 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 557797fb6..b1dbf66a8 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index ee443457a..da9eebea6 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 5927c802f..a22b36a14 100755 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 564ebc22d..5f8984fe5 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 1662ffb7f..4e6eac5ca 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 281a1fc5f..51809ad64 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-json diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index 2f1fc0078..64a36d4e9 100755 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-jwt diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index f42c075b5..2222137fe 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 3166aafcb..eccfe33cc 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index e7147b9fc..e831e82e4 100755 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 8529bb999..b57b466d1 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 18a5e972e..64826b523 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 09b69acbc..31e1cdb09 100755 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 582dc12b4..8fc8c657b 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.8.35 + 5.8.36-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool From c9bbe506d97db73bfa10fdfeadfca88bea740359 Mon Sep 17 00:00:00 2001 From: miko <1059665047@qq.com> Date: Wed, 25 Dec 2024 18:18:55 +0800 Subject: [PATCH 02/29] =?UTF-8?q?MapUtil[partition][computeIfAbsentForJdk8?= =?UTF-8?q?][computeIfAbsent][entry][valuesOfKeys][clear][empty][removeNul?= =?UTF-8?q?lValue][renameKey][get/getQuietly]=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/map/MapUtilTest.java | 575 ++++++++++++++++++ 1 file changed, 575 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java index 0a9500135..746175321 100644 --- a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java @@ -3,12 +3,16 @@ package cn.hutool.core.map; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Opt; +import cn.hutool.core.lang.TypeReference; import cn.hutool.core.util.StrUtil; import lombok.Builder; import lombok.Data; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -215,6 +219,18 @@ public class MapUtilTest { assertEquals(Integer.valueOf(2), map.get("b")); } + @Test + public void ofEntriesSimpleEntryTest(){ + final Map map = MapUtil.ofEntries( + MapUtil.entry("a", 1,false), + MapUtil.entry("b", 2,false) + ); + assertEquals(2, map.size()); + + assertEquals(Integer.valueOf(1), map.get("a")); + assertEquals(Integer.valueOf(2), map.get("b")); + } + @Test public void getIntTest(){ assertThrows(NumberFormatException.class, () -> { @@ -238,6 +254,40 @@ public class MapUtilTest { assertEquals("张三", map.get("newName")); } + @Test + public void renameKeyMapEmptyNoChange() { + Map map = new HashMap<>(); + Map result = MapUtil.renameKey(map, "oldKey", "newKey"); + assertTrue(result.isEmpty()); + } + @Test + public void renameKeyOldKeyNotPresentNoChange() { + Map map = new HashMap<>(); + map.put("anotherKey", "value"); + Map result = MapUtil.renameKey(map, "oldKey", "newKey"); + assertEquals(1, result.size()); + assertEquals("value", result.get("anotherKey")); + } + + @Test + public void renameKeyOldKeyPresentNewKeyNotPresentKeyRenamed() { + Map map = new HashMap<>(); + map.put("oldKey", "value"); + Map result = MapUtil.renameKey(map, "oldKey", "newKey"); + assertEquals(1, result.size()); + assertEquals("value", result.get("newKey")); + } + + @Test + public void renameKeyNewKeyPresentThrowsException() { + Map map = new HashMap<>(); + map.put("oldKey", "value"); + map.put("newKey", "existingValue"); + assertThrows(IllegalArgumentException.class, () -> { + MapUtil.renameKey(map, "oldKey", "newKey"); + }); + } + @Test public void issue3162Test() { final Map map = new HashMap() { @@ -252,4 +302,529 @@ public class MapUtilTest { assertEquals("1", filtered.get("a")); assertEquals("2", filtered.get("b")); } + + + @Test + public void partitionNullMapThrowsException() { + assertThrows(IllegalArgumentException.class, () -> MapUtil.partition(null, 2)); + } + + @Test + public void partitionSizeZeroThrowsException() { + Map map = new HashMap<>(); + map.put("a", "1"); + assertThrows(IllegalArgumentException.class, () -> MapUtil.partition(map, 0)); + } + + @Test + public void partitionSizeNegativeThrowsException() { + Map map = new HashMap<>(); + map.put("a", "1"); + assertThrows(IllegalArgumentException.class, () -> MapUtil.partition(map, -1)); + } + + @Test + public void partitionEmptyMapReturnsEmptyList() { + Map map = new HashMap<>(); + List> result = MapUtil.partition(map, 2); + assertTrue(result.isEmpty()); + } + + @Test + public void partitionMapSizeMultipleOfSizePartitionsCorrectly() { + Map map = new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + map.put("d", "4"); + + List> result = MapUtil.partition(map, 2); + + assertEquals(2, result.size()); + assertEquals(2, result.get(0).size()); + assertEquals(2, result.get(1).size()); + } + + @Test + public void partitionMapSizeNotMultipleOfSizePartitionsCorrectly() { + Map map = new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + map.put("d", "4"); + map.put("e", "5"); + + List> result = MapUtil.partition(map, 2); + + assertEquals(3, result.size()); + assertEquals(2, result.get(0).size()); + assertEquals(2, result.get(1).size()); + assertEquals(1, result.get(2).size()); + } + + @Test + public void partitionGeneralCasePartitionsCorrectly() { + Map map = new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + map.put("d", "4"); + map.put("e", "5"); + map.put("f", "6"); + + List> result = MapUtil.partition(map, 3); + + assertEquals(2, result.size()); + assertEquals(3, result.get(0).size()); + assertEquals(3, result.get(1).size()); + } + + + // ---------MapUtil.computeIfAbsentForJdk8 + @Test + public void computeIfAbsentForJdk8KeyExistsReturnsExistingValue() { + Map map = new HashMap<>(); + map.put("key", 10); + Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); + assertEquals(10, result); + } + + @Test + public void computeIfAbsentForJdk8KeyDoesNotExistComputesAndInsertsValue() { + Map map = new HashMap<>(); + Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); + assertEquals(20, result); + assertEquals(20, map.get("key")); + } + + @Test + public void computeIfAbsentForJdk8ConcurrentInsertReturnsOldValue() { + ConcurrentHashMap concurrentMap = new ConcurrentHashMap<>(); + concurrentMap.put("key", 30); + AtomicInteger counter = new AtomicInteger(0); + + // 模拟并发插入 + concurrentMap.computeIfAbsent("key", k -> { + counter.incrementAndGet(); + return 40; + }); + + Integer result = MapUtil.computeIfAbsentForJdk8(concurrentMap, "key", k -> 50); + assertEquals(30, result); + assertEquals(30, concurrentMap.get("key")); + assertEquals(0, counter.get()); + } + + @Test + public void computeIfAbsentForJdk8NullValueComputesAndInsertsValue() { + Map map = new HashMap<>(); + map.put("key", null); + Integer result = MapUtil.computeIfAbsentForJdk8(map, "key", k -> 20); + assertEquals(20, result); + assertEquals(20, map.get("key")); + } + + //--------MapUtil.computeIfAbsent + @Test + public void computeIfAbsentKeyExistsReturnsExistingValue() { + Map map = new HashMap<>(); + map.put("key", 10); + Integer result = MapUtil.computeIfAbsent(map, "key", k -> 20); + assertEquals(10, result); + } + + @Test + public void computeIfAbsentKeyDoesNotExistComputesAndInsertsValue() { + Map map = new HashMap<>(); + Integer result = MapUtil.computeIfAbsent(map, "key", k -> 20); + assertEquals(20, result); + assertEquals(20, map.get("key")); + } + + @Test + public void computeIfAbsentConcurrentInsertReturnsOldValue() { + ConcurrentHashMap concurrentMap = new ConcurrentHashMap<>(); + concurrentMap.put("key", 30); + AtomicInteger counter = new AtomicInteger(0); + + // 模拟并发插入 + concurrentMap.computeIfAbsent("key", k -> { + counter.incrementAndGet(); + return 40; + }); + + Integer result = MapUtil.computeIfAbsent(concurrentMap, "key", k -> 50); + assertEquals(30, result); + assertEquals(30, concurrentMap.get("key")); + assertEquals(0, counter.get()); + } + + @Test + public void computeIfAbsentNullValueComputesAndInsertsValue() { + Map map = new HashMap<>(); + map.put("key", null); + Integer result = MapUtil.computeIfAbsent(map, "key", k -> 20); + assertEquals(20, result); + assertEquals(20, map.get("key")); + } + + @Test + public void computeIfAbsentEmptyMapInsertsValue() { + Map map = new HashMap<>(); + Integer result = MapUtil.computeIfAbsent(map, "newKey", k -> 100); + assertEquals(100, result); + assertEquals(100, map.get("newKey")); + } + + @Test + public void computeIfAbsentJdk8KeyExistsReturnsExistingValue() { + Map map = new HashMap<>(); + // 假设JdkUtil.ISJDK8为true + map.put("key", 10); + Integer result = MapUtil.computeIfAbsent(map, "key", k -> 20); + assertEquals(10, result); + } + + @Test + public void computeIfAbsentJdk8KeyDoesNotExistComputesAndInsertsValue() { + Map map = new HashMap<>(); + // 假设JdkUtil.ISJDK8为true + Integer result = MapUtil.computeIfAbsent(map, "key", k -> 20); + assertEquals(20, result); + assertEquals(20, map.get("key")); + } + + + //----------valuesOfKeys + @Test + public void valuesOfKeysEmptyIteratorReturnsEmptyList() { + Map map= new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + Iterator emptyIterator = new ArrayList().iterator(); + ArrayList result = MapUtil.valuesOfKeys(map, emptyIterator); + assertEquals(new ArrayList(), result); + } + + @Test + public void valuesOfKeysNonEmptyIteratorReturnsValuesList() { + Map map= new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + Iterator iterator = new ArrayList() {{ + add("a"); + add("b"); + }}.iterator(); + ArrayList result = MapUtil.valuesOfKeys(map, iterator); + assertEquals(new ArrayList() {{ + add("1"); + add("2"); + }}, result); + } + + @Test + public void valuesOfKeysKeysNotInMapReturnsNulls() { + Map map= new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + Iterator iterator = new ArrayList() {{ + add("d"); + add("e"); + }}.iterator(); + ArrayList result = MapUtil.valuesOfKeys(map, iterator); + assertEquals(new ArrayList() {{ + add(null); + add(null); + }}, result); + } + + @Test + public void valuesOfKeysMixedKeysReturnsMixedValues() { + Map map= new HashMap<>(); + map.put("a", "1"); + map.put("b", "2"); + map.put("c", "3"); + Iterator iterator = new ArrayList() {{ + add("a"); + add("d"); + add("b"); + }}.iterator(); + ArrayList result = MapUtil.valuesOfKeys(map, iterator); + assertEquals(new ArrayList() {{ + add("1"); + add(null); + add("2"); + }}, result); + } + + //--------clear + @Test + public void clearNoMapsProvidedNoAction() { + MapUtil.clear(); + // 预期没有异常发生,且没有Map被处理 + } + + @Test + public void clearEmptyMapNoChange() { + Map map= new HashMap<>(); + MapUtil.clear(map); + assertTrue(map.isEmpty()); + } + + @Test + public void clearNonEmptyMapClearsMap() { + Map map= new HashMap<>(); + map.put("key", "value"); + MapUtil.clear(map); + assertTrue(map.isEmpty()); + } + + @Test + public void clearMultipleMapsClearsNonEmptyMaps() { + Map map1 = new HashMap<>(); + map1.put("key1", "value1"); + + Map map2 = new HashMap<>(); + map2.put("key2", "value2"); + + Map map3 = new HashMap<>(); + + MapUtil.clear(map1, map2, map3); + + assertTrue(map1.isEmpty()); + assertTrue(map2.isEmpty()); + assertTrue(map3.isEmpty()); + } + + @Test + public void clearMixedMapsClearsNonEmptyMaps() { + Map map= new HashMap<>(); + map.put("key", "value"); + + Map emptyMap = new HashMap<>(); + + MapUtil.clear(map, emptyMap); + + assertTrue(map.isEmpty()); + assertTrue(emptyMap.isEmpty()); + } + + //-----empty + + @Test + public void emptyNoParametersReturnsEmptyMap() { + Map emptyMap = MapUtil.empty(); + assertTrue(emptyMap.isEmpty(), "The map should be empty."); + assertSame(Collections.emptyMap(), emptyMap, "The map should be the same instance as Collections.emptyMap()."); + } + + @Test + public void emptyNullMapClassReturnsEmptyMap() { + Map emptyMap = MapUtil.empty(null); + assertTrue(emptyMap.isEmpty(), "The map should be empty."); + assertSame(Collections.emptyMap(), emptyMap, "The map should be the same instance as Collections.emptyMap()."); + } + + @Test + public void emptyNavigableMapClassReturnsEmptyNavigableMap() { + Map map = MapUtil.empty(NavigableMap.class); + assertTrue(map.isEmpty()); + assertInstanceOf(NavigableMap.class, map); + } + + @Test + public void emptySortedMapClassReturnsEmptySortedMap() { + Map map = MapUtil.empty(SortedMap.class); + assertTrue(map.isEmpty()); + assertInstanceOf(SortedMap.class, map); + } + + @Test + public void emptyMapClassReturnsEmptyMap() { + Map map = MapUtil.empty(Map.class); + assertTrue(map.isEmpty()); + } + + @Test + public void emptyUnsupportedMapClassThrowsIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> { + MapUtil.empty(TreeMap.class); + }); + } + + //--------removeNullValue + @Test + public void removeNullValueNullMapReturnsNull() { + Map result = MapUtil.removeNullValue(null); + assertNull(result); + } + + @Test + public void removeNullValueEmptyMapReturnsEmptyMap() { + Map map= new HashMap<>(); + Map result = MapUtil.removeNullValue(map); + assertEquals(0, result.size()); + } + + @Test + public void removeNullValueNoNullValuesReturnsSameMap() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", "value2"); + + Map result = MapUtil.removeNullValue(map); + + assertEquals(2, result.size()); + assertEquals("value1", result.get("key1")); + assertEquals("value2", result.get("key2")); + } + + @Test + public void removeNullValueWithNullValuesRemovesNullEntries() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", null); + map.put("key3", "value3"); + + Map result = MapUtil.removeNullValue(map); + + assertEquals(2, result.size()); + assertEquals("value1", result.get("key1")); + assertEquals("value3", result.get("key3")); + assertNull(result.get("key2")); + } + + @Test + public void removeNullValueAllNullValuesReturnsEmptyMap() { + Map map= new HashMap<>(); + map.put("key1", null); + map.put("key2", null); + + Map result = MapUtil.removeNullValue(map); + + assertEquals(0, result.size()); + } + + + //------getQuietly + @Test + public void getQuietlyMapIsNullReturnsDefaultValue() { + String result = MapUtil.getQuietly(null, "key1", new TypeReference() {}, "default"); + assertEquals("default", result); + result = MapUtil.getQuietly(null, "key1", String.class, "default"); + assertEquals("default", result); + } + + @Test + public void getQuietlyKeyExistsReturnsConvertedValue() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", 123); + String result = MapUtil.getQuietly(map, "key1", new TypeReference() {}, "default"); + assertEquals("value1", result); + } + + @Test + public void getQuietlyKeyDoesNotExistReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", 123); + String result = MapUtil.getQuietly(map, "key3", new TypeReference() {}, "default"); + assertEquals("default", result); + } + + @Test + public void getQuietlyConversionFailsReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", 123); + Integer result = MapUtil.getQuietly(map, "key1", new TypeReference() {}, 0); + assertEquals(0, result); + } + + @Test + public void getQuietlyKeyExistsWithCorrectTypeReturnsValue() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", 123); + Integer result = MapUtil.getQuietly(map, "key2", new TypeReference() {}, 0); + assertEquals(123, result); + } + + @Test + public void getQuietlyKeyExistsWithNullValueReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("key1", "value1"); + map.put("key2", 123); + map.put("key3", null); + String result = MapUtil.getQuietly(map, "key3", new TypeReference() {}, "default"); + assertEquals("default", result); + } + + @Test + public void getMapIsNullReturnsDefaultValue() { + assertNull(MapUtil.get(null, "age", String.class)); + } + + @Test + public void getKeyExistsReturnsConvertedValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals("18", MapUtil.get(map, "age", String.class)); + } + + @Test + public void getKeyDoesNotExistReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals("default", MapUtil.get(map, "nonexistent", String.class, "default")); + } + + @Test + public void getTypeConversionFailsReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals(18, MapUtil.get(map, "age", Integer.class, 0)); + } + + @Test + public void getQuietlyTypeConversionFailsReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals(0, MapUtil.getQuietly(map, "name", Integer.class, 0)); + } + + @Test + public void getTypeReferenceReturnsConvertedValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals("18", MapUtil.get(map, "age", new TypeReference() {})); + } + + @Test + public void getTypeReferenceWithDefaultValueReturnsConvertedValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals("18", MapUtil.get(map, "age", new TypeReference() {}, "default")); + } + + @Test + public void getTypeReferenceWithDefaultValueTypeConversionFailsReturnsDefaultValue() { + Map map= new HashMap<>(); + map.put("age", "18"); + map.put("name", "Hutool"); + assertEquals(18, MapUtil.get(map, "age", new TypeReference() {}, 0)); + + map = null; + assertEquals(0, MapUtil.get(map, "age", new TypeReference() {}, 0)); + } } From 46fa4a12958c4fa1332a8bac6d2eb3e29066a7fa Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 26 Dec 2024 18:24:50 +0800 Subject: [PATCH 03/29] add test --- .../java/cn/hutool/core/map/MapUtilTest.java | 201 ++++++++++-------- 1 file changed, 118 insertions(+), 83 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java index 746175321..3082e0979 100644 --- a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java @@ -7,7 +7,6 @@ import cn.hutool.core.lang.TypeReference; import cn.hutool.core.util.StrUtil; import lombok.Builder; import lombok.Data; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.*; @@ -65,10 +64,10 @@ public class MapUtilTest { public void mapTest() { // Add test like a foreigner final Map adjectivesMap = MapUtil.builder() - .put(0, "lovely") - .put(1, "friendly") - .put(2, "happily") - .build(); + .put(0, "lovely") + .put(1, "friendly") + .put(2, "happily") + .build(); final Map resultMap = MapUtil.map(adjectivesMap, (k, v) -> v + " " + PeopleEnum.values()[k].name().toLowerCase()); @@ -84,7 +83,7 @@ public class MapUtilTest { final Map idUserMap = Stream.iterate(0L, i -> ++i).limit(4).map(i -> User.builder().id(i).name(customers.poll()).build()).collect(Collectors.toMap(User::getId, Function.identity())); // 如你所见,它是一个map,key由分组id,value由用户ids组成,典型的多对多关系 final Map> groupIdUserIdsMap = groups.stream().flatMap(group -> idUserMap.keySet().stream().map(userId -> UserGroup.builder().groupId(group.getId()).userId(userId).build())) - .collect(Collectors.groupingBy(UserGroup::getGroupId, Collectors.mapping(UserGroup::getUserId, Collectors.toList()))); + .collect(Collectors.groupingBy(UserGroup::getGroupId, Collectors.mapping(UserGroup::getUserId, Collectors.toList()))); // 神奇的魔法发生了, 分组id和用户ids组成的map,竟然变成了订单编号和用户实体集合组成的map final Map> groupIdUserMap = MapUtil.map(groupIdUserIdsMap, (groupId, userIds) -> userIds.stream().map(idUserMap::get).collect(Collectors.toList())); @@ -194,11 +193,11 @@ public class MapUtilTest { } @Test - public void sortJoinTest(){ + public void sortJoinTest() { final Map build = MapUtil.builder(new HashMap()) - .put("key1", "value1") - .put("key3", "value3") - .put("key2", "value2").build(); + .put("key1", "value1") + .put("key3", "value3") + .put("key2", "value2").build(); final String join1 = MapUtil.sortJoin(build, StrUtil.EMPTY, StrUtil.EMPTY, false); assertEquals("key1value1key2value2key3value3", join1); @@ -211,7 +210,7 @@ public class MapUtilTest { } @Test - public void ofEntriesTest(){ + public void ofEntriesTest() { final Map map = MapUtil.ofEntries(MapUtil.entry("a", 1), MapUtil.entry("b", 2)); assertEquals(2, map.size()); @@ -220,10 +219,10 @@ public class MapUtilTest { } @Test - public void ofEntriesSimpleEntryTest(){ + public void ofEntriesSimpleEntryTest() { final Map map = MapUtil.ofEntries( - MapUtil.entry("a", 1,false), - MapUtil.entry("b", 2,false) + MapUtil.entry("a", 1, false), + MapUtil.entry("b", 2, false) ); assertEquals(2, map.size()); @@ -232,7 +231,7 @@ public class MapUtilTest { } @Test - public void getIntTest(){ + public void getIntTest() { assertThrows(NumberFormatException.class, () -> { final HashMap map = MapUtil.of("age", "d"); final Integer age = MapUtil.getInt(map, "age"); @@ -256,13 +255,14 @@ public class MapUtilTest { @Test public void renameKeyMapEmptyNoChange() { - Map map = new HashMap<>(); + Map map = new HashMap<>(); Map result = MapUtil.renameKey(map, "oldKey", "newKey"); assertTrue(result.isEmpty()); } + @Test public void renameKeyOldKeyNotPresentNoChange() { - Map map = new HashMap<>(); + Map map = new HashMap<>(); map.put("anotherKey", "value"); Map result = MapUtil.renameKey(map, "oldKey", "newKey"); assertEquals(1, result.size()); @@ -271,7 +271,7 @@ public class MapUtilTest { @Test public void renameKeyOldKeyPresentNewKeyNotPresentKeyRenamed() { - Map map = new HashMap<>(); + Map map = new HashMap<>(); map.put("oldKey", "value"); Map result = MapUtil.renameKey(map, "oldKey", "newKey"); assertEquals(1, result.size()); @@ -280,7 +280,7 @@ public class MapUtilTest { @Test public void renameKeyNewKeyPresentThrowsException() { - Map map = new HashMap<>(); + Map map = new HashMap<>(); map.put("oldKey", "value"); map.put("newKey", "existingValue"); assertThrows(IllegalArgumentException.class, () -> { @@ -292,11 +292,13 @@ public class MapUtilTest { public void issue3162Test() { final Map map = new HashMap() { private static final long serialVersionUID = 1L; + { - put("a", "1"); - put("b", "2"); - put("c", "3"); - }}; + put("a", "1"); + put("b", "2"); + put("c", "3"); + } + }; final Map filtered = MapUtil.filter(map, "a", "b"); assertEquals(2, filtered.size()); assertEquals("1", filtered.get("a")); @@ -498,66 +500,89 @@ public class MapUtilTest { //----------valuesOfKeys @Test public void valuesOfKeysEmptyIteratorReturnsEmptyList() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("a", "1"); map.put("b", "2"); map.put("c", "3"); - Iterator emptyIterator = new ArrayList().iterator(); + Iterator emptyIterator = Collections.emptyIterator(); ArrayList result = MapUtil.valuesOfKeys(map, emptyIterator); assertEquals(new ArrayList(), result); } @Test public void valuesOfKeysNonEmptyIteratorReturnsValuesList() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("a", "1"); map.put("b", "2"); map.put("c", "3"); - Iterator iterator = new ArrayList() {{ - add("a"); - add("b"); - }}.iterator(); + Iterator iterator = new ArrayList() { + private static final long serialVersionUID = -4593258366224032110L; + + { + add("a"); + add("b"); + } + }.iterator(); ArrayList result = MapUtil.valuesOfKeys(map, iterator); - assertEquals(new ArrayList() {{ - add("1"); - add("2"); - }}, result); + assertEquals(new ArrayList() { + private static final long serialVersionUID = 7218152799308667271L; + + { + add("1"); + add("2"); + } + }, result); } @Test public void valuesOfKeysKeysNotInMapReturnsNulls() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("a", "1"); map.put("b", "2"); map.put("c", "3"); - Iterator iterator = new ArrayList() {{ - add("d"); - add("e"); - }}.iterator(); + Iterator iterator = new ArrayList() { + private static final long serialVersionUID = -5479427021989481058L; + + { + add("d"); + add("e"); + } + }.iterator(); ArrayList result = MapUtil.valuesOfKeys(map, iterator); - assertEquals(new ArrayList() {{ - add(null); - add(null); - }}, result); + assertEquals(new ArrayList() { + private static final long serialVersionUID = 4390715387901549136L; + + { + add(null); + add(null); + } + }, result); } @Test public void valuesOfKeysMixedKeysReturnsMixedValues() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("a", "1"); map.put("b", "2"); map.put("c", "3"); - Iterator iterator = new ArrayList() {{ - add("a"); - add("d"); - add("b"); - }}.iterator(); + Iterator iterator = new ArrayList() { + private static final long serialVersionUID = 8510595063492828968L; + + { + add("a"); + add("d"); + add("b"); + } + }.iterator(); ArrayList result = MapUtil.valuesOfKeys(map, iterator); - assertEquals(new ArrayList() {{ - add("1"); - add(null); - add("2"); - }}, result); + assertEquals(new ArrayList() { + private static final long serialVersionUID = 6383576410597048337L; + { + add("1"); + add(null); + add("2"); + } + }, result); } //--------clear @@ -569,14 +594,14 @@ public class MapUtilTest { @Test public void clearEmptyMapNoChange() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); MapUtil.clear(map); assertTrue(map.isEmpty()); } @Test public void clearNonEmptyMapClearsMap() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key", "value"); MapUtil.clear(map); assertTrue(map.isEmpty()); @@ -601,7 +626,7 @@ public class MapUtilTest { @Test public void clearMixedMapsClearsNonEmptyMaps() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key", "value"); Map emptyMap = new HashMap<>(); @@ -664,14 +689,14 @@ public class MapUtilTest { @Test public void removeNullValueEmptyMapReturnsEmptyMap() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); Map result = MapUtil.removeNullValue(map); assertEquals(0, result.size()); } @Test public void removeNullValueNoNullValuesReturnsSameMap() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", "value2"); @@ -684,7 +709,7 @@ public class MapUtilTest { @Test public void removeNullValueWithNullValuesRemovesNullEntries() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", null); map.put("key3", "value3"); @@ -699,7 +724,7 @@ public class MapUtilTest { @Test public void removeNullValueAllNullValuesReturnsEmptyMap() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", null); map.put("key2", null); @@ -712,7 +737,8 @@ public class MapUtilTest { //------getQuietly @Test public void getQuietlyMapIsNullReturnsDefaultValue() { - String result = MapUtil.getQuietly(null, "key1", new TypeReference() {}, "default"); + String result = MapUtil.getQuietly(null, "key1", new TypeReference() { + }, "default"); assertEquals("default", result); result = MapUtil.getQuietly(null, "key1", String.class, "default"); assertEquals("default", result); @@ -720,47 +746,52 @@ public class MapUtilTest { @Test public void getQuietlyKeyExistsReturnsConvertedValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", 123); - String result = MapUtil.getQuietly(map, "key1", new TypeReference() {}, "default"); + String result = MapUtil.getQuietly(map, "key1", new TypeReference() { + }, "default"); assertEquals("value1", result); } @Test public void getQuietlyKeyDoesNotExistReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", 123); - String result = MapUtil.getQuietly(map, "key3", new TypeReference() {}, "default"); + String result = MapUtil.getQuietly(map, "key3", new TypeReference() { + }, "default"); assertEquals("default", result); } @Test public void getQuietlyConversionFailsReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", 123); - Integer result = MapUtil.getQuietly(map, "key1", new TypeReference() {}, 0); + Integer result = MapUtil.getQuietly(map, "key1", new TypeReference() { + }, 0); assertEquals(0, result); } @Test public void getQuietlyKeyExistsWithCorrectTypeReturnsValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", 123); - Integer result = MapUtil.getQuietly(map, "key2", new TypeReference() {}, 0); + Integer result = MapUtil.getQuietly(map, "key2", new TypeReference() { + }, 0); assertEquals(123, result); } @Test public void getQuietlyKeyExistsWithNullValueReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", 123); map.put("key3", null); - String result = MapUtil.getQuietly(map, "key3", new TypeReference() {}, "default"); + String result = MapUtil.getQuietly(map, "key3", new TypeReference() { + }, "default"); assertEquals("default", result); } @@ -771,7 +802,7 @@ public class MapUtilTest { @Test public void getKeyExistsReturnsConvertedValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); assertEquals("18", MapUtil.get(map, "age", String.class)); @@ -779,7 +810,7 @@ public class MapUtilTest { @Test public void getKeyDoesNotExistReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); assertEquals("default", MapUtil.get(map, "nonexistent", String.class, "default")); @@ -787,7 +818,7 @@ public class MapUtilTest { @Test public void getTypeConversionFailsReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); assertEquals(18, MapUtil.get(map, "age", Integer.class, 0)); @@ -795,7 +826,7 @@ public class MapUtilTest { @Test public void getQuietlyTypeConversionFailsReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); assertEquals(0, MapUtil.getQuietly(map, "name", Integer.class, 0)); @@ -803,28 +834,32 @@ public class MapUtilTest { @Test public void getTypeReferenceReturnsConvertedValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); - assertEquals("18", MapUtil.get(map, "age", new TypeReference() {})); + assertEquals("18", MapUtil.get(map, "age", new TypeReference() { + })); } @Test public void getTypeReferenceWithDefaultValueReturnsConvertedValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); - assertEquals("18", MapUtil.get(map, "age", new TypeReference() {}, "default")); + assertEquals("18", MapUtil.get(map, "age", new TypeReference() { + }, "default")); } @Test public void getTypeReferenceWithDefaultValueTypeConversionFailsReturnsDefaultValue() { - Map map= new HashMap<>(); + Map map = new HashMap<>(); map.put("age", "18"); map.put("name", "Hutool"); - assertEquals(18, MapUtil.get(map, "age", new TypeReference() {}, 0)); + assertEquals(18, MapUtil.get(map, "age", new TypeReference() { + }, 0)); map = null; - assertEquals(0, MapUtil.get(map, "age", new TypeReference() {}, 0)); + assertEquals(0, MapUtil.get(map, "age", new TypeReference() { + }, 0)); } } From 12b56a38417f0682a95f1f2cd1250bd8d0add92e Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 1 Jan 2025 18:39:50 +0800 Subject: [PATCH 04/29] =?UTF-8?q?=E5=A2=9E=E5=8A=A0BCUtil.decodeECPrivateK?= =?UTF-8?q?ey=E6=96=B9=E6=B3=95=EF=BC=88issue#3829@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- .../main/java/cn/hutool/crypto/BCUtil.java | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a019d4170..83cf0736a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2024-12-25) +# 5.8.36(2025-01-01) ### 🐣新特性 +* 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) ### 🐞Bug修复 ------------------------------------------------------------------------------------------------------------- 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 1b603cc09..f1fb2a1ae 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java @@ -14,7 +14,9 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.jce.spec.ECPrivateKeySpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.util.BigIntegers; import java.io.IOException; import java.io.InputStream; @@ -44,6 +46,27 @@ public class BCUtil { return ((BCECPrivateKey) privateKey).getD().toByteArray(); } + /** + * 解码恢复EC私钥,支持Base64和Hex编码,(基于BouncyCastle) + * + * @param d 私钥d值 + * @param curveName EC曲线名 + * @return 私钥 + * @since 5.8.36 + */ + public static PrivateKey decodeECPrivateKey(final byte[] d, final String curveName) { + final X9ECParameters x9ECParameters = ECUtil.getNamedCurveByName(curveName); + final ECParameterSpec ecSpec = new ECParameterSpec( + x9ECParameters.getCurve(), + x9ECParameters.getG(), + x9ECParameters.getN(), + x9ECParameters.getH() + ); + + final ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(BigIntegers.fromUnsignedByteArray(d), ecSpec); + return KeyUtil.generatePrivateKey("EC", privateKeySpec); + } + /** * 编码压缩EC公钥(基于BouncyCastle),即Q值
* 见:https://www.cnblogs.com/xinzhao/p/8963724.html From 2500d5307c4f1a3190e5a2c32919f7c4d5bc8f21 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 1 Jan 2025 23:48:53 +0800 Subject: [PATCH 05/29] fix sh --- bin/javadoc.sh | 5 +++++ hutool-json/src/main/java/cn/hutool/json/JSON.java | 1 + pom.xml | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/javadoc.sh b/bin/javadoc.sh index 38eb2b683..0341e1d22 100755 --- a/bin/javadoc.sh +++ b/bin/javadoc.sh @@ -4,3 +4,8 @@ # 多模块聚合文档,生成在target/site/apidocs exec mvn javadoc:aggregate + +bin_home="$(dirname ${BASH_SOURCE[0]})" + +# 拷贝自定义的index.html到聚合文档目录 +cp -vf $bin_home/../docs/apidocs/index.html $bin_home/../target/reports/apidocs/ diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java index 9a5972cc9..3034902d8 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSON.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java @@ -117,6 +117,7 @@ public interface JSON extends Cloneable, Serializable, IJSONTypeConverter { * * @param expression 表达式 * @param targetType 返回值类型 + * @param 获取对象类型 * @return 对象 * @see BeanPath#get(Object) * @since 5.8.34 diff --git a/pom.xml b/pom.xml index 8fc8c657b..57b32548a 100755 --- a/pom.xml +++ b/pom.xml @@ -126,7 +126,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.8.0 + 3.11.2 package From 8c81e43a071a74c4b44a96750a614167050c7193 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 2 Jan 2025 13:33:02 +0800 Subject: [PATCH 06/29] =?UTF-8?q?=E4=BF=AE=E5=A4=8DProxyUtil=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E7=9A=84=E7=A9=BA=E6=8C=87=E9=92=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=88issue#IBF20Z@Gitee=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../cn/hutool/aop/proxy/JdkProxyFactory.java | 5 ++ .../cn/hutool/aop/proxy/ProxyFactory.java | 8 ++- .../cn/hutool/aop/test/IssueIBF20ZTest.java | 49 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 83cf0736a..36d0cb044 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-01) +# 5.8.36(2025-01-02) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) ### 🐞Bug修复 +* 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) diff --git a/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java b/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java index 91a5a7129..166b45e2a 100755 --- a/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java +++ b/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java @@ -12,6 +12,11 @@ import cn.hutool.aop.interceptor.JdkInterceptor; public class JdkProxyFactory extends ProxyFactory { private static final long serialVersionUID = 1L; + /** + * 获取单例 + */ + public static JdkProxyFactory INSTANCE = new JdkProxyFactory(); + @Override public T proxy(T target, Aspect aspect) { return ProxyUtil.newProxyInstance(// diff --git a/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java b/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java index 96d988971..db45b9d45 100755 --- a/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java +++ b/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java @@ -59,7 +59,13 @@ public abstract class ProxyFactory implements Serializable { * @return 代理对象 */ public static T createProxy(T target, Aspect aspect) { - return create().proxy(target, aspect); + ProxyFactory factory = create(); + if(null == factory){ + // issue#IBF20Z + // 可能的空指针问题 + factory = JdkProxyFactory.INSTANCE; + } + return factory.proxy(target, aspect); } /** diff --git a/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java b/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java new file mode 100644 index 000000000..22a246809 --- /dev/null +++ b/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java @@ -0,0 +1,49 @@ +package cn.hutool.aop.test; + +import cn.hutool.aop.proxy.ProxyFactory; +import cn.hutool.core.lang.Console; +import cn.hutool.core.thread.ThreadUtil; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class IssueIBF20ZTest { + + @Test + public void testLoadFirstAvailableConcurrent() throws InterruptedException { + // 创建一个固定大小的线程池 + int threadCount = 1000; + ExecutorService executorService = ThreadUtil.newExecutor(threadCount); + + // 创建一个 CountDownLatch,用于等待所有任务完成 + CountDownLatch latch = new CountDownLatch(threadCount); + + // 计数器用于统计成功加载服务提供者的次数 + AtomicInteger successCount = new AtomicInteger(0); + + // 提交多个任务到线程池 + for (int i = 0; i < threadCount; i++) { + executorService.submit(() -> { + ProxyFactory factory = ProxyFactory.create(); + if (factory != null) { + Console.log(factory.getClass()); + successCount.incrementAndGet(); + } + latch.countDown(); // 每个任务完成时,计数减一 + }); + } + + // 等待所有任务完成 + latch.await(); + + // 关闭线程池并等待所有任务完成 + executorService.shutdown(); + + // 验证所有线程都成功加载了服务提供者 + assertEquals(threadCount, successCount.get()); + } +} From 307670b50d200df6432c889679be02152964f7b9 Mon Sep 17 00:00:00 2001 From: "Zhenheng.Xie" Date: Thu, 9 Jan 2025 17:09:23 +0800 Subject: [PATCH 07/29] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20XmlUtil=20?= =?UTF-8?q?=E4=B8=AD=E8=BD=AC=E4=B9=89/=E5=8F=8D=E8=BD=AC=E4=B9=89?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E9=94=99=E8=AF=AF=E8=B0=83=E7=94=A8=20html4?= =?UTF-8?q?=20=E8=BD=AC=E4=B9=89/=E5=8F=8D=E8=BD=AC=E4=B9=89=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82html4=20=E8=BD=AC?= =?UTF-8?q?=E4=B9=89=E4=BC=9A=E5=B0=86=E4=B8=AD=E6=96=87=E5=8F=8C=E5=BC=95?= =?UTF-8?q?=E5=8F=B7=E7=AD=89=E5=AD=97=E7=AC=A6=E8=BD=AC=E4=B9=89=E4=B8=BA?= =?UTF-8?q?=20xml=20=E6=97=A0=E6=B3=95=E8=AF=86=E5=88=AB=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=EF=BC=8C=E4=BB=8E=E8=80=8C=E5=AF=BC=E8=87=B4=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=20xml=20=E6=97=B6=E5=87=BA=E7=8E=B0=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java | 5 +++-- .../src/test/java/cn/hutool/core/util/XmlUtilTest.java | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) 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 1b42ff9a3..1d77b0012 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 @@ -956,6 +956,7 @@ public class XmlUtil { * < (小于) 替换为 &lt; * > (大于) 替换为 &gt; * " (双引号) 替换为 &quot; + * ' (单引号) 替换为 &apos; * * * @param string 被替换的字符串 @@ -963,7 +964,7 @@ public class XmlUtil { * @since 4.0.8 */ public static String escape(String string) { - return EscapeUtil.escapeHtml4(string); + return EscapeUtil.escapeXml(string); } /** @@ -975,7 +976,7 @@ public class XmlUtil { * @since 5.0.6 */ public static String unescape(String string) { - return EscapeUtil.unescapeHtml4(string); + return EscapeUtil.unescapeXml(string); } /** 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 6f0932082..cb7a2d9f5 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 @@ -320,6 +320,7 @@ public class XmlUtilTest { final String a = "<>"; final String escape = XmlUtil.escape(a); Console.log(escape); + Console.log(XmlUtil.escape("中文“双引号”")); } @Test From f4cf4dc21fac347393f8997d867767f5f475b353 Mon Sep 17 00:00:00 2001 From: "Zhenheng.Xie" Date: Thu, 9 Jan 2025 17:12:51 +0800 Subject: [PATCH 08/29] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20XmlEscape=20?= =?UTF-8?q?=E6=9C=AA=E5=AF=B9=E5=8D=95=E5=BC=95=E5=8F=B7=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E8=BD=AC=E4=B9=89=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/text/escape/XmlEscape.java | 2 +- .../src/main/java/cn/hutool/core/text/escape/XmlUnescape.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlEscape.java b/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlEscape.java index 8aba9e2a7..461b1c90a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlEscape.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlEscape.java @@ -22,7 +22,7 @@ public class XmlEscape extends ReplacerChain { private static final long serialVersionUID = 1L; protected static final String[][] BASIC_ESCAPE = { // -// {"'", "'"}, // " - single-quote + {"'", "'"}, // " - single-quote {"\"", """}, // " - double-quote {"&", "&"}, // & - ampersand {"<", "<"}, // < - less-than diff --git a/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlUnescape.java b/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlUnescape.java index 80073a9c1..dee798851 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlUnescape.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/escape/XmlUnescape.java @@ -13,8 +13,6 @@ public class XmlUnescape extends ReplacerChain { private static final long serialVersionUID = 1L; protected static final String[][] BASIC_UNESCAPE = InternalEscapeUtil.invert(XmlEscape.BASIC_ESCAPE); - // issue#1118 - protected static final String[][] OTHER_UNESCAPE = new String[][]{new String[]{"'", "'"}}; /** * 构造 @@ -22,6 +20,5 @@ public class XmlUnescape extends ReplacerChain { public XmlUnescape() { addChain(new LookupReplacer(BASIC_UNESCAPE)); addChain(new NumericEntityUnescaper()); - addChain(new LookupReplacer(OTHER_UNESCAPE)); } } From f637ebfd5f858546f9a58ddb72206f4cf65ea066 Mon Sep 17 00:00:00 2001 From: "zehao.song" Date: Thu, 9 Jan 2025 18:07:25 +0800 Subject: [PATCH 09/29] spelling wrong --- hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java index 2735eae87..f4ca55db0 100644 --- a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java +++ b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java @@ -17,7 +17,7 @@ public class CronTest { @Test @Disabled public void customCronTest() { - CronUtil.schedule("*/2 * * * * *", (Task) () -> Console.log("Task excuted.")); + CronUtil.schedule("*/2 * * * * *", (Task) () -> Console.log("Task executed.")); // 支持秒级别定时任务 CronUtil.setMatchSecond(true); From 5befdeea3fc4fbb16bef04713577fd337e9c7bd2 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Jan 2025 19:31:23 +0800 Subject: [PATCH 10/29] =?UTF-8?q?=E4=BF=AE=E5=A4=8DXmlUtil=E8=BD=AC?= =?UTF-8?q?=E4=B9=89=E8=B0=83=E7=94=A8=E6=96=B9=E6=B3=95=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E5=A4=8DXmlEscape=E6=9C=AA?= =?UTF-8?q?=E8=BD=AC=E4=B9=89=E5=8D=95=E5=BC=95=E5=8F=B7=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=88pr#3837@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- .../cn/hutool/core/text/escape/Html4Escape.java | 16 +++++++++++++++- .../java/cn/hutool/core/util/XmlUtilTest.java | 8 +++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36d0cb044..61b3553bd 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,13 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-02) +# 5.8.36(2025-01-09) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) +* 【core 】 修复XmlUtil转义调用方法错误问题,修复XmlEscape未转义单引号问题(pr#3837@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) 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..8473e417d 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 @@ -1,6 +1,7 @@ package cn.hutool.core.text.escape; import cn.hutool.core.text.replacer.LookupReplacer; +import cn.hutool.core.text.replacer.ReplacerChain; /** * HTML4的ESCAPE @@ -9,9 +10,21 @@ import cn.hutool.core.text.replacer.LookupReplacer; * @author looly * */ -public class Html4Escape extends XmlEscape { +public class Html4Escape extends ReplacerChain { private static final long serialVersionUID = 1L; + /** + * HTML转义字符
+ * HTML转义相比XML,并不转义单引号
+ * 见:https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents + */ + protected static final String[][] BASIC_ESCAPE = { // + {"\"", """}, // " - double-quote + {"&", "&"}, // & - ampersand + {"<", "<"}, // < - less-than + {">", ">"}, // > - greater-than + }; + protected static final String[][] ISO8859_1_ESCAPE = { // { "\u00A0", " " }, // non-breaking space { "\u00A1", "¡" }, // inverted exclamation mark @@ -310,6 +323,7 @@ public class Html4Escape extends XmlEscape { public Html4Escape() { super(); + addChain(new LookupReplacer(BASIC_ESCAPE)); addChain(new LookupReplacer(ISO8859_1_ESCAPE)); addChain(new LookupReplacer(HTML40_EXTENDED_ESCAPE)); } 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 cb7a2d9f5..373aa323a 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 @@ -7,7 +7,7 @@ import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapBuilder; import cn.hutool.core.map.MapUtil; import lombok.Data; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; @@ -22,6 +22,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static org.junit.jupiter.api.Assertions.*; + /** * {@link XmlUtil} 工具类 * @@ -319,8 +321,8 @@ public class XmlUtilTest { public void escapeTest(){ final String a = "<>"; final String escape = XmlUtil.escape(a); - Console.log(escape); - Console.log(XmlUtil.escape("中文“双引号”")); + Assertions.assertEquals("<>", escape); + Assertions.assertEquals("中文“双引号”", XmlUtil.escape("中文“双引号”")); } @Test From dc13edd66336ded296a339c982f797d535685bdf Mon Sep 17 00:00:00 2001 From: freeok <51998152+freeok@users.noreply.github.com> Date: Fri, 10 Jan 2025 08:19:51 +0800 Subject: [PATCH 11/29] feat: Add cleanEmptyTag method for HtmlUtil --- .../main/java/cn/hutool/http/HtmlUtil.java | 12 ++++++++++ .../java/cn/hutool/http/HtmlUtilTest.java | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/hutool-http/src/main/java/cn/hutool/http/HtmlUtil.java b/hutool-http/src/main/java/cn/hutool/http/HtmlUtil.java index 94d429a18..9e08e360a 100755 --- a/hutool-http/src/main/java/cn/hutool/http/HtmlUtil.java +++ b/hutool-http/src/main/java/cn/hutool/http/HtmlUtil.java @@ -24,6 +24,7 @@ public class HtmlUtil { public static final String GT = StrUtil.HTML_GT; public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + public static final String RE_HTML_EMPTY_MARK = "<(\\w+)([^>]*)>\\s*"; public static final String RE_SCRIPT = "<[\\s]*?script[^>]*?>.*?<[\\s]*?\\/[\\s]*?script[\\s]*?>"; private static final char[][] TEXT = new char[256][]; @@ -86,6 +87,17 @@ public class HtmlUtil { return content.replaceAll(RE_HTML_MARK, ""); } + /** + * 清除所有HTML空标签
+ * 例如:<p></p> + * + * @param content 文本 + * @return 清除空标签后的文本 + */ + public static String cleanEmptyTag(String content) { + return content.replaceAll(RE_HTML_EMPTY_MARK, ""); + } + /** * 清除指定HTML标签和被标签包围的内容
* 不区分大小写 diff --git a/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java index 6e0d56a59..2c4487768 100644 --- a/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java @@ -77,6 +77,29 @@ public class HtmlUtilTest { assertEquals("pre\r\n\t\tdfdsfdsfdsf\r\nBBBB", result); } + @Test + public void cleanEmptyTag() { + String str = "

"; + String result = HtmlUtil.cleanEmptyTag(str); + assertEquals("", result); + + str = "

TEXT

"; + result = HtmlUtil.cleanEmptyTag(str); + assertEquals("

TEXT

", result); + + str = "

TEXT
"; + result = HtmlUtil.cleanEmptyTag(str); + assertEquals("
TEXT
", result); + + str = "

TEXT

TEXT
"; + result = HtmlUtil.cleanEmptyTag(str); + assertEquals("

TEXT

TEXT
", result); + + str = "TEXT

TEXT"; + result = HtmlUtil.cleanEmptyTag(str); + assertEquals("TEXTTEXT", result); + } + @Test public void unwrapHtmlTagTest() { //非闭合标签 From 5f57da864dc0c6f3e9d19004c0d9f689a46e17ed Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Jan 2025 09:58:29 +0800 Subject: [PATCH 12/29] =?UTF-8?q?=E5=A2=9E=E5=8A=A0HtmlUtil.cleanEmptyTag?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=88pr#3838@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61b3553bd..aa1d3e64d 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-09) +# 5.8.36(2025-01-10) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) +* 【core 】 增加HtmlUtil.cleanEmptyTag方法(pr#3838@Github) ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) * 【core 】 修复XmlUtil转义调用方法错误问题,修复XmlEscape未转义单引号问题(pr#3837@Github) diff --git a/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java index 2c4487768..585c61266 100644 --- a/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/HtmlUtilTest.java @@ -1,8 +1,9 @@ package cn.hutool.http; -import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * Html单元测试 * @@ -78,7 +79,7 @@ public class HtmlUtilTest { } @Test - public void cleanEmptyTag() { + public void cleanEmptyTagTest() { String str = "

"; String result = HtmlUtil.cleanEmptyTag(str); assertEquals("", result); From b116be492a45448d83ae26b289b3edcf7009114f Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 12 Jan 2025 17:52:42 +0800 Subject: [PATCH 13/29] =?UTF-8?q?GlobalDbSetting=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=85=8D=E7=BD=AE=E8=AF=BB=E5=8F=96=E8=A7=84?= =?UTF-8?q?=E5=88=99=EF=BC=8C=E4=BC=98=E5=85=88=E8=AF=BB=E5=8F=96=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=80=8C=E9=9D=9Ejar=E4=B8=AD=E7=9A=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=88issue#900@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++- .../hutool/core/io/resource/FileResource.java | 3 ++ .../java/cn/hutool/db/GlobalDbConfig.java | 31 +++++++++++++------ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa1d3e64d..32fee2e7a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,13 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-10) +# 5.8.36(2025-01-12) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) * 【core 】 增加HtmlUtil.cleanEmptyTag方法(pr#3838@Github) +* 【db 】 GlobalDbSetting优化默认配置读取规则,优先读取文件而非jar中的文件(issue#900@Github) + ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) * 【core 】 修复XmlUtil转义调用方法错误问题,修复XmlEscape未转义单引号问题(pr#3837@Github) 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 3fcdea20a..06b661e11 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 @@ -79,6 +79,9 @@ public class FileResource implements Resource, Serializable { @Override public InputStream getStream() throws NoResourceException { + if (!this.file.exists()) { + throw new NoResourceException("File [{}] not exist!", this.file.getAbsolutePath()); + } return FileUtil.getInputStream(this.file); } diff --git a/hutool-db/src/main/java/cn/hutool/db/GlobalDbConfig.java b/hutool-db/src/main/java/cn/hutool/db/GlobalDbConfig.java index fc720fe72..0c3ba4ba2 100644 --- a/hutool-db/src/main/java/cn/hutool/db/GlobalDbConfig.java +++ b/hutool-db/src/main/java/cn/hutool/db/GlobalDbConfig.java @@ -1,6 +1,7 @@ package cn.hutool.db; import cn.hutool.core.io.resource.NoResourceException; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.db.sql.SqlLog; import cn.hutool.log.level.Level; import cn.hutool.setting.Setting; @@ -83,20 +84,30 @@ public class GlobalDbConfig { throw new NoResourceException("Customize db setting file [{}] not found !", dbSettingPath); } } else { - try { - setting = new Setting(DEFAULT_DB_SETTING_PATH, true); - } catch (NoResourceException e) { - // 尝试ClassPath下直接读取配置文件 - try { - setting = new Setting(DEFAULT_DB_SETTING_PATH2, true); - } catch (NoResourceException e2) { - throw new NoResourceException("Default db setting [{}] or [{}] in classpath not found !", DEFAULT_DB_SETTING_PATH, DEFAULT_DB_SETTING_PATH2); - } - } + setting = tryDefaultDbSetting(); } return setting; } + /** + * 获取自定义或默认位置数据库配置{@link Setting} + * + * @return 数据库配置 + * @since 5.8.36 + */ + private static Setting tryDefaultDbSetting() { + final String[] defaultDbSettingPaths = {"file:" + DEFAULT_DB_SETTING_PATH, "file:" + DEFAULT_DB_SETTING_PATH2, DEFAULT_DB_SETTING_PATH, DEFAULT_DB_SETTING_PATH2}; + for (final String settingPath : defaultDbSettingPaths) { + try { + return new Setting(settingPath, true); + } catch (final NoResourceException e) { + // ignore + } + } + + throw new NoResourceException("Default db settings [{}] in classpath not found !", ArrayUtil.join(defaultDbSettingPaths, ",")); + } + /** * 设置全局配置:是否通过debug日志显示SQL * From c0090f7678704d67f4f022fb4b009ac0e2d8c460 Mon Sep 17 00:00:00 2001 From: vsxd Date: Mon, 13 Jan 2025 15:11:07 +0800 Subject: [PATCH 14/29] rename local var --- hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java index b52133be7..fa193ddad 100755 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java @@ -98,7 +98,7 @@ public class WordTree extends HashMap { * @return this */ public WordTree addWord(String word) { - final Filter charFilter = this.charFilter; + final Filter localCharFilter = this.charFilter; WordTree parent = null; WordTree current = this; WordTree child; @@ -106,7 +106,7 @@ public class WordTree extends HashMap { final int length = word.length(); for (int i = 0; i < length; i++) { currentChar = word.charAt(i); - if (charFilter.accept(currentChar)) {//只处理合法字符 + if (localCharFilter.accept(currentChar)) {//只处理合法字符 child = current.get(currentChar); if (child == null) { //无子类,新建一个子节点后存放下一个字符 @@ -245,7 +245,7 @@ public class WordTree extends HashMap { List foundWords = new ArrayList<>(); WordTree current = this; final int length = text.length(); - final Filter charFilter = this.charFilter; + final Filter localCharFilter = this.charFilter; //存放查找到的字符缓存。完整出现一个词时加到findedWords中,否则清空 final StringBuilder wordBuffer = StrUtil.builder(); final StringBuilder keyBuffer = StrUtil.builder(); @@ -256,7 +256,7 @@ public class WordTree extends HashMap { for (int j = i; j < length; j++) { currentChar = text.charAt(j); // Console.log("i: {}, j: {}, currentChar: {}", i, j, currentChar); - if (false == charFilter.accept(currentChar)) { + if (false == localCharFilter.accept(currentChar)) { if (wordBuffer.length() > 0) { //做为关键词中间的停顿词被当作关键词的一部分被返回 wordBuffer.append(currentChar); From 86ebc3bc2d69813da775e6f400a3eee07e454e9b Mon Sep 17 00:00:00 2001 From: vsxd Date: Mon, 13 Jan 2025 15:11:36 +0800 Subject: [PATCH 15/29] rm repeated stop chars --- .../src/main/java/cn/hutool/dfa/StopChar.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java index 9aaa7b6a9..583380653 100755 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java @@ -20,14 +20,14 @@ public class StopChar { '※', '→', '←', '↑', '↓', '↖', '↗', '↘', '↙', '〓', 'ⅰ', 'ⅱ', 'ⅲ', 'ⅳ', 'ⅴ', 'ⅵ', 'ⅶ', 'ⅷ', 'ⅸ', 'ⅹ', '①', // '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⒈', '⒉', '⒊', '⒋', '⒌', '⒍', '⒎', '⒏', '⒐', '⒑', '⒒', '⒓', // '⒔', '⒕', '⒖', '⒗', '⒘', '⒙', '⒚', '⒛', '⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀', // - '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇', 'Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', 'Ⅴ', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', 'Ⅹ', 'Ⅺ', 'Ⅻ', '!', '”', // - '#', '¥', '%', '&', '’', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', // - '8', '9', ':', ';', '<', '=', '>', '?', '@', '〔', '\', '〕', '^', '_', '‘', '{', '|', '}', '∏', 'Ρ', '∑', // + '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇', 'Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', 'Ⅴ', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', 'Ⅹ', 'Ⅺ', 'Ⅻ', '!', // + '#', '¥', '%', '&', '(', ')', '*', ',', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', // + '8', '9', ':', ';', '<', '=', '>', '?', '@', '\', '^', '_', '{', '|', '}', 'Ρ', // 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', // - 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '(', ')', '〔', '〕', '^', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', // - '', '^', '(', '^', ':', '!', '/', '\\', '\"', '<', '>', '`', '·', '。', '{', '}', '~', '~', '(', ')', '-', // - '√', '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?', - ':', '.', '!', ';', ']','|','%'); + 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', // + '/', '\\', '\"', '<', '>', '`', '{', '}', '~', '(', ')', '-', // + '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?', + ':', '.', '!', ';', ']','|','%'); /** * 判断指定的词是否是不处理的词。 如果参数为空,则返回true,因为空也属于不处理的字符。 From 7467a2cb5baf2df2bd8f80b0bf952b18cfcf986a Mon Sep 17 00:00:00 2001 From: vsxd Date: Tue, 14 Jan 2025 10:02:27 +0800 Subject: [PATCH 16/29] Revert "rename local var" This reverts commit c0090f7678704d67f4f022fb4b009ac0e2d8c460. --- hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java index fa193ddad..b52133be7 100755 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java @@ -98,7 +98,7 @@ public class WordTree extends HashMap { * @return this */ public WordTree addWord(String word) { - final Filter localCharFilter = this.charFilter; + final Filter charFilter = this.charFilter; WordTree parent = null; WordTree current = this; WordTree child; @@ -106,7 +106,7 @@ public class WordTree extends HashMap { final int length = word.length(); for (int i = 0; i < length; i++) { currentChar = word.charAt(i); - if (localCharFilter.accept(currentChar)) {//只处理合法字符 + if (charFilter.accept(currentChar)) {//只处理合法字符 child = current.get(currentChar); if (child == null) { //无子类,新建一个子节点后存放下一个字符 @@ -245,7 +245,7 @@ public class WordTree extends HashMap { List foundWords = new ArrayList<>(); WordTree current = this; final int length = text.length(); - final Filter localCharFilter = this.charFilter; + final Filter charFilter = this.charFilter; //存放查找到的字符缓存。完整出现一个词时加到findedWords中,否则清空 final StringBuilder wordBuffer = StrUtil.builder(); final StringBuilder keyBuffer = StrUtil.builder(); @@ -256,7 +256,7 @@ public class WordTree extends HashMap { for (int j = i; j < length; j++) { currentChar = text.charAt(j); // Console.log("i: {}, j: {}, currentChar: {}", i, j, currentChar); - if (false == localCharFilter.accept(currentChar)) { + if (false == charFilter.accept(currentChar)) { if (wordBuffer.length() > 0) { //做为关键词中间的停顿词被当作关键词的一部分被返回 wordBuffer.append(currentChar); From 633e6a8599f38093833fdbdc35d803ce96924e37 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 14 Jan 2025 16:35:51 +0800 Subject: [PATCH 17/29] =?UTF-8?q?=E5=88=A0=E9=99=A4StopChar=E7=B1=BB?= =?UTF-8?q?=E4=B8=AD=E5=AD=98=E5=9C=A8=E9=87=8D=E5=A4=8D=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=EF=BC=88pr#3841@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32fee2e7a..3569cac5c 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,13 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-12) +# 5.8.36(2025-01-14) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) * 【core 】 增加HtmlUtil.cleanEmptyTag方法(pr#3838@Github) * 【db 】 GlobalDbSetting优化默认配置读取规则,优先读取文件而非jar中的文件(issue#900@Github) +* 【dfa 】 删除StopChar类中存在重复字符(pr#3841@Github) ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) From 2e468781ce3119a698e1986f0b96bb6add6d86f7 Mon Sep 17 00:00:00 2001 From: Yurin Date: Thu, 16 Jan 2025 14:20:49 +0800 Subject: [PATCH 18/29] =?UTF-8?q?windows=E7=9A=84SMB=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E7=BB=9D=E5=AF=B9=E8=B7=AF=E5=BE=84bug?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/io/FileUtil.java | 9 +++++-- .../java/cn/hutool/core/io/FileUtilTest.java | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 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 b81ac8ad2..11f8f29bd 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 @@ -64,6 +64,10 @@ public class FileUtil extends PathUtil { */ private static final Pattern PATTERN_PATH_ABSOLUTE = Pattern.compile("^[a-zA-Z]:([/\\\\].*)?", Pattern.DOTALL); + /** + * windows的共享文件夹开头 + */ + private static final String SMB_PATH_PREFIX = "\\\\"; /** * 是否为Windows环境 @@ -1370,6 +1374,7 @@ public class FileUtil extends PathUtil { *
  • 以/开头的路径
  • *
  • 满足类似于 c:/xxxxx,其中祖母随意,不区分大小写
  • *
  • 满足类似于 d:\xxxxx,其中祖母随意,不区分大小写
  • + *
  • 满足windows SMB协议格式,如: \\192.168.254.1\Share
  • * * * @param path 需要检查的Path @@ -1381,7 +1386,7 @@ public class FileUtil extends PathUtil { } // 给定的路径已经是绝对路径了 - return StrUtil.C_SLASH == path.charAt(0) || ReUtil.isMatch(PATTERN_PATH_ABSOLUTE, path); + return StrUtil.C_SLASH == path.charAt(0) || path.startsWith(SMB_PATH_PREFIX) || ReUtil.isMatch(PATTERN_PATH_ABSOLUTE, path); } /** @@ -1667,7 +1672,7 @@ public class FileUtil extends PathUtil { } //兼容Windows下的共享目录路径(原始路径如果以\\开头,则保留这种路径) - if (path.startsWith("\\\\")) { + if (path.startsWith(SMB_PATH_PREFIX)) { return path; } 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 5f1fb6b7e..132c7aec5 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 @@ -53,6 +53,30 @@ public class FileUtilTest { path = FileUtil.getAbsolutePath("d:"); assertEquals("d:", path); + + } + + @Test + @Disabled + public void smbPathTest() { + String smbPath = "\\\\192.168.254.88\\share\\rc-source"; + String parseSmbPath = FileUtil.getAbsolutePath(smbPath); + assertEquals(smbPath, parseSmbPath); + String dir = smbPath + "\\test"; + + FileUtil.mkdir(dir); + assertTrue(FileUtil.exist(dir)); + String file = dir + "\\a.txt"; + FileUtil.touch(file); + FileUtil.writeString("Hello SMB", file, "UTF-8"); + + String read = FileUtil.readString(file, "UTF-8"); + assertEquals(read, "Hello SMB"); + + assertEquals(1, FileUtil.loopFiles(dir).size()); + assertEquals(1, FileUtil.ls(dir).length); + + FileUtil.del(dir); } @Test From 5c7c86897ef6f42a4c311572d4429b81bf5c5a48 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 17 Jan 2025 03:10:01 +0800 Subject: [PATCH 19/29] =?UTF-8?q?=E4=BF=AE=E5=A4=8DFileUtil.isAbsolutePath?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=88=A4=E6=96=ADsmb=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=88pr#1299@Gitee=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- .../java/cn/hutool/core/io/FileUtilTest.java | 22 ++++--------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3569cac5c..6fed90e60 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-14) +# 5.8.36(2025-01-17) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) @@ -13,6 +13,7 @@ ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) * 【core 】 修复XmlUtil转义调用方法错误问题,修复XmlEscape未转义单引号问题(pr#3837@Github) +* 【core 】 修复FileUtil.isAbsolutePath没有判断smb路径问题(pr#1299@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) 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 132c7aec5..bce768e79 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 @@ -57,26 +57,12 @@ public class FileUtilTest { } @Test - @Disabled public void smbPathTest() { - String smbPath = "\\\\192.168.254.88\\share\\rc-source"; - String parseSmbPath = FileUtil.getAbsolutePath(smbPath); + final String smbPath = "\\\\192.168.1.1\\share\\rc-source"; + final String parseSmbPath = FileUtil.getAbsolutePath(smbPath); assertEquals(smbPath, parseSmbPath); - String dir = smbPath + "\\test"; - - FileUtil.mkdir(dir); - assertTrue(FileUtil.exist(dir)); - String file = dir + "\\a.txt"; - FileUtil.touch(file); - FileUtil.writeString("Hello SMB", file, "UTF-8"); - - String read = FileUtil.readString(file, "UTF-8"); - assertEquals(read, "Hello SMB"); - - assertEquals(1, FileUtil.loopFiles(dir).size()); - assertEquals(1, FileUtil.ls(dir).length); - - FileUtil.del(dir); + assertTrue(FileUtil.isAbsolutePath(smbPath)); + assertTrue(Paths.get(smbPath).isAbsolute()); } @Test From 2b0b02d1c3c50ee3aba6544e4e8b09ee08be426a Mon Sep 17 00:00:00 2001 From: "peng.li" Date: Thu, 23 Jan 2025 18:34:17 +0800 Subject: [PATCH 20/29] Supports parsing HarmonyOS useragent --- .../main/java/cn/hutool/http/useragent/OS.java | 1 + .../java/cn/hutool/http/useragent/Platform.java | 17 ++++++++++++++++- .../http/useragent/UserAgentUtilTest.java | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/hutool-http/src/main/java/cn/hutool/http/useragent/OS.java b/hutool-http/src/main/java/cn/hutool/http/useragent/OS.java index 38a956c58..d6f964421 100755 --- a/hutool-http/src/main/java/cn/hutool/http/useragent/OS.java +++ b/hutool-http/src/main/java/cn/hutool/http/useragent/OS.java @@ -36,6 +36,7 @@ public class OS extends UserAgentInfo { new OS("Windows", "windows"), // new OS("OSX", "os x (\\d+)[._](\\d+)", "os x (\\d+([._]\\d+)*)"), // new OS("Android", "Android", "Android (\\d+([._]\\d+)*)"),// + new OS("Harmony", "OpenHarmony", "OpenHarmony (\\d+([._]\\d+)*)"), // new OS("Android", "XiaoMi|MI\\s+", "\\(X(\\d+([._]\\d+)*)"),// new OS("Linux", "linux"), // new OS("Wii", "wii", "wii libnup/(\\d+([._]\\d+)*)"), // diff --git a/hutool-http/src/main/java/cn/hutool/http/useragent/Platform.java b/hutool-http/src/main/java/cn/hutool/http/useragent/Platform.java index 960ee18f9..17a4380b4 100644 --- a/hutool-http/src/main/java/cn/hutool/http/useragent/Platform.java +++ b/hutool-http/src/main/java/cn/hutool/http/useragent/Platform.java @@ -36,6 +36,11 @@ public class Platform extends UserAgentInfo { * android */ public static final Platform ANDROID = new Platform("Android", "android"); + + /** + * harmony + */ + public static final Platform HARMONY = new Platform("Harmony", "OpenHarmony"); /** * android */ @@ -59,7 +64,8 @@ public class Platform extends UserAgentInfo { GOOGLE_TV, // new Platform("htcFlyer", "htc_flyer"), // new Platform("Symbian", "symbian(os)?"), // - new Platform("Blackberry", "blackberry") // + new Platform("Blackberry", "blackberry"), // + HARMONY ); /** @@ -144,4 +150,13 @@ public class Platform extends UserAgentInfo { return this.equals(ANDROID) || this.equals(GOOGLE_TV); } + /** + * 是否为Harmony平台 + * + * @return 是否为Harmony平台 + */ + public boolean isHarmony() { + return this.equals(HARMONY); + } + } diff --git a/hutool-http/src/test/java/cn/hutool/http/useragent/UserAgentUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/useragent/UserAgentUtilTest.java index 323948308..700177e64 100644 --- a/hutool-http/src/test/java/cn/hutool/http/useragent/UserAgentUtilTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/useragent/UserAgentUtilTest.java @@ -413,6 +413,16 @@ public class UserAgentUtilTest { assertEquals("Linux", ua.getOs().toString()); } + @Test + public void parseHarmonyUATest() { + final String uaStr = "Mozilla/5.0 (Phone; OpenHarmony 4.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile "; + final UserAgent ua = UserAgentUtil.parse(uaStr); + assertEquals("Harmony", ua.getPlatform().toString()); + assertTrue(ua.getPlatform().isHarmony()); + assertEquals("Harmony", ua.getOs().toString()); + assertEquals("4.1", ua.getOsVersion()); + } + @Test public void issueI60UOPTest() { final String uaStr = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 dingtalk-win/1.0.0 nw(0.14.7) DingTalk(6.5.40-Release.9059101) Mojo/1.0.0 Native AppType(release) Channel/201200"; From 565d57d3cb384c4cd3fb00dd9fab77f9c6911689 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Jan 2025 16:17:26 +0800 Subject: [PATCH 21/29] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=B8=BF=E8=92=99?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=20UA=20=E8=A7=A3=E6=9E=90=EF=BC=88pr#1301@Gi?= =?UTF-8?q?tee=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fed90e60..15188cd66 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,14 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-17) +# 5.8.36(2025-01-24) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) * 【core 】 增加HtmlUtil.cleanEmptyTag方法(pr#3838@Github) * 【db 】 GlobalDbSetting优化默认配置读取规则,优先读取文件而非jar中的文件(issue#900@Github) * 【dfa 】 删除StopChar类中存在重复字符(pr#3841@Github) +* 【http 】 支持鸿蒙设备 UA 解析(pr#1301@Gitee) ### 🐞Bug修复 * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) From 486500d026a1e9da2783d94571d8e2deb57152c1 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Jan 2025 16:33:10 +0800 Subject: [PATCH 22/29] add test --- .../src/test/java/cn/hutool/json/JSONObjectTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index 1d5e0d557..f6a36847a 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -729,4 +729,15 @@ public class JSONObjectTest { }); assertEquals("value2_edit", jsonObject.get("b")); } + + @Test + void issue3844Test(){ + String camelCaseStr = "{\"userAge\":\"123\"}"; + final JSONObject entries = new JSONObject(camelCaseStr, null, (pair) -> { + pair.setKey(StrUtil.toUnderlineCase(pair.getKey())); + return true; + }); + + Console.log(entries); + } } From 13c6f35826aa3f5e11275269cbf9d5cc01231e61 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 Jan 2025 17:13:47 +0800 Subject: [PATCH 23/29] add test --- .../java/cn/hutool/core/io/Issue3846Test.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 hutool-core/src/test/java/cn/hutool/core/io/Issue3846Test.java diff --git a/hutool-core/src/test/java/cn/hutool/core/io/Issue3846Test.java b/hutool-core/src/test/java/cn/hutool/core/io/Issue3846Test.java new file mode 100644 index 000000000..98a493dc2 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/io/Issue3846Test.java @@ -0,0 +1,23 @@ +package cn.hutool.core.io; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.lang.Console; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.TimeUnit; + +public class Issue3846Test { + @Test + @Disabled + void readBytesTest() { + final StopWatch stopWatch = DateUtil.createStopWatch(); + stopWatch.start(); + final String filePath = "d:/test/issue3846.data"; + final byte[] bytes = IoUtil.readBytes(ResourceUtil.getStream(filePath), false); + stopWatch.stop(); + Console.log(stopWatch.prettyPrint(TimeUnit.MILLISECONDS)); + } +} From d8ff04ede2a04cc0902ec41c5abf9b31eb7f55b2 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 27 Jan 2025 09:29:48 +0800 Subject: [PATCH 24/29] =?UTF-8?q?=E4=BF=AE=E5=A4=8DAbstractFilter=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E6=A3=80=E6=9F=A5=E5=8F=82=E6=95=B0=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=88issue#3854@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- .../main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15188cd66..d20bd0e61 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-24) +# 5.8.36(2025-01-27) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) @@ -15,6 +15,7 @@ * 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) * 【core 】 修复XmlUtil转义调用方法错误问题,修复XmlEscape未转义单引号问题(pr#3837@Github) * 【core 】 修复FileUtil.isAbsolutePath没有判断smb路径问题(pr#1299@Gitee) +* 【core 】 修复AbstractFilter没有检查参数长度问题(issue#3854@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) diff --git a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java index bc37e729d..327fad055 100755 --- a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java +++ b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/filter/AbstractFilter.java @@ -4,6 +4,7 @@ import cn.hutool.bloomfilter.BloomFilter; import cn.hutool.bloomfilter.bitMap.BitMap; import cn.hutool.bloomfilter.bitMap.IntMap; import cn.hutool.bloomfilter.bitMap.LongMap; +import cn.hutool.core.lang.Assert; /** * 抽象Bloom过滤器 @@ -46,7 +47,7 @@ public abstract class AbstractFilter implements BloomFilter { * @param machineNum 机器位数 */ public void init(long maxValue, int machineNum) { - this.size = maxValue; + this.size = Assert.checkBetween(maxValue, 1, Integer.MAX_VALUE); switch (machineNum) { case BitMap.MACHINE32: bm = new IntMap((int) (size / machineNum)); From 6854381b2923708a7c8c8e01c307044fbd2df3a4 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 17 Feb 2025 12:38:02 +0800 Subject: [PATCH 25/29] add test --- .../cn/hutool/core/bean/IssueIBLTZWTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 hutool-core/src/test/java/cn/hutool/core/bean/IssueIBLTZWTest.java diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/IssueIBLTZWTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/IssueIBLTZWTest.java new file mode 100644 index 000000000..892f840dc --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/bean/IssueIBLTZWTest.java @@ -0,0 +1,61 @@ +package cn.hutool.core.bean; + +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.convert.TypeConverter; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ReflectUtil; +import lombok.Data; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; +import java.util.Date; + +/** + * 自定义某个字段的转换 + */ +public class IssueIBLTZWTest { + @Test + public void copyTest() { + TestBean bean = new TestBean(); + bean.setName("test"); + bean.setDate(DateUtil.parse("2025-02-17")); + + final TestBean2 testBean2 = new TestBean2(); + BeanUtil.copyProperties(bean, testBean2, createCopyOptions(TestBean2.class)); + Assertions.assertEquals("2025", testBean2.getDate()); + } + + @Data + static class TestBean { + private String name; + private Date date; + } + + @Data + static class TestBean2 { + private String name; + private String date; + } + + static CopyOptions createCopyOptions(Class targetClass) { + CopyOptions copyOptions = CopyOptions.create(); + TypeConverter converter = (TypeConverter) ReflectUtil.getFieldValue(copyOptions, "converter"); + copyOptions + .setIgnoreError(true) // 忽略类型错误,避免自动转换 + .setConverter(null) + .setFieldValueEditor((fieldName, value) -> { + try { + Field targetField = targetClass.getDeclaredField(fieldName); + // Date类型的 value instanceof 结果是String + if (targetField.getType() == String.class && value instanceof Date) { + return DateUtil.format((Date)value, "yyyy"); + } + return converter.convert(targetField.getType(), value); + } catch (NoSuchFieldException e) { + return value; + } + }); + return copyOptions; + } +} From 97bcdbdc380a69265a9f1ed97378d72c47fa5963 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 17 Feb 2025 12:40:53 +0800 Subject: [PATCH 26/29] add test --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d20bd0e61..10cbf311e 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-27) +# 5.8.36(2025-02-17) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) From 6b843b1ca65123032de377ac9e376542e2edfc6c Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 17 Feb 2025 12:43:15 +0800 Subject: [PATCH 27/29] fix comment --- hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1d77b0012..5a4b17ce1 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 @@ -956,7 +956,7 @@ public class XmlUtil { * < (小于) 替换为 &lt; * > (大于) 替换为 &gt; * " (双引号) 替换为 &quot; - * ' (单引号) 替换为 &apos; + * ' (单引号) 替换为 &apos; * * * @param string 被替换的字符串 From 26c40fb51c6b539f94b225b0ace1b06a2f05783b Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 17 Feb 2025 13:03:46 +0800 Subject: [PATCH 28/29] fix stopchars --- .../src/main/java/cn/hutool/dfa/StopChar.java | 42 +++++++++---------- .../src/test/java/cn/hutool/dfa/DfaTest.java | 5 ++- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java index 583380653..d4ffb136d 100755 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java @@ -1,37 +1,37 @@ package cn.hutool.dfa; -import java.util.Set; - import cn.hutool.core.collection.CollUtil; +import java.util.Set; + /** * 过滤词及一些简单处理 - * + * * @author Looly */ public class StopChar { /** 不需要处理的词,如标点符号、空格等 */ public static final Set STOP_WORD = CollUtil.newHashSet(' ', '\'', '、', '。', // - '·', 'ˉ', 'ˇ', '々', '—', '~', '‖', '…', '‘', '’', '“', '”', '〔', '〕', '〈', '〉', '《', '》', '「', '」', '『', // - '』', '〖', '〗', '【', '】', '±', '+', '-', '×', '÷', '∧', '∨', '∑', '∏', '∪', '∩', '∈', '√', '⊥', '⊙', '∫', // - '∮', '≡', '≌', '≈', '∽', '∝', '≠', '≮', '≯', '≤', '≥', '∞', '∶', '∵', '∴', '∷', '♂', '♀', '°', '′', '〃', // - '℃', '$', '¤', '¢', '£', '‰', '§', '☆', '★', '〇', '○', '●', '◎', '◇', '◆', '□', '■', '△', '▽', '⊿', '▲', // - '▼', '◣', '◤', '◢', '◥', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▉', '▊', '▋', '▌', '▍', '▎', '▏', '▓', // - '※', '→', '←', '↑', '↓', '↖', '↗', '↘', '↙', '〓', 'ⅰ', 'ⅱ', 'ⅲ', 'ⅳ', 'ⅴ', 'ⅵ', 'ⅶ', 'ⅷ', 'ⅸ', 'ⅹ', '①', // - '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⒈', '⒉', '⒊', '⒋', '⒌', '⒍', '⒎', '⒏', '⒐', '⒑', '⒒', '⒓', // - '⒔', '⒕', '⒖', '⒗', '⒘', '⒙', '⒚', '⒛', '⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀', // - '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇', 'Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', 'Ⅴ', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', 'Ⅹ', 'Ⅺ', 'Ⅻ', '!', // - '#', '¥', '%', '&', '(', ')', '*', ',', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', // - '8', '9', ':', ';', '<', '=', '>', '?', '@', '\', '^', '_', '{', '|', '}', 'Ρ', // - 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', // - 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', // - '/', '\\', '\"', '<', '>', '`', '{', '}', '~', '(', ')', '-', // - '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?', - ':', '.', '!', ';', ']','|','%'); + '·', 'ˉ', 'ˇ', '々', '—', '~', '‖', '…', '‘', '’', '“', '”', '〔', '〕', '〈', '〉', '《', '》', '「', '」', '『', // + '』', '〖', '〗', '【', '】', '±', '+', '-', '×', '÷', '∧', '∨', '∑', '∏', '∪', '∩', '∈', '√', '⊥', '⊙', '∫', // + '∮', '≡', '≌', '≈', '∽', '∝', '≠', '≮', '≯', '≤', '≥', '∞', '∶', '∵', '∴', '∷', '♂', '♀', '°', '′', '〃', // + '℃', '$', '¤', '¢', '£', '‰', '§', '☆', '★', '〇', '○', '●', '◎', '◇', '◆', '□', '■', '△', '▽', '⊿', '▲', // + '▼', '◣', '◤', '◢', '◥', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▉', '▊', '▋', '▌', '▍', '▎', '▏', '▓', // + '※', '→', '←', '↑', '↓', '↖', '↗', '↘', '↙', '〓', 'ⅰ', 'ⅱ', 'ⅲ', 'ⅳ', 'ⅴ', 'ⅵ', 'ⅶ', 'ⅷ', 'ⅸ', 'ⅹ', '①', // + '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⒈', '⒉', '⒊', '⒋', '⒌', '⒍', '⒎', '⒏', '⒐', '⒑', '⒒', '⒓', // + '⒔', '⒕', '⒖', '⒗', '⒘', '⒙', '⒚', '⒛', '⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀', // + '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇', 'Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ', 'Ⅴ', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', 'Ⅹ', 'Ⅺ', 'Ⅻ', '!', // + '#', '¥', '%', '&', '(', ')', '*', ',', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', // + '8', '9', ':', ';', '<', '=', '>', '?', '@', '〔', '\', '〕', '^', '_', '‘', '{', '|', '}', 'Ρ', // + 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', // + 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '(', ')', '^', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', // + '', '^', '(', ':', '!', '/', '\\', '\"', '<', '>', '`', '{', '}', '~', '(', ')', '-', // + '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?', + ':', '.', '!', ';', ']','|','%'); /** * 判断指定的词是否是不处理的词。 如果参数为空,则返回true,因为空也属于不处理的字符。 - * + * * @param ch 指定的词 * @return 是否是不处理的词 */ @@ -41,7 +41,7 @@ public class StopChar { /** * 是否为合法字符(待处理字符) - * + * * @param ch 指定的词 * @return 是否为合法字符(待处理字符) */ diff --git a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java index 515237e25..97b068be5 100755 --- a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java +++ b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java @@ -1,11 +1,12 @@ package cn.hutool.dfa; import cn.hutool.core.collection.CollUtil; -import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; import java.util.List; +import static org.junit.jupiter.api.Assertions.*; + /** * DFA单元测试 * @@ -27,7 +28,7 @@ public class DfaTest { // 匹配到【大】,就不再继续匹配了,因此【大土豆】不匹配 // 匹配到【刚出锅】,就跳过这三个字了,因此【出锅】不匹配(由于刚首先被匹配,因此长的被匹配,最短匹配只针对第一个字相同选最短) List matchAll = tree.matchAll(text, -1, false, false); - assertEquals(matchAll, CollUtil.newArrayList("大", "土^豆", "刚出锅")); + assertEquals(CollUtil.newArrayList("大", "土^豆", "刚出锅"), matchAll); } /** From b8048c10910496da2f9d558bbba5376b668785d8 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 18 Feb 2025 09:19:23 +0800 Subject: [PATCH 29/29] =?UTF-8?q?=F0=9F=90=8Crelease=205.8.36?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-jwt/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10cbf311e..63d0f298f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-02-17) +# 5.8.36(2025-02-18) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index ededd708b..461bbb281 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 35f733897..98d35c75e 100755 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 26d28bfee..4f168a9a3 100755 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 9995c38fd..98a3f7e1b 100755 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 024c7bb7e..66a711b3e 100755 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index c63b6625a..a196bd42c 100755 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 76c631622..30520742c 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index dbae23835..2ace03996 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index b1dbf66a8..fee560ee4 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index da9eebea6..12b9268a0 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index a22b36a14..44e972633 100755 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 5f8984fe5..e9705ee0f 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index 4e6eac5ca..7cade2401 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 51809ad64..4729bd20f 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-json diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index 64a36d4e9..03624d7ed 100755 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-jwt diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 2222137fe..b264dcd71 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index eccfe33cc..b6bf3b2ab 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index e831e82e4..e6d975602 100755 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index b57b466d1..6104366ab 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 64826b523..32807733c 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 31e1cdb09..79817e3a1 100755 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool-system diff --git a/pom.xml b/pom.xml index 57b32548a..2cc77cd71 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.8.36-SNAPSHOT + 5.8.36 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool