diff --git a/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java b/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java index c189de92e5d6..2b8f3f395c4b 100644 --- a/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java +++ b/paimon-api/src/main/java/org/apache/paimon/utils/StringUtils.java @@ -307,6 +307,112 @@ public static boolean isNotEmpty(CharSequence cs) { return !isEmpty(cs); } + public static boolean isBlank(final CharSequence cs) { + if (isEmpty(cs)) { + return true; + } + + for (int i = 0; i < cs.length(); i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; + } + + public static boolean equals(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null || cs1.length() != cs2.length()) { + return false; + } + + for (int i = 0; i < cs1.length(); i++) { + if (cs1.charAt(i) != cs2.charAt(i)) { + return false; + } + } + return true; + } + + public static boolean startsWith(final CharSequence str, final CharSequence prefix) { + if (str == prefix) { + return true; + } + if (str == null || prefix == null) { + return false; + } + + return str.toString().startsWith(prefix.toString()); + } + + public static boolean endsWith(final CharSequence str, final CharSequence suffix) { + if (str == suffix) { + return true; + } + if (str == null || suffix == null) { + return false; + } + + return str.toString().endsWith(suffix.toString()); + } + + public static String substringBeforeLast(final String str, final String separator) { + if (isEmpty(str) || isEmpty(separator)) { + return str; + } + + int pos = str.lastIndexOf(separator); + if (pos == INDEX_NOT_FOUND) { + return str; + } + + return str.substring(0, pos); + } + + public static String substringAfterLast(final String str, final String separator) { + if (isEmpty(str)) { + return str; + } + if (isEmpty(separator)) { + return EMPTY; + } + + int pos = str.lastIndexOf(separator); + if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) { + return EMPTY; + } + + return str.substring(pos + separator.length()); + } + + public static String stripEnd(final String str, final String stripChars) { + if (isEmpty(str)) { + return str; + } + + int end = str.length(); + if (stripChars == null) { + while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { + end--; + } + } else if (stripChars.isEmpty()) { + return str; + } else { + while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { + end--; + } + } + + return str.substring(0, end); + } + + public static String trimToNull(final String str) { + String trimmed = trim(str); + return isEmpty(trimmed) ? null : trimmed; + } + public static String randomNumericString(int len) { StringBuilder builder = new StringBuilder(); ThreadLocalRandom rnd = ThreadLocalRandom.current(); @@ -445,6 +551,61 @@ public static String[] split( return list.toArray(new String[list.size()]); } + /** + * Joins the elements of the provided array into a single String containing the provided list of + * elements. + * + *
No delimiter is added before or after the list. A {@code null} separator is the same as an + * empty String (""). + * + * @param array the array of values to join together, may be null + * @param separator the separator character to use, null treated as "" + * @return the joined String, {@code null} if null array input + */ + public static String join(final Object[] array, final String separator) { + if (array == null) { + return null; + } + return join(array, separator, 0, array.length); + } + + /** + * Joins the elements of the provided array into a single String containing the provided list of + * elements. + * + *
No delimiter is added before or after the list. A {@code null} separator is the same as an
+ * empty String ("").
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @param startIndex the first index to start joining from
+ * @param endIndex the index to stop joining from (exclusive)
+ * @return the joined String, {@code null} if null array input
+ */
+ public static String join(
+ final Object[] array,
+ final String separator,
+ final int startIndex,
+ final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ if (array[i] != null) {
+ buf.append(array[i]);
+ }
+ }
+ return buf.toString();
+ }
+
/**
* Joins the elements of the provided {@code Iterable} into a single String containing the
* provided elements.
diff --git a/paimon-benchmark/paimon-cluster-benchmark/src/main/java/org/apache/paimon/benchmark/metric/cpu/ProcfsBasedProcessTree.java b/paimon-benchmark/paimon-cluster-benchmark/src/main/java/org/apache/paimon/benchmark/metric/cpu/ProcfsBasedProcessTree.java
index b1a9b3fd8699..e500d2820c53 100644
--- a/paimon-benchmark/paimon-cluster-benchmark/src/main/java/org/apache/paimon/benchmark/metric/cpu/ProcfsBasedProcessTree.java
+++ b/paimon-benchmark/paimon-cluster-benchmark/src/main/java/org/apache/paimon/benchmark/metric/cpu/ProcfsBasedProcessTree.java
@@ -20,13 +20,13 @@
import org.apache.paimon.benchmark.metric.cpu.clock.Clock;
import org.apache.paimon.benchmark.metric.cpu.clock.SystemClock;
+import org.apache.paimon.utils.StringUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.AndFileFilter;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.File;
diff --git a/paimon-benchmark/paimon-micro-benchmarks/src/test/java/org/apache/paimon/benchmark/Benchmark.java b/paimon-benchmark/paimon-micro-benchmarks/src/test/java/org/apache/paimon/benchmark/Benchmark.java
index 939f8cf90bdc..450e7035a40b 100644
--- a/paimon-benchmark/paimon-micro-benchmarks/src/test/java/org/apache/paimon/benchmark/Benchmark.java
+++ b/paimon-benchmark/paimon-micro-benchmarks/src/test/java/org/apache/paimon/benchmark/Benchmark.java
@@ -18,7 +18,8 @@
package org.apache.paimon.benchmark;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
+
import org.apache.paimon.shade.org.apache.commons.lang3.SystemUtils;
import java.io.BufferedReader;
diff --git a/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java b/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
index b281812a13d7..b80d5bc2bf7d 100644
--- a/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
+++ b/paimon-common/src/test/java/org/apache/paimon/utils/StringUtilsTest.java
@@ -259,6 +259,56 @@ void testNonEmptyStringBuilder() {
}
}
+ @Nested
+ class CommonsCompatibilityTests {
+
+ @Test
+ void testIsBlank() {
+ assertThat(StringUtils.isBlank(null)).isTrue();
+ assertThat(StringUtils.isBlank("")).isTrue();
+ assertThat(StringUtils.isBlank(" \t")).isTrue();
+ assertThat(StringUtils.isBlank("paimon")).isFalse();
+ }
+
+ @Test
+ void testEquals() {
+ assertThat(StringUtils.equals(null, null)).isTrue();
+ assertThat(StringUtils.equals(null, "paimon")).isFalse();
+ assertThat(StringUtils.equals("paimon", "paimon")).isTrue();
+ assertThat(StringUtils.equals("paimon", "Paimon")).isFalse();
+ }
+
+ @Test
+ void testStartsWithAndEndsWith() {
+ assertThat(StringUtils.startsWith("manifest-1", "manifest")).isTrue();
+ assertThat(StringUtils.startsWith(null, "manifest")).isFalse();
+ assertThat(StringUtils.endsWith("part-0.parquet", ".parquet")).isTrue();
+ assertThat(StringUtils.endsWith("part-0.orc", ".parquet")).isFalse();
+ }
+
+ @Test
+ void testSubstringBeforeAndAfterLast() {
+ assertThat(StringUtils.substringBeforeLast("a/b/c", "/")).isEqualTo("a/b");
+ assertThat(StringUtils.substringBeforeLast("abc", "/")).isEqualTo("abc");
+ assertThat(StringUtils.substringAfterLast("a/b/c", "/")).isEqualTo("c");
+ assertThat(StringUtils.substringAfterLast("abc/", "/")).isEmpty();
+ }
+
+ @Test
+ void testStripEnd() {
+ assertThat(StringUtils.stripEnd("cpu\n", null)).isEqualTo("cpu");
+ assertThat(StringUtils.stripEnd("abccc", "c")).isEqualTo("ab");
+ assertThat(StringUtils.stripEnd("abc", "")).isEqualTo("abc");
+ }
+
+ @Test
+ void testTrimToNull() {
+ assertThat(StringUtils.trimToNull(null)).isNull();
+ assertThat(StringUtils.trimToNull(" ")).isNull();
+ assertThat(StringUtils.trimToNull(" paimon ")).isEqualTo("paimon");
+ }
+ }
+
@Nested
class RandomNumericStringTests {
diff --git a/paimon-core/src/main/java/org/apache/paimon/catalog/TableQueryAuthResult.java b/paimon-core/src/main/java/org/apache/paimon/catalog/TableQueryAuthResult.java
index 87910b5cc65a..b0bb9b1d520d 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/TableQueryAuthResult.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/TableQueryAuthResult.java
@@ -36,8 +36,7 @@
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.InternalRowUtils;
import org.apache.paimon.utils.JsonSerdeUtil;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import javax.annotation.Nullable;
diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
index 364cdb3cd591..e81e6c8e6108 100644
--- a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
@@ -63,13 +63,12 @@
import org.apache.paimon.table.system.SystemTableLoader;
import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.SnapshotNotExistException;
+import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.view.View;
import org.apache.paimon.view.ViewChange;
import org.apache.paimon.view.ViewImpl;
import org.apache.paimon.view.ViewSchema;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
-
import javax.annotation.Nullable;
import java.io.IOException;
diff --git a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
index 5961101c3a55..41caed02637b 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
@@ -111,6 +111,7 @@
import org.apache.paimon.utils.LazyField;
import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.SnapshotManager;
+import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.utils.TagManager;
import org.apache.paimon.utils.TimeUtils;
import org.apache.paimon.view.View;
@@ -120,7 +121,6 @@
import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.core.JsonProcessingException;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
diff --git a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
index e70a11321aff..78d8cd8e00a4 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
@@ -90,6 +90,7 @@
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.utils.SnapshotManager;
import org.apache.paimon.utils.SnapshotNotExistException;
+import org.apache.paimon.utils.StringUtils;
import org.apache.paimon.view.View;
import org.apache.paimon.view.ViewChange;
@@ -97,7 +98,6 @@
import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
import org.apache.paimon.shade.guava30.com.google.common.collect.Lists;
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Assertions;
diff --git a/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java b/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
index a7a8fb995271..547cbfecd33d 100644
--- a/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
+++ b/paimon-flink/paimon-flink-1.18/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
@@ -21,8 +21,7 @@
import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.table.Table;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.flink.table.procedure.ProcedureContext;
diff --git a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateBranchAction.java b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateBranchAction.java
index 0d681cae73bb..9e65878c99e7 100644
--- a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateBranchAction.java
+++ b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateBranchAction.java
@@ -18,7 +18,7 @@
package org.apache.paimon.flink.action;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import java.util.Map;
diff --git a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
index 90cb5f8cd9ac..d6287cff56a3 100644
--- a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
+++ b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/procedure/CreateBranchProcedure.java
@@ -21,8 +21,7 @@
import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.table.Table;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.flink.table.annotation.ArgumentHint;
import org.apache.flink.table.annotation.DataTypeHint;
diff --git a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/BranchSqlITCase.java b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/BranchSqlITCase.java
index 641efb733595..0fd5b81de43c 100644
--- a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/BranchSqlITCase.java
+++ b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/BranchSqlITCase.java
@@ -22,8 +22,7 @@
import org.apache.paimon.table.FileStoreTable;
import org.apache.paimon.utils.BlockingIterator;
import org.apache.paimon.utils.SnapshotManager;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.flink.types.Row;
import org.apache.flink.types.RowKind;
diff --git a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/CatalogTableITCase.java b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/CatalogTableITCase.java
index 0bea96f04630..7a82007870a1 100644
--- a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/CatalogTableITCase.java
+++ b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/CatalogTableITCase.java
@@ -20,8 +20,7 @@
import org.apache.paimon.catalog.Catalog;
import org.apache.paimon.utils.BlockingIterator;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.flink.table.catalog.CatalogPartition;
import org.apache.flink.table.catalog.CatalogPartitionSpec;
diff --git a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/ShowCreateUtil.java b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/ShowCreateUtil.java
index 415135ae514d..50ed3bf532dd 100644
--- a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/ShowCreateUtil.java
+++ b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/ShowCreateUtil.java
@@ -18,7 +18,7 @@
package org.apache.paimon.flink;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.flink.table.api.TableException;
import org.apache.flink.table.catalog.CatalogBaseTable;
diff --git a/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkReadTestBase.java b/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkReadTestBase.java
index 27a7557ab75a..918552fb06fa 100644
--- a/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkReadTestBase.java
+++ b/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkReadTestBase.java
@@ -34,8 +34,7 @@
import org.apache.paimon.table.sink.TableCommitImpl;
import org.apache.paimon.types.DataField;
import org.apache.paimon.types.RowKind;
-
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
diff --git a/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkSchemaEvolutionITCase.java b/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkSchemaEvolutionITCase.java
index ea837960cc40..1cdf210d89d4 100644
--- a/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkSchemaEvolutionITCase.java
+++ b/paimon-spark/paimon-spark-ut/src/test/java/org/apache/paimon/spark/SparkSchemaEvolutionITCase.java
@@ -18,7 +18,7 @@
package org.apache.paimon.spark;
-import org.apache.paimon.shade.org.apache.commons.lang3.StringUtils;
+import org.apache.paimon.utils.StringUtils;
import org.apache.spark.sql.AnalysisException;
import org.apache.spark.sql.Dataset;
diff --git a/tools/maven/checkstyle.xml b/tools/maven/checkstyle.xml
index 998c56383f66..2e8334375f9f 100644
--- a/tools/maven/checkstyle.xml
+++ b/tools/maven/checkstyle.xml
@@ -189,12 +189,6 @@ This file is based on the checkstyle file of Apache Beam.