Repository: apache/amoro
Pull request #3127 (2024-08-22 13:41:15)

[AMORO-3095][ams-server]Fix: Add s3a dependency software.amazon.awssdk:s3-transfer-manager
<!--
Thanks for sending a pull request!

Here are some tips for you:
  1. If this is your first time, please read our contributor guidelines: https://amoro.apache.org/how-to-contribute/
  2. If the PR is related to an issue in https://github.com/apache/amoro/issues, add '[AMORO-XXXX]' in your PR title, e.g., '[AMORO-XXXX] Your PR title ...'.
  3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., '[WIP][AMORO-XXXX] Your PR title ...'.
-->

## Why are the changes needed?
<!--
Please clarify why the changes are needed. For instance,
  1. If you add a feature, you can talk about its use case.
  2. If you fix a bug, you can clarify why it is a bug.
  3. Use Fix/Resolve/Close #{ISSUE_NUMBER} to link this PR to its related issue
-->

Close  https://github.com/apache/amoro/issues/3095

## Brief change log
<!--
Clearly describe the changes made in modules, classes, methods, etc.
-->

- Just add the mvn pom dependency

## How was this patch tested?

- [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible

- [x] Add screenshots for manual tests if appropriate
When I connect to S3:
Before:
<img width="806" alt="amoro_class_not_found" src="https://github.com/user-attachments/assets/ada7f894-295a-46ed-b1cf-3207b90060ea">
After:
<img width="960" alt="amoro_optimizer" src="https://github.com/user-attachments/assets/6d746230-9e6a-49ca-b911-de3f752c7387">
<img width="349" alt="amoro_run_success" src="https://github.com/user-attachments/assets/51647784-f933-4737-84d6-67d8533489c2">

- [x] Run test locally before making a pull request

## Documentation

- Does this pull request introduce a new feature? (no)
- If yes, how is the feature documented? (not applicable / docs / JavaDocs / not documented)



Patch:
diff --git a/amoro-ams/amoro-ams-api/pom.xml b/amoro-ams/amoro-ams-api/pom.xml
index 4fdc4d9b0..3333021a2 100644
--- a/amoro-ams/amoro-ams-api/pom.xml
+++ b/amoro-ams/amoro-ams-api/pom.xml
@@ -47,6 +47,19 @@
             <scope>provided</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-core</artifactId>
+            <version>${iceberg.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.curator</groupId>
             <artifactId>curator-test</artifactId>
diff --git a/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/OptimizingConfig.java b/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/OptimizingConfig.java
index fac4143b9..06614e602 100644
--- a/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/OptimizingConfig.java
+++ b/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/OptimizingConfig.java
@@ -24,7 +24,7 @@ import org.apache.amoro.shade.guava32.com.google.common.base.Objects;
 import org.apache.amoro.shade.jackson2.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import org.apache.amoro.table.TableProperties;
 import org.apache.amoro.utils.CompatiblePropertyUtil;
-import org.apache.iceberg.util.PropertyUtil;
+import org.apache.amoro.utils.PropertyUtil;
 
 import java.util.Map;
 
diff --git a/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/TableConfiguration.java b/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/TableConfiguration.java
index d33451821..8362ba264 100644
--- a/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/TableConfiguration.java
+++ b/amoro-ams/amoro-ams-api/src/main/java/org/apache/amoro/api/config/TableConfiguration.java
@@ -157,9 +157,7 @@ public class TableConfiguration {
   }
 
   public static TableConfiguration parseConfig(Map<String, String> properties) {
-    boolean gcEnabled =
-        CompatiblePropertyUtil.propertyAsBoolean(
-            properties, org.apache.iceberg.TableProperties.GC_ENABLED, true);
+    boolean gcEnabled = CompatiblePropertyUtil.propertyAsBoolean(properties, "gc.enabled", true);
     return new TableConfiguration()
         .setExpireSnapshotEnabled(
             gcEnabled
diff --git a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-common/src/main/java/org/apache/amoro/optimizer/common/OptimizerExecutor.java b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-common/src/main/java/org/apache/amoro/optimizer/common/OptimizerExecutor.java
index 3e797f800..197be5f8f 100644
--- a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-common/src/main/java/org/apache/amoro/optimizer/common/OptimizerExecutor.java
+++ b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-common/src/main/java/org/apache/amoro/optimizer/common/OptimizerExecutor.java
@@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
 public class OptimizerExecutor extends AbstractOptimizerOperator {
 
   private static final Logger LOG = LoggerFactory.getLogger(OptimizerExecutor.class);
+  protected static final int ERROR_MESSAGE_MAX_LENGTH = 4000;
 
   private final int threadId;
 
@@ -166,7 +167,7 @@ public class OptimizerExecutor extends AbstractOptimizerOperator {
           System.currentTimeMillis() - startTime,
           t);
       OptimizingTaskResult errorResult = new OptimizingTaskResult(task.getTaskId(), threadId);
-      errorResult.setErrorMessage(ExceptionUtil.getErrorMessage(t, 4000));
+      errorResult.setErrorMessage(ExceptionUtil.getErrorMessage(t, ERROR_MESSAGE_MAX_LENGTH));
       return errorResult;
     }
   }
diff --git a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-flink/src/main/java/org/apache/amoro/optimizer/flink/FlinkOptimizerExecutor.java b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-flink/src/main/java/org/apache/amoro/optimizer/flink/FlinkOptimizerExecutor.java
index 5a1213606..824a73b59 100644
--- a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-flink/src/main/java/org/apache/amoro/optimizer/flink/FlinkOptimizerExecutor.java
+++ b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-flink/src/main/java/org/apache/amoro/optimizer/flink/FlinkOptimizerExecutor.java
@@ -72,10 +72,11 @@ public class FlinkOptimizerExecutor extends OptimizerExecutor {
     // add optimizer flink runtime info, including application_id, tm_id
     StringBuilder sb = new StringBuilder();
     if (!Strings.isNullOrEmpty(result.getErrorMessage())) {
-      if (runtimeContext != null && runtimeContext.size() > 0) {
+      if (runtimeContext != null && !runtimeContext.isEmpty()) {
         runtimeContext.forEach((k, v) -> sb.append(k).append("=").append(v).append("\n"));
       }
-      result.setErrorMessage(sb.toString() + result.getErrorMessage());
+      result.setErrorMessage(
+          (sb + result.getErrorMessage()).substring(0, ERROR_MESSAGE_MAX_LENGTH));
     }
     return result;
   }
diff --git a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/src/main/java/org/apache/amoro/optimizer/spark/SparkOptimizerExecutor.java b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/src/main/java/org/apache/amoro/optimizer/spark/SparkOptimizerExecutor.java
index b1cae14ad..7cdcd2522 100644
--- a/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/src/main/java/org/apache/amoro/optimizer/spark/SparkOptimizerExecutor.java
+++ b/amoro-ams/amoro-ams-optimizer/amoro-optimizer-spark/src/main/java/org/apache/amoro/optimizer/spark/SparkOptimizerExecutor.java
@@ -74,7 +74,7 @@ public class SparkOptimizerExecutor extends OptimizerExecutor {
           (System.currentTimeMillis() - startTime),
           r);
       result = new OptimizingTaskResult(task.getTaskId(), threadId);
-      result.setErrorMessage(ExceptionUtil.getErrorMessage(r, 4000));
+      result.setErrorMessage(ExceptionUtil.getErrorMessage(r, ERROR_MESSAGE_MAX_LENGTH));
       return result;
     }
   }
diff --git a/amoro-ams/amoro-ams-server/pom.xml b/amoro-ams/amoro-ams-server/pom.xml
index 0672b8895..a13bb67c7 100644
--- a/amoro-ams/amoro-ams-server/pom.xml
+++ b/amoro-ams/amoro-ams-server/pom.xml
@@ -41,6 +41,11 @@
             <artifactId>amoro-ams-api</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-mixed-format-hive</artifactId>
@@ -276,6 +281,11 @@
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>url-connection-client</artifactId>
         </dependency>
+	
+	<dependency>
+                <groupId>software.amazon.awssdk</groupId>
+                <artifactId>s3-transfer-manager</artifactId>
+	</dependency>
 
         <dependency>
             <groupId>org.apache.hadoop</groupId>
@@ -351,6 +361,14 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-ams-api</artifactId>
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/HighAvailabilityContainer.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/HighAvailabilityContainer.java
index 5d10b1a2d..76fb83d49 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/HighAvailabilityContainer.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/HighAvailabilityContainer.java
@@ -122,8 +122,8 @@ public class HighAvailabilityContainer implements LeaderLatchListener {
   public void close() {
     if (leaderLatch != null) {
       try {
-        this.zkClient.close();
         this.leaderLatch.close();
+        this.zkClient.close();
       } catch (IOException e) {
         LOG.error("Close high availability services failed", e);
       }
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
index cceb573cb..83ee552c2 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/RestCatalogService.java
@@ -50,7 +50,7 @@ import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.amoro.utils.TablePropertyUtil;
 import org.apache.iceberg.TableMetadata;
 import org.apache.iceberg.TableOperations;
@@ -435,7 +435,7 @@ public class RestCatalogService extends PersistentBase {
     ServerCatalog internalCatalog = tableService.getServerCatalog(catalog);
     Preconditions.checkArgument(
         internalCatalog instanceof InternalCatalog, "The catalog is not an iceberg rest catalog");
-    Set<TableFormat> tableFormats = MixedCatalogUtil.tableFormats(internalCatalog.getMetadata());
+    Set<TableFormat> tableFormats = CatalogUtil.tableFormats(internalCatalog.getMetadata());
     Preconditions.checkArgument(
         tableFormats.size() == 1
             && (tableFormats.contains(TableFormat.ICEBERG)
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
index 9aaa6ca17..447c4e7af 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/CatalogBuilder.java
@@ -32,7 +32,7 @@ import org.apache.amoro.server.AmoroManagementConf;
 import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.shade.guava32.com.google.common.collect.ImmutableMap;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 
 import java.util.Map;
 import java.util.Set;
@@ -68,7 +68,7 @@ public class CatalogBuilder {
   public static ServerCatalog buildServerCatalog(
       CatalogMeta catalogMeta, Configurations serverConfiguration) {
     String type = catalogMeta.getCatalogType();
-    Set<TableFormat> tableFormats = MixedCatalogUtil.tableFormats(catalogMeta);
+    Set<TableFormat> tableFormats = CatalogUtil.tableFormats(catalogMeta);
 
     Preconditions.checkState(
         formatSupportedMatrix.containsKey(type), "unsupported catalog type: %s", type);
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
index bd8f11d02..94eb17d88 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/ExternalCatalog.java
@@ -29,7 +29,7 @@ import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.server.persistence.mapper.TableMetaMapper;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -46,7 +46,7 @@ public class ExternalCatalog extends ServerCatalog {
 
   protected ExternalCatalog(CatalogMeta metadata) {
     super(metadata);
-    this.tableMetaStore = MixedCatalogUtil.buildMetaStore(metadata);
+    this.tableMetaStore = CatalogUtil.buildMetaStore(metadata);
     this.unifiedCatalog =
         this.tableMetaStore.doAs(
             () -> new CommonUnifiedCatalog(this::getMetadata, Maps.newHashMap()));
@@ -76,7 +76,7 @@ public class ExternalCatalog extends ServerCatalog {
   @Override
   public void updateMetadata(CatalogMeta metadata) {
     super.updateMetadata(metadata);
-    this.tableMetaStore = MixedCatalogUtil.buildMetaStore(metadata);
+    this.tableMetaStore = CatalogUtil.buildMetaStore(metadata);
     this.unifiedCatalog.refresh();
     updateDatabaseFilter(metadata);
     updateTableFilter(metadata);
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
index 9deba0d52..a67f68f31 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/InternalIcebergCatalogImpl.java
@@ -34,7 +34,7 @@ import org.apache.amoro.server.table.internal.InternalTableCreator;
 import org.apache.amoro.server.table.internal.InternalTableHandler;
 import org.apache.amoro.server.utils.InternalTableUtil;
 import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.iceberg.BaseTable;
 import org.apache.iceberg.CatalogProperties;
 import org.apache.iceberg.TableOperations;
@@ -100,7 +100,7 @@ public class InternalIcebergCatalogImpl extends InternalCatalog {
     return IcebergTable.newIcebergTable(
         tableIdentifier,
         table,
-        MixedCatalogUtil.buildMetaStore(getMetadata()),
+        CatalogUtil.buildMetaStore(getMetadata()),
         getMetadata().getCatalogProperties());
   }
 
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
index 917822498..0d1cc9b1c 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/catalog/MixedHiveCatalogImpl.java
@@ -29,7 +29,7 @@ import org.apache.amoro.server.persistence.mapper.TableMetaMapper;
 import org.apache.amoro.server.table.TableMetadata;
 import org.apache.amoro.server.table.internal.InternalTableCreator;
 import org.apache.amoro.server.table.internal.InternalTableHandler;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
 import org.apache.iceberg.rest.requests.CreateTableRequest;
 import org.apache.thrift.TException;
@@ -44,7 +44,7 @@ public class MixedHiveCatalogImpl extends InternalCatalog {
     super(catalogMeta);
     this.tables =
         new MixedHiveTables(
-            catalogMeta.getCatalogProperties(), MixedCatalogUtil.buildMetaStore(catalogMeta));
+            catalogMeta.getCatalogProperties(), CatalogUtil.buildMetaStore(catalogMeta));
     hiveClientPool = ((MixedHiveTables) tables()).getHiveClientPool();
   }
 
@@ -53,8 +53,7 @@ public class MixedHiveCatalogImpl extends InternalCatalog {
     super.updateMetadata(metadata);
     hiveClientPool = ((MixedHiveTables) tables()).getHiveClientPool();
     this.tables =
-        new MixedHiveTables(
-            metadata.getCatalogProperties(), MixedCatalogUtil.buildMetaStore(metadata));
+        new MixedHiveTables(metadata.getCatalogProperties(), CatalogUtil.buildMetaStore(metadata));
   }
 
   @Override
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
index a7a78c9b1..78d10823b 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/CatalogController.java
@@ -72,7 +72,7 @@ import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.TableProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.commons.lang.StringUtils;
 import org.apache.iceberg.CatalogProperties;
 import org.apache.iceberg.aws.AwsClientProperties;
@@ -249,12 +249,12 @@ public class CatalogController {
         metaAuthConfig.put(
             AUTH_CONFIGS_KEY_SECRET_KEY, serverAuthConfig.get(AUTH_CONFIGS_KEY_SECRET_KEY));
 
-        MixedCatalogUtil.copyProperty(
+        CatalogUtil.copyProperty(
             serverAuthConfig,
             catalogMeta.getCatalogProperties(),
             AUTH_CONFIGS_KEY_ACCESS_KEY,
             S3FileIOProperties.ACCESS_KEY_ID);
-        MixedCatalogUtil.copyProperty(
+        CatalogUtil.copyProperty(
             serverAuthConfig,
             catalogMeta.getCatalogProperties(),
             AUTH_CONFIGS_KEY_SECRET_KEY,
@@ -295,12 +295,12 @@ public class CatalogController {
                     catalogName, CONFIG_TYPE_AUTH, AUTH_CONFIGS_KEY_KRB5.replace("\\.", "-"))));
         break;
       case AUTH_CONFIGS_VALUE_TYPE_AK_SK:
-        MixedCatalogUtil.copyProperty(
+        CatalogUtil.copyProperty(
             catalogMeta.getCatalogProperties(),
             serverAuthConfig,
             S3FileIOProperties.ACCESS_KEY_ID,
             AUTH_CONFIGS_KEY_ACCESS_KEY);
-        MixedCatalogUtil.copyProperty(
+        CatalogUtil.copyProperty(
             catalogMeta.getCatalogProperties(),
             serverAuthConfig,
             S3FileIOProperties.SECRET_ACCESS_KEY,
@@ -315,7 +315,7 @@ public class CatalogController {
       String catalogName, CatalogMeta catalogMeta) {
     Map<String, Object> storageConfig = new HashMap<>();
     Map<String, String> config = catalogMeta.getStorageConfigs();
-    String storageType = MixedCatalogUtil.getCompatibleStorageType(config);
+    String storageType = CatalogUtil.getCompatibleStorageType(config);
     storageConfig.put(STORAGE_CONFIGS_KEY_TYPE, storageType);
     if (STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equals(storageType)) {
       storageConfig.put(
@@ -345,12 +345,12 @@ public class CatalogController {
                   CONFIG_TYPE_STORAGE,
                   STORAGE_CONFIGS_KEY_HIVE_SITE.replace("\\.", "-"))));
     } else if (STORAGE_CONFIGS_VALUE_TYPE_S3.equals(storageType)) {
-      MixedCatalogUtil.copyProperty(
+      CatalogUtil.copyProperty(
           catalogMeta.getCatalogProperties(),
           storageConfig,
           AwsClientProperties.CLIENT_REGION,
           STORAGE_CONFIGS_KEY_REGION);
-      MixedCatalogUtil.copyProperty(
+      CatalogUtil.copyProperty(
           catalogMeta.getCatalogProperties(),
           storageConfig,
           S3FileIOProperties.ENDPOINT,
@@ -421,12 +421,12 @@ public class CatalogController {
         }
       }
     } else if (storageType.equals(STORAGE_CONFIGS_VALUE_TYPE_S3)) {
-      MixedCatalogUtil.copyProperty(
+      CatalogUtil.copyProperty(
           info.getStorageConfig(),
           catalogMeta.getCatalogProperties(),
           STORAGE_CONFIGS_KEY_REGION,
           AwsClientProperties.CLIENT_REGION);
-      MixedCatalogUtil.copyProperty(
+      CatalogUtil.copyProperty(
           info.getStorageConfig(),
           catalogMeta.getCatalogProperties(),
           STORAGE_CONFIGS_KEY_ENDPOINT,
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
index 178c0001c..39cf9cd71 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/dashboard/controller/TableController.java
@@ -68,7 +68,7 @@ import org.apache.amoro.shade.guava32.com.google.common.util.concurrent.ThreadFa
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.metastore.api.Table;
@@ -171,7 +171,7 @@ public class TableController {
         "catalog.database.tableName can not be empty in any element");
     ServerCatalog serverCatalog = tableService.getServerCatalog(catalog);
     CatalogMeta catalogMeta = serverCatalog.getMetadata();
-    TableMetaStore tableMetaStore = MixedCatalogUtil.buildMetaStore(catalogMeta);
+    TableMetaStore tableMetaStore = CatalogUtil.buildMetaStore(catalogMeta);
     HMSClientPool hmsClientPool =
         new CachedHiveClientPool(tableMetaStore, catalogMeta.getCatalogProperties());
 
@@ -212,9 +212,9 @@ public class TableController {
     CatalogMeta catalogMeta = serverCatalog.getMetadata();
     String amsUri = AmsUtil.getAMSThriftAddress(serviceConfig, Constants.THRIFT_TABLE_SERVICE_NAME);
     catalogMeta.putToCatalogProperties(CatalogMetaProperties.AMS_URI, amsUri);
-    TableMetaStore tableMetaStore = MixedCatalogUtil.buildMetaStore(catalogMeta);
+    TableMetaStore tableMetaStore = CatalogUtil.buildMetaStore(catalogMeta);
     // check whether catalog support MIXED_HIVE format.
-    Set<TableFormat> tableFormats = MixedCatalogUtil.tableFormats(catalogMeta);
+    Set<TableFormat> tableFormats = CatalogUtil.tableFormats(catalogMeta);
     Preconditions.checkState(
         tableFormats.contains(TableFormat.MIXED_HIVE),
         "Catalog %s does not support MIXED_HIVE format",
@@ -527,7 +527,7 @@ public class TableController {
     String catalogType = serverCatalog.getMetadata().getCatalogType();
     if (catalogType.equals(CATALOG_TYPE_HIVE)) {
       CatalogMeta catalogMeta = serverCatalog.getMetadata();
-      TableMetaStore tableMetaStore = MixedCatalogUtil.buildMetaStore(catalogMeta);
+      TableMetaStore tableMetaStore = CatalogUtil.buildMetaStore(catalogMeta);
       HMSClientPool hmsClientPool =
           new CachedHiveClientPool(tableMetaStore, catalogMeta.getCatalogProperties());
 
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/manager/FlinkOptimizerContainer.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/manager/FlinkOptimizerContainer.java
index 593f3ae92..27dec48a0 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/manager/FlinkOptimizerContainer.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/manager/FlinkOptimizerContainer.java
@@ -231,6 +231,10 @@ public class FlinkOptimizerContainer extends AbstractResourceContainer {
         FlinkConfKeys.JOB_MANAGER_TOTAL_PROCESS_MEMORY, jobManagerMemory + "m");
     resourceFlinkConf.putToOptions(
         FlinkConfKeys.TASK_MANAGER_TOTAL_PROCESS_MEMORY, taskManagerMemory + "m");
+    resourceFlinkConf.putToOptions(
+        FlinkConfKeys.YARN_APPLICATION_JOB_NAME,
+        String.join(
+            "-", "Amoro-flink-optimizer", resource.getGroupName(), resource.getResourceId()));
 
     String flinkAction = target.isApplicationMode() ? "run-application" : "run";
     if (Target.KUBERNETES_APPLICATION == target) {
@@ -650,6 +654,8 @@ public class FlinkOptimizerContainer extends AbstractResourceContainer {
     public static final String KUBERNETES_CLUSTER_ID = "kubernetes.cluster-id";
     public static final String KUBERNETES_TASKMANAGER_LABELS = "kubernetes.taskmanager.labels";
     public static final String KUBERNETES_JOBMANAGER_LABELS = "kubernetes.jobmanager.labels";
+
+    public static final String YARN_APPLICATION_JOB_NAME = "yarn.application.name";
   }
 
   public static class FlinkConf {
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java
index 90237539d..e838440a9 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java
@@ -27,7 +27,7 @@ import org.apache.amoro.server.utils.InternalTableUtil;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.PrimaryKeySpec;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.amoro.utils.TablePropertyUtil;
 import org.apache.hadoop.fs.Path;
 import org.apache.iceberg.TableOperations;
@@ -65,7 +65,7 @@ public class InternalMixedIcebergHandler extends InternalIcebergHandler {
     if (InternalTableUtil.isLegacyMixedIceberg(tableMetadata())) {
       String tableLocation =
           changeStore ? tableMetadata().getChangeLocation() : tableMetadata().getBaseLocation();
-      TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(catalogMeta);
+      TableMetaStore metaStore = CatalogUtil.buildMetaStore(catalogMeta);
 
       MixedHadoopTableOperations ops =
           new MixedHadoopTableOperations(new Path(tableLocation), io, metaStore.getConfiguration());
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
index 2e3000448..47cb8ffc9 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/terminal/TerminalManager.java
@@ -36,7 +36,7 @@ import org.apache.amoro.server.terminal.local.LocalSessionFactory;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.iceberg.CatalogProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -251,7 +251,7 @@ public class TerminalManager {
 
   private String catalogConnectorType(CatalogMeta catalogMeta) {
     String catalogType = catalogMeta.getCatalogType();
-    Set<TableFormat> tableFormatSet = MixedCatalogUtil.tableFormats(catalogMeta);
+    Set<TableFormat> tableFormatSet = CatalogUtil.tableFormats(catalogMeta);
 
     if (catalogType.equalsIgnoreCase(CatalogType.AMS.name())) {
       if (tableFormatSet.contains(TableFormat.MIXED_ICEBERG)) {
@@ -294,7 +294,7 @@ public class TerminalManager {
     if (catalogMeta.getStorageConfigs() != null) {
       Map<String, String> storageConfigs = catalogMeta.getStorageConfigs();
       if (CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(
-          MixedCatalogUtil.getCompatibleStorageType(storageConfigs))) {
+          CatalogUtil.getCompatibleStorageType(storageConfigs))) {
         builder
             .withBase64MetaStoreSite(
                 catalogMeta
@@ -379,7 +379,7 @@ public class TerminalManager {
   }
 
   private void applyClientProperties(CatalogMeta catalogMeta) {
-    Set<TableFormat> formats = MixedCatalogUtil.tableFormats(catalogMeta);
+    Set<TableFormat> formats = CatalogUtil.tableFormats(catalogMeta);
     String catalogType = catalogMeta.getCatalogType();
     if (formats.contains(TableFormat.ICEBERG)) {
       if (CatalogMetaProperties.CATALOG_TYPE_AMS.equalsIgnoreCase(catalogType)) {
diff --git a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/InternalTableUtil.java b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/InternalTableUtil.java
index 0caecd51d..928fbce97 100644
--- a/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/InternalTableUtil.java
+++ b/amoro-ams/amoro-ams-server/src/main/java/org/apache/amoro/server/utils/InternalTableUtil.java
@@ -30,7 +30,7 @@ import org.apache.amoro.io.AuthenticatedFileIO;
 import org.apache.amoro.io.AuthenticatedFileIOs;
 import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.iceberg.CatalogProperties;
@@ -82,7 +82,7 @@ public class InternalTableUtil {
    */
   public static AuthenticatedFileIO newIcebergFileIo(CatalogMeta meta) {
     Map<String, String> catalogProperties = meta.getCatalogProperties();
-    TableMetaStore store = MixedCatalogUtil.buildMetaStore(meta);
+    TableMetaStore store = CatalogUtil.buildMetaStore(meta);
     Configuration conf = store.getConfiguration();
     String warehouse = meta.getCatalogProperties().get(CatalogMetaProperties.KEY_WAREHOUSE);
     String defaultImpl = HADOOP_FILE_IO_IMPL;
diff --git a/amoro-core/pom.xml b/amoro-core/pom.xml
index 52c1483c2..3166403d3 100644
--- a/amoro-core/pom.xml
+++ b/amoro-core/pom.xml
@@ -91,35 +91,6 @@
             <artifactId>kryo</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-data</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-orc</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-common</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-parquet</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-aws</artifactId>
-        </dependency>
 
         <dependency>
             <groupId>org.apache.parquet</groupId>
@@ -184,30 +155,6 @@
             <artifactId>lucene-core</artifactId>
         </dependency>
 
-        <!-- test dependencies -->
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-api</artifactId>
-            <version>${iceberg.version}</version>
-            <classifier>tests</classifier>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-core</artifactId>
-            <version>${iceberg.version}</version>
-            <classifier>tests</classifier>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.iceberg</groupId>
-            <artifactId>iceberg-data</artifactId>
-            <version>${iceberg.version}</version>
-            <classifier>tests</classifier>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
     <build>
diff --git a/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java b/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
index 55c639523..84e855972 100644
--- a/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/CommonUnifiedCatalog.java
@@ -22,7 +22,7 @@ import org.apache.amoro.api.CatalogMeta;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 
 import java.util.List;
 import java.util.Map;
@@ -45,9 +45,9 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
   public CommonUnifiedCatalog(
       Supplier<CatalogMeta> catalogMetaSupplier, Map<String, String> properties) {
     CatalogMeta catalogMeta = catalogMetaSupplier.get();
-    MixedCatalogUtil.mergeCatalogProperties(catalogMeta, properties);
+    CatalogUtil.mergeCatalogProperties(catalogMeta, properties);
     this.meta = catalogMeta;
-    this.tableMetaStore = MixedCatalogUtil.buildMetaStore(catalogMeta);
+    this.tableMetaStore = CatalogUtil.buildMetaStore(catalogMeta);
     this.properties.putAll(properties);
     this.metaSupplier = catalogMetaSupplier;
     initializeFormatCatalogs();
@@ -176,11 +176,11 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
   @Override
   public synchronized void refresh() {
     CatalogMeta newMeta = metaSupplier.get();
-    MixedCatalogUtil.mergeCatalogProperties(meta, properties);
+    CatalogUtil.mergeCatalogProperties(meta, properties);
     if (newMeta.equals(this.meta)) {
       return;
     }
-    this.tableMetaStore = MixedCatalogUtil.buildMetaStore(newMeta);
+    this.tableMetaStore = CatalogUtil.buildMetaStore(newMeta);
     this.meta = newMeta;
     this.initializeFormatCatalogs();
   }
@@ -192,8 +192,8 @@ public class CommonUnifiedCatalog implements UnifiedCatalog {
 
   protected void initializeFormatCatalogs() {
     ServiceLoader<FormatCatalogFactory> loader = ServiceLoader.load(FormatCatalogFactory.class);
-    Set<TableFormat> formats = MixedCatalogUtil.tableFormats(this.meta);
-    TableMetaStore store = MixedCatalogUtil.buildMetaStore(this.meta);
+    Set<TableFormat> formats = CatalogUtil.tableFormats(this.meta);
+    TableMetaStore store = CatalogUtil.buildMetaStore(this.meta);
     Map<TableFormat, FormatCatalog> formatCatalogs = Maps.newConcurrentMap();
     for (FormatCatalogFactory factory : loader) {
       if (formats.contains(factory.format())) {
diff --git a/amoro-core/src/main/java/org/apache/amoro/client/ClientPool.java b/amoro-core/src/main/java/org/apache/amoro/client/ClientPool.java
new file mode 100644
index 000000000..8c9fca4da
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/client/ClientPool.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.client;
+
+/**
+ * Copied from iceberg-common
+ *
+ * @param <C> client type
+ * @param <E> exception type that client will throw
+ */
+public interface ClientPool<C, E extends Exception> {
+  interface Action<R, C, E extends Exception> {
+    R run(C client) throws E;
+  }
+
+  <R> R run(Action<R, C, E> action) throws E, InterruptedException;
+
+  <R> R run(Action<R, C, E> action, boolean retry) throws E, InterruptedException;
+}
diff --git a/amoro-core/src/main/java/org/apache/amoro/client/ClientPoolImpl.java b/amoro-core/src/main/java/org/apache/amoro/client/ClientPoolImpl.java
new file mode 100644
index 000000000..52561f729
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/client/ClientPoolImpl.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.client;
+
+import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Closeable;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * Copied from iceberg-common
+ *
+ * @param <C> client type
+ * @param <E> exception type that client will throw
+ */
+public abstract class ClientPoolImpl<C, E extends Exception>
+    implements Closeable, ClientPool<C, E> {
+  private static final Logger LOG = LoggerFactory.getLogger(ClientPoolImpl.class);
+
+  private final int poolSize;
+  private final Deque<C> clients;
+  private final Class<? extends E> reconnectExc;
+  private final Object signal = new Object();
+  private final boolean retryByDefault;
+  private volatile int currentSize;
+  private boolean closed;
+
+  public ClientPoolImpl(int poolSize, Class<? extends E> reconnectExc, boolean retryByDefault) {
+    this.poolSize = poolSize;
+    this.reconnectExc = reconnectExc;
+    this.clients = new ArrayDeque<>(poolSize);
+    this.currentSize = 0;
+    this.closed = false;
+    this.retryByDefault = retryByDefault;
+  }
+
+  @Override
+  public <R> R run(Action<R, C, E> action) throws E, InterruptedException {
+    return run(action, retryByDefault);
+  }
+
+  @Override
+  public <R> R run(Action<R, C, E> action, boolean retry) throws E, InterruptedException {
+    C client = get();
+    try {
+      return action.run(client);
+
+    } catch (Exception exc) {
+      if (retry && isConnectionException(exc)) {
+        try {
+          client = reconnect(client);
+        } catch (Exception ignored) {
+          // if reconnection throws any exception, rethrow the original failure
+          throw reconnectExc.cast(exc);
+        }
+
+        return action.run(client);
+      }
+
+      throw exc;
+
+    } finally {
+      release(client);
+    }
+  }
+
+  protected abstract C newClient();
+
+  protected abstract C reconnect(C client);
+
+  protected boolean isConnectionException(Exception exc) {
+    return reconnectExc.isInstance(exc);
+  }
+
+  protected abstract void close(C client);
+
+  @Override
+  public void close() {
+    this.closed = true;
+    try {
+      while (currentSize > 0) {
+        if (!clients.isEmpty()) {
+          synchronized (this) {
+            if (!clients.isEmpty()) {
+              C client = clients.removeFirst();
+              close(client);
+              currentSize -= 1;
+            }
+          }
+        }
+        if (clients.isEmpty() && currentSize > 0) {
+          // wake every second in case this missed the signal
+          synchronized (signal) {
+            signal.wait(1000);
+          }
+        }
+      }
+
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      LOG.warn("Interrupted while shutting down pool. Some clients may not be closed.", e);
+    }
+  }
+
+  private C get() throws InterruptedException {
+    Preconditions.checkState(!closed, "Cannot get a client from a closed pool");
+    while (true) {
+      if (!clients.isEmpty() || currentSize < poolSize) {
+        synchronized (this) {
+          if (!clients.isEmpty()) {
+            return clients.removeFirst();
+          } else if (currentSize < poolSize) {
+            C client = newClient();
+            currentSize += 1;
+            return client;
+          }
+        }
+      }
+      synchronized (signal) {
+        // wake every second in case this missed the signal
+        signal.wait(1000);
+      }
+    }
+  }
+
+  private void release(C client) {
+    synchronized (this) {
+      clients.addFirst(client);
+    }
+    synchronized (signal) {
+      signal.notify();
+    }
+  }
+
+  public int poolSize() {
+    return poolSize;
+  }
+
+  public boolean isClosed() {
+    return closed;
+  }
+}
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHadoopCatalog.java b/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHadoopCatalog.java
index 2e696d3d2..b50f0b12f 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHadoopCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHadoopCatalog.java
@@ -27,7 +27,7 @@ import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
@@ -185,7 +185,7 @@ public class HudiHadoopCatalog implements FormatCatalog {
           Map<String, String> tableProperties =
               hoodieTable.getMetaClient().getTableConfig().propsMap();
           Map<String, String> properties =
-              MixedCatalogUtil.mergeCatalogPropertiesToTable(tableProperties, this.properties);
+              CatalogUtil.mergeCatalogPropertiesToTable(tableProperties, this.properties);
           return new HudiTable(identifier, hoodieTable, properties);
         });
   }
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHiveCatalog.java b/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHiveCatalog.java
index ba2a40302..3bf8deda1 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHiveCatalog.java
+++ b/amoro-core/src/main/java/org/apache/amoro/formats/hudi/HudiHiveCatalog.java
@@ -26,7 +26,7 @@ import org.apache.amoro.hive.HMSClient;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
@@ -190,7 +190,7 @@ public class HudiHiveCatalog implements FormatCatalog {
           Map<String, String> tableProperties = hiveTable.getParameters();
           tableProperties = filterEngineProperties(tableProperties);
           Map<String, String> properties =
-              MixedCatalogUtil.mergeCatalogPropertiesToTable(tableProperties, this.properties);
+              CatalogUtil.mergeCatalogPropertiesToTable(tableProperties, this.properties);
           return new HudiTable(identifier, hoodieTable, properties);
         });
   }
diff --git a/amoro-core/src/main/java/org/apache/amoro/hive/AuthenticatedHiveClientPool.java b/amoro-core/src/main/java/org/apache/amoro/hive/AuthenticatedHiveClientPool.java
index 8b7f7e407..33206eeb2 100644
--- a/amoro-core/src/main/java/org/apache/amoro/hive/AuthenticatedHiveClientPool.java
+++ b/amoro-core/src/main/java/org/apache/amoro/hive/AuthenticatedHiveClientPool.java
@@ -18,13 +18,13 @@
 
 package org.apache.amoro.hive;
 
+import org.apache.amoro.client.ClientPoolImpl;
 import org.apache.amoro.table.TableMetaStore;
+import org.apache.amoro.utils.DynConstructors;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
 import org.apache.hadoop.hive.metastore.api.MetaException;
-import org.apache.iceberg.ClientPoolImpl;
-import org.apache.iceberg.common.DynConstructors;
 import org.apache.iceberg.hive.RuntimeMetaException;
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransportException;
diff --git a/amoro-core/src/main/java/org/apache/amoro/hive/CachedHiveClientPool.java b/amoro-core/src/main/java/org/apache/amoro/hive/CachedHiveClientPool.java
index 7ddc666fa..0c5862257 100644
--- a/amoro-core/src/main/java/org/apache/amoro/hive/CachedHiveClientPool.java
+++ b/amoro-core/src/main/java/org/apache/amoro/hive/CachedHiveClientPool.java
@@ -22,6 +22,7 @@ import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.table.TableMetaStore;
+import org.apache.amoro.utils.PropertyUtil;
 import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
 import org.apache.hadoop.hive.metastore.api.InvalidObjectException;
 import org.apache.hadoop.hive.metastore.api.InvalidOperationException;
@@ -29,7 +30,6 @@ import org.apache.hadoop.hive.metastore.api.MetaException;
 import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
 import org.apache.hadoop.hive.metastore.api.UnknownDBException;
 import org.apache.hadoop.hive.metastore.api.UnknownTableException;
-import org.apache.iceberg.util.PropertyUtil;
 import org.apache.thrift.TException;
 
 import java.io.Serializable;
diff --git a/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientImpl.java b/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientImpl.java
index c4e11ad6c..85ddb6833 100644
--- a/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientImpl.java
+++ b/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientImpl.java
@@ -18,6 +18,7 @@
 
 package org.apache.amoro.hive;
 
+import org.apache.amoro.utils.DynMethods;
 import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
 import org.apache.hadoop.hive.metastore.PartitionDropOptions;
 import org.apache.hadoop.hive.metastore.api.Database;
@@ -25,7 +26,6 @@ import org.apache.hadoop.hive.metastore.api.EnvironmentContext;
 import org.apache.hadoop.hive.metastore.api.MetaException;
 import org.apache.hadoop.hive.metastore.api.Partition;
 import org.apache.hadoop.hive.metastore.api.Table;
-import org.apache.iceberg.common.DynMethods;
 import org.apache.thrift.TException;
 
 import java.util.List;
diff --git a/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientPool.java b/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientPool.java
index fa42ee7c5..889ff3b95 100644
--- a/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientPool.java
+++ b/amoro-core/src/main/java/org/apache/amoro/hive/HMSClientPool.java
@@ -18,7 +18,7 @@
 
 package org.apache.amoro.hive;
 
-import org.apache.iceberg.ClientPool;
+import org.apache.amoro.client.ClientPool;
 import org.apache.thrift.TException;
 
 public interface HMSClientPool extends ClientPool<HMSClient, TException> {}
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/TableMetaStore.java b/amoro-core/src/main/java/org/apache/amoro/table/TableMetaStore.java
index ef022d328..9983b159c 100644
--- a/amoro-core/src/main/java/org/apache/amoro/table/TableMetaStore.java
+++ b/amoro-core/src/main/java/org/apache/amoro/table/TableMetaStore.java
@@ -59,7 +59,7 @@ import java.util.Optional;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 
-/** Stores hadoop config files for {@link MixedTable} */
+/** Stores hadoop config files */
 public class TableMetaStore implements Serializable {
   private static final long serialVersionUID = 1L;
 
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/CatalogUtil.java b/amoro-core/src/main/java/org/apache/amoro/utils/CatalogUtil.java
new file mode 100644
index 000000000..89d3e7fdf
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/utils/CatalogUtil.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.utils;
+
+import org.apache.amoro.TableFormat;
+import org.apache.amoro.api.CatalogMeta;
+import org.apache.amoro.api.TableMeta;
+import org.apache.amoro.properties.CatalogMetaProperties;
+import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
+import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
+import org.apache.amoro.table.TableIdentifier;
+import org.apache.amoro.table.TableMetaStore;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class CatalogUtil {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CatalogUtil.class);
+
+  /** Return table format set catalog supported. */
+  public static Set<TableFormat> tableFormats(CatalogMeta meta) {
+    return tableFormats(meta.getCatalogType(), meta.getCatalogProperties());
+  }
+
+  /** Return table format set catalog supported. */
+  public static Set<TableFormat> tableFormats(
+      String metastoreType, Map<String, String> catalogProperties) {
+    if (catalogProperties != null
+        && catalogProperties.containsKey(CatalogMetaProperties.TABLE_FORMATS)) {
+      String tableFormatsProperty = catalogProperties.get(CatalogMetaProperties.TABLE_FORMATS);
+      return Arrays.stream(tableFormatsProperty.split(","))
+          .map(
+              tableFormatString ->
+                  TableFormat.valueOf(tableFormatString.trim().toUpperCase(Locale.ROOT)))
+          .collect(Collectors.toSet());
+    } else {
+      // Generate table format from catalog type for compatibility with older versions
+      switch (metastoreType) {
+        case CatalogMetaProperties.CATALOG_TYPE_AMS:
+          return Sets.newHashSet(TableFormat.MIXED_ICEBERG);
+        case CatalogMetaProperties.CATALOG_TYPE_CUSTOM:
+        case CatalogMetaProperties.CATALOG_TYPE_HADOOP:
+        case CatalogMetaProperties.CATALOG_TYPE_GLUE:
+          return Sets.newHashSet(TableFormat.ICEBERG);
+        case CatalogMetaProperties.CATALOG_TYPE_HIVE:
+          return Sets.newHashSet(TableFormat.MIXED_HIVE);
+        default:
+          throw new IllegalArgumentException("Unsupported catalog type:" + metastoreType);
+      }
+    }
+  }
+
+  /** Merge catalog properties in client side into catalog meta. */
+  public static void mergeCatalogProperties(CatalogMeta meta, Map<String, String> properties) {
+    if (meta.getCatalogProperties() == null) {
+      meta.setCatalogProperties(Maps.newHashMap());
+    }
+    if (properties != null) {
+      properties.forEach(meta::putToCatalogProperties);
+    }
+  }
+
+  /**
+   * merge properties of table level in catalog properties to table(properties key start with
+   * table.)
+   *
+   * @param tableProperties properties in table
+   * @param catalogProperties properties in catalog
+   * @return merged table properties
+   */
+  public static Map<String, String> mergeCatalogPropertiesToTable(
+      Map<String, String> tableProperties, Map<String, String> catalogProperties) {
+    Map<String, String> mergedProperties =
+        catalogProperties.entrySet().stream()
+            .filter(e -> e.getKey().startsWith(CatalogMetaProperties.TABLE_PROPERTIES_PREFIX))
+            .collect(
+                Collectors.toMap(
+                    e ->
+                        e.getKey()
+                            .substring(CatalogMetaProperties.TABLE_PROPERTIES_PREFIX.length()),
+                    Map.Entry::getValue));
+    mergedProperties.putAll(tableProperties);
+    return mergedProperties;
+  }
+
+  /** Build {@link TableMetaStore} from catalog meta. */
+  public static TableMetaStore buildMetaStore(CatalogMeta catalogMeta) {
+    // load storage configs
+    TableMetaStore.Builder builder = TableMetaStore.builder();
+    if (catalogMeta.getStorageConfigs() != null) {
+      Map<String, String> storageConfigs = catalogMeta.getStorageConfigs();
+      if (CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(
+          CatalogUtil.getCompatibleStorageType(storageConfigs))) {
+        String coreSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_CORE_SITE);
+        String hdfsSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HDFS_SITE);
+        String hiveSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HIVE_SITE);
+        builder
+            .withBase64CoreSite(coreSite)
+            .withBase64MetaStoreSite(hiveSite)
+            .withBase64HdfsSite(hdfsSite);
+      }
+    }
+
+    boolean loadAuthFromAMS =
+        propertyAsBoolean(
+            catalogMeta.getCatalogProperties(),
+            CatalogMetaProperties.LOAD_AUTH_FROM_AMS,
+            CatalogMetaProperties.LOAD_AUTH_FROM_AMS_DEFAULT);
+    // load auth configs from ams
+    if (loadAuthFromAMS) {
+      if (catalogMeta.getAuthConfigs() != null) {
+        Map<String, String> authConfigs = catalogMeta.getAuthConfigs();
+        String authType = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
+        LOG.info("TableMetaStore use auth config in catalog meta, authType is {}", authType);
+        if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE.equalsIgnoreCase(authType)) {
+          String hadoopUsername =
+              authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
+          builder.withSimpleAuth(hadoopUsername);
+        } else if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_KERBEROS.equalsIgnoreCase(
+            authType)) {
+          String krb5 = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
+          String keytab = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
+          String principal = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
+          builder.withBase64KrbAuth(keytab, krb5, principal);
+        } else if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_AK_SK.equalsIgnoreCase(authType)) {
+          String accessKey = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
+          String secretKey = authConfigs.get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
+          builder.withAkSkAuth(accessKey, secretKey);
+        }
+      }
+    }
+
+    // cover auth configs from ams with auth configs in properties
+    String authType =
+        catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_TYPE);
+    if (StringUtils.isNotEmpty(authType)) {
+      LOG.info("TableMetaStore use auth config in properties, authType is {}", authType);
+      if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_SIMPLE.equalsIgnoreCase(authType)) {
+        String hadoopUsername =
+            catalogMeta
+                .getCatalogProperties()
+                .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_HADOOP_USERNAME);
+        builder.withSimpleAuth(hadoopUsername);
+      } else if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_KERBEROS.equalsIgnoreCase(
+          authType)) {
+        String krb5 =
+            catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KRB5);
+        String keytab =
+            catalogMeta.getCatalogProperties().get(CatalogMetaProperties.AUTH_CONFIGS_KEY_KEYTAB);
+        String principal =
+            catalogMeta
+                .getCatalogProperties()
+                .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_PRINCIPAL);
+        builder.withBase64KrbAuth(keytab, krb5, principal);
+      } else if (CatalogMetaProperties.AUTH_CONFIGS_VALUE_TYPE_AK_SK.equalsIgnoreCase(authType)) {
+        String accessKey =
+            catalogMeta
+                .getCatalogProperties()
+                .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_ACCESS_KEY);
+        String secretKey =
+            catalogMeta
+                .getCatalogProperties()
+                .get(CatalogMetaProperties.AUTH_CONFIGS_KEY_SECRET_KEY);
+        builder.withAkSkAuth(accessKey, secretKey);
+      }
+    }
+    return builder.build();
+  }
+
+  public static TableIdentifier tableId(TableMeta tableMeta) {
+    return TableIdentifier.of(
+        tableMeta.getTableIdentifier().getCatalog(),
+        tableMeta.getTableIdentifier().getDatabase(),
+        tableMeta.getTableIdentifier().getTableName());
+  }
+
+  public static org.apache.amoro.api.TableIdentifier amsTaleId(TableIdentifier tableIdentifier) {
+    return new org.apache.amoro.api.TableIdentifier(
+        tableIdentifier.getCatalog(),
+        tableIdentifier.getDatabase(),
+        tableIdentifier.getTableName());
+  }
+
+  /**
+   * Get storage type compatible with history storage type `hdfs`, which is `Hadoop` now.
+   *
+   * @param conf - configurations containing `storage.type`
+   * @return storage type, return `Hadoop` if `storage.type` is `hdfs`, return null if
+   *     `storage.type` not exist.
+   */
+  public static String getCompatibleStorageType(Map<String, String> conf) {
+    if (CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HDFS_LEGACY.equals(
+        conf.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_TYPE))) {
+      return CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP;
+    }
+    return conf.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_TYPE);
+  }
+
+  /**
+   * Copy property from source properties to target properties, support changing the key name.
+   *
+   * @param fromProperties - from these properties
+   * @param toProperties - to these properties
+   * @param fromKey - from key
+   * @param toKey - to key
+   */
+  public static <T> void copyProperty(
+      Map<String, String> fromProperties,
+      Map<String, T> toProperties,
+      String fromKey,
+      String toKey) {
+    if (StringUtils.isNotEmpty(fromProperties.get(fromKey))) {
+      toProperties.put(toKey, (T) fromProperties.get(fromKey));
+    }
+  }
+
+  private static boolean propertyAsBoolean(
+      Map<String, String> properties, String property, boolean defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Boolean.parseBoolean(value);
+    }
+    return defaultValue;
+  }
+}
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/DynConstructors.java b/amoro-core/src/main/java/org/apache/amoro/utils/DynConstructors.java
new file mode 100644
index 000000000..6ad3ba4de
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/utils/DynConstructors.java
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.utils;
+
+import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
+import org.apache.amoro.shade.guava32.com.google.common.base.Throwables;
+import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Map;
+
+/** Copied from parquet-common */
+public class DynConstructors {
+
+  private DynConstructors() {}
+
+  public static class Ctor<C> extends DynMethods.UnboundMethod {
+    private final Constructor<C> ctor;
+    private final Class<? extends C> constructed;
+
+    private Ctor(Constructor<C> constructor, Class<? extends C> constructed) {
+      super(null, "newInstance");
+      this.ctor = constructor;
+      this.constructed = constructed;
+    }
+
+    public Class<? extends C> getConstructedClass() {
+      return constructed;
+    }
+
+    public C newInstanceChecked(Object... args) throws Exception {
+      try {
+        if (args.length > ctor.getParameterCount()) {
+          return ctor.newInstance(Arrays.copyOfRange(args, 0, ctor.getParameterCount()));
+        } else {
+          return ctor.newInstance(args);
+        }
+      } catch (InstantiationException | IllegalAccessException e) {
+        throw e;
+      } catch (InvocationTargetException e) {
+        Throwables.throwIfInstanceOf(e.getCause(), Exception.class);
+        Throwables.throwIfInstanceOf(e.getCause(), RuntimeException.class);
+        Throwables.throwIfUnchecked(e.getCause());
+        throw new RuntimeException(e.getCause());
+      }
+    }
+
+    public C newInstance(Object... args) {
+      try {
+        return newInstanceChecked(args);
+      } catch (Exception e) {
+        Throwables.throwIfInstanceOf(e, RuntimeException.class);
+        Throwables.throwIfUnchecked(e.getCause());
+        throw new RuntimeException(e.getCause());
+      }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <R> R invoke(Object target, Object... args) {
+      Preconditions.checkArgument(
+          target == null, "Invalid call to constructor: target must be null");
+      return (R) newInstance(args);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <R> R invokeChecked(Object target, Object... args) throws Exception {
+      Preconditions.checkArgument(
+          target == null, "Invalid call to constructor: target must be null");
+      return (R) newInstanceChecked(args);
+    }
+
+    @Override
+    public DynMethods.BoundMethod bind(Object receiver) {
+      throw new IllegalStateException("Cannot bind constructors");
+    }
+
+    @Override
+    public boolean isStatic() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return getClass().getSimpleName() + "(constructor=" + ctor + ", class=" + constructed + ")";
+    }
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static Builder builder(Class<?> baseClass) {
+    return new Builder(baseClass);
+  }
+
+  public static class Builder {
+    private final Class<?> baseClass;
+    private ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    private Ctor ctor = null;
+    private Map<String, Throwable> problems = Maps.newHashMap();
+
+    public Builder(Class<?> baseClass) {
+      this.baseClass = baseClass;
+    }
+
+    public Builder() {
+      this.baseClass = null;
+    }
+
+    /**
+     * Set the {@link ClassLoader} used to lookup classes by name.
+     *
+     * <p>If not set, the current thread's ClassLoader is used.
+     *
+     * @param newLoader a ClassLoader
+     * @return this Builder for method chaining
+     */
+    public Builder loader(ClassLoader newLoader) {
+      this.loader = newLoader;
+      return this;
+    }
+
+    public Builder impl(String className, Class<?>... types) {
+      // don't do any work if an implementation has been found
+      if (ctor != null) {
+        return this;
+      }
+
+      try {
+        Class<?> targetClass = Class.forName(className, true, loader);
+        impl(targetClass, types);
+      } catch (NoClassDefFoundError | ClassNotFoundException e) {
+        // cannot load this implementation
+        problems.put(className, e);
+      }
+      return this;
+    }
+
+    public <T> Builder impl(Class<T> targetClass, Class<?>... types) {
+      // don't do any work if an implementation has been found
+      if (ctor != null) {
+        return this;
+      }
+
+      try {
+        ctor = new Ctor<T>(targetClass.getConstructor(types), targetClass);
+      } catch (NoSuchMethodException e) {
+        // not the right implementation
+        problems.put(methodName(targetClass, types), e);
+      }
+      return this;
+    }
+
+    public Builder hiddenImpl(Class<?>... types) {
+      hiddenImpl(baseClass, types);
+      return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Builder hiddenImpl(String className, Class<?>... types) {
+      // don't do any work if an implementation has been found
+      if (ctor != null) {
+        return this;
+      }
+
+      try {
+        Class targetClass = Class.forName(className, true, loader);
+        hiddenImpl(targetClass, types);
+      } catch (NoClassDefFoundError | ClassNotFoundException e) {
+        // cannot load this implementation
+        problems.put(className, e);
+      }
+      return this;
+    }
+
+    public <T> Builder hiddenImpl(Class<T> targetClass, Class<?>... types) {
+      // don't do any work if an implementation has been found
+      if (ctor != null) {
+        return this;
+      }
+
+      try {
+        Constructor<T> hidden = targetClass.getDeclaredConstructor(types);
+        AccessController.doPrivileged(new MakeAccessible(hidden));
+        ctor = new Ctor<T>(hidden, targetClass);
+      } catch (SecurityException e) {
+        // unusable
+        problems.put(methodName(targetClass, types), e);
+      } catch (NoSuchMethodException e) {
+        // not the right implementation
+        problems.put(methodName(targetClass, types), e);
+      }
+      return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <C> Ctor<C> buildChecked() throws NoSuchMethodException {
+      if (ctor != null) {
+        return ctor;
+      }
+      throw buildCheckedException(baseClass, problems);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <C> Ctor<C> build() {
+      if (ctor != null) {
+        return ctor;
+      }
+      throw buildRuntimeException(baseClass, problems);
+    }
+  }
+
+  private static class MakeAccessible implements PrivilegedAction<Void> {
+    private Constructor<?> hidden;
+
+    MakeAccessible(Constructor<?> hidden) {
+      this.hidden = hidden;
+    }
+
+    @Override
+    public Void run() {
+      hidden.setAccessible(true);
+      return null;
+    }
+  }
+
+  private static NoSuchMethodException buildCheckedException(
+      Class<?> baseClass, Map<String, Throwable> problems) {
+    NoSuchMethodException exc =
+        new NoSuchMethodException(
+            "Cannot find constructor for " + baseClass + "\n" + formatProblems(problems));
+    problems.values().forEach(exc::addSuppressed);
+    return exc;
+  }
+
+  private static RuntimeException buildRuntimeException(
+      Class<?> baseClass, Map<String, Throwable> problems) {
+    RuntimeException exc =
+        new RuntimeException(
+            "Cannot find constructor for " + baseClass + "\n" + formatProblems(problems));
+    problems.values().forEach(exc::addSuppressed);
+    return exc;
+  }
+
+  private static String formatProblems(Map<String, Throwable> problems) {
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (Map.Entry<String, Throwable> problem : problems.entrySet()) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append("\n");
+      }
+      sb.append("\tMissing ")
+          .append(problem.getKey())
+          .append(" [")
+          .append(problem.getValue().getClass().getName())
+          .append(": ")
+          .append(problem.getValue().getMessage())
+          .append("]");
+    }
+    return sb.toString();
+  }
+
+  private static String methodName(Class<?> targetClass, Class<?>... types) {
+    StringBuilder sb = new StringBuilder();
+    sb.append(targetClass.getName()).append("(");
+    boolean first = true;
+    for (Class<?> type : types) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(",");
+      }
+      sb.append(type.getName());
+    }
+    sb.append(")");
+    return sb.toString();
+  }
+}
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/DynMethods.java b/amoro-core/src/main/java/org/apache/amoro/utils/DynMethods.java
new file mode 100644
index 000000000..68532547f
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/utils/DynMethods.java
@@ -0,0 +1,526 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.utils;
+
+import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
+import org.apache.amoro.shade.guava32.com.google.common.base.Throwables;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+
+/** Copied from parquet-common */
+public class DynMethods {
+
+  private DynMethods() {}
+
+  /**
+   * Convenience wrapper class around {@link java.lang.reflect.Method}.
+   *
+   * <p>Allows callers to invoke the wrapped method with all Exceptions wrapped by RuntimeException,
+   * or with a single Exception catch block.
+   */
+  public static class UnboundMethod {
+
+    private final Method method;
+    private final String name;
+    private final int argLength;
+
+    UnboundMethod(Method method, String name) {
+      this.method = method;
+      this.name = name;
+      this.argLength =
+          (method == null || method.isVarArgs()) ? -1 : method.getParameterTypes().length;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <R> R invokeChecked(Object target, Object... args) throws Exception {
+      try {
+        if (argLength < 0) {
+          return (R) method.invoke(target, args);
+        } else {
+          return (R) method.invoke(target, Arrays.copyOfRange(args, 0, argLength));
+        }
+
+      } catch (InvocationTargetException e) {
+        Throwables.throwIfInstanceOf(e.getCause(), Exception.class);
+        Throwables.throwIfInstanceOf(e.getCause(), RuntimeException.class);
+        Throwables.throwIfUnchecked(e.getCause());
+        throw new RuntimeException(e.getCause());
+      }
+    }
+
+    public <R> R invoke(Object target, Object... args) {
+      try {
+        return this.invokeChecked(target, args);
+      } catch (Exception e) {
+        Throwables.throwIfInstanceOf(e, RuntimeException.class);
+        Throwables.throwIfUnchecked(e.getCause());
+        throw new RuntimeException(e.getCause());
+      }
+    }
+
+    /**
+     * Returns this method as a BoundMethod for the given receiver.
+     *
+     * @param receiver an Object to receive the method invocation
+     * @return a {@link BoundMethod} for this method and the receiver
+     * @throws IllegalStateException if the method is static
+     * @throws IllegalArgumentException if the receiver's class is incompatible
+     */
+    public BoundMethod bind(Object receiver) {
+      Preconditions.checkState(
+          !isStatic(), "Cannot bind static method %s", method.toGenericString());
+      Preconditions.checkArgument(
+          method.getDeclaringClass().isAssignableFrom(receiver.getClass()),
+          "Cannot bind %s to instance of %s",
+          method.toGenericString(),
+          receiver.getClass());
+
+      return new BoundMethod(this, receiver);
+    }
+
+    /** Returns whether the method is a static method. */
+    public boolean isStatic() {
+      return Modifier.isStatic(method.getModifiers());
+    }
+
+    /** Returns whether the method is a noop. */
+    public boolean isNoop() {
+      return this == NOOP;
+    }
+
+    /**
+     * Returns this method as a StaticMethod.
+     *
+     * @return a {@link StaticMethod} for this method
+     * @throws IllegalStateException if the method is not static
+     */
+    public StaticMethod asStatic() {
+      Preconditions.checkState(isStatic(), "Method is not static");
+      return new StaticMethod(this);
+    }
+
+    @Override
+    public String toString() {
+      return "DynMethods.UnboundMethod(name=" + name + " method=" + method.toGenericString() + ")";
+    }
+
+    /** Singleton {@link UnboundMethod}, performs no operation and returns null. */
+    private static final UnboundMethod NOOP =
+        new UnboundMethod(null, "NOOP") {
+          @Override
+          public <R> R invokeChecked(Object target, Object... args) throws Exception {
+            return null;
+          }
+
+          @Override
+          public BoundMethod bind(Object receiver) {
+            return new BoundMethod(this, receiver);
+          }
+
+          @Override
+          public StaticMethod asStatic() {
+            return new StaticMethod(this);
+          }
+
+          @Override
+          public boolean isStatic() {
+            return true;
+          }
+
+          @Override
+          public String toString() {
+            return "DynMethods.UnboundMethod(NOOP)";
+          }
+        };
+  }
+
+  public static class BoundMethod {
+    private final UnboundMethod method;
+    private final Object receiver;
+
+    private BoundMethod(UnboundMethod method, Object receiver) {
+      this.method = method;
+      this.receiver = receiver;
+    }
+
+    public <R> R invokeChecked(Object... args) throws Exception {
+      return method.invokeChecked(receiver, args);
+    }
+
+    public <R> R invoke(Object... args) {
+      return method.invoke(receiver, args);
+    }
+  }
+
+  public static class StaticMethod {
+    private final UnboundMethod method;
+
+    private StaticMethod(UnboundMethod method) {
+      this.method = method;
+    }
+
+    public <R> R invokeChecked(Object... args) throws Exception {
+      return method.invokeChecked(null, args);
+    }
+
+    public <R> R invoke(Object... args) {
+      return method.invoke(null, args);
+    }
+  }
+
+  /**
+   * Constructs a new builder for calling methods dynamically.
+   *
+   * @param methodName name of the method the builder will locate
+   * @return a Builder for finding a method
+   */
+  public static Builder builder(String methodName) {
+    return new Builder(methodName);
+  }
+
+  public static class Builder {
+    private final String name;
+    private ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    private UnboundMethod method = null;
+
+    public Builder(String methodName) {
+      this.name = methodName;
+    }
+
+    /**
+     * Set the {@link ClassLoader} used to lookup classes by name.
+     *
+     * <p>If not set, the current thread's ClassLoader is used.
+     *
+     * @param newLoader a ClassLoader
+     * @return this Builder for method chaining
+     */
+    public Builder loader(ClassLoader newLoader) {
+      this.loader = newLoader;
+      return this;
+    }
+
+    /**
+     * If no implementation has been found, adds a NOOP method.
+     *
+     * <p>Note: calls to impl will not match after this method is called!
+     *
+     * @return this Builder for method chaining
+     */
+    public Builder orNoop() {
+      if (method == null) {
+        this.method = UnboundMethod.NOOP;
+      }
+      return this;
+    }
+
+    /**
+     * Checks for an implementation, first finding the given class by name.
+     *
+     * @param className name of a class
+     * @param methodName name of a method (different from constructor)
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder impl(String className, String methodName, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        Class<?> targetClass = Class.forName(className, true, loader);
+        impl(targetClass, methodName, argClasses);
+      } catch (ClassNotFoundException e) {
+        // not the right implementation
+      }
+      return this;
+    }
+
+    /**
+     * Checks for an implementation, first finding the given class by name.
+     *
+     * <p>The name passed to the constructor is the method name used.
+     *
+     * @param className name of a class
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder impl(String className, Class<?>... argClasses) {
+      impl(className, name, argClasses);
+      return this;
+    }
+
+    /**
+     * Checks for a method implementation.
+     *
+     * @param targetClass a class instance
+     * @param methodName name of a method (different from constructor)
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder impl(Class<?> targetClass, String methodName, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        this.method = new UnboundMethod(targetClass.getMethod(methodName, argClasses), name);
+      } catch (NoSuchMethodException e) {
+        // not the right implementation
+      }
+      return this;
+    }
+
+    /**
+     * Checks for a method implementation.
+     *
+     * <p>The name passed to the constructor is the method name used.
+     *
+     * @param targetClass a class instance
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder impl(Class<?> targetClass, Class<?>... argClasses) {
+      impl(targetClass, name, argClasses);
+      return this;
+    }
+
+    public Builder ctorImpl(Class<?> targetClass, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        this.method = new DynConstructors.Builder().impl(targetClass, argClasses).buildChecked();
+      } catch (NoSuchMethodException e) {
+        // not the right implementation
+      }
+      return this;
+    }
+
+    public Builder ctorImpl(String className, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        this.method = new DynConstructors.Builder().impl(className, argClasses).buildChecked();
+      } catch (NoSuchMethodException e) {
+        // not the right implementation
+      }
+      return this;
+    }
+
+    /**
+     * Checks for an implementation, first finding the given class by name.
+     *
+     * @param className name of a class
+     * @param methodName name of a method (different from constructor)
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder hiddenImpl(String className, String methodName, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        Class<?> targetClass = Class.forName(className, true, loader);
+        hiddenImpl(targetClass, methodName, argClasses);
+      } catch (ClassNotFoundException e) {
+        // not the right implementation
+      }
+      return this;
+    }
+
+    /**
+     * Checks for an implementation, first finding the given class by name.
+     *
+     * <p>The name passed to the constructor is the method name used.
+     *
+     * @param className name of a class
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder hiddenImpl(String className, Class<?>... argClasses) {
+      hiddenImpl(className, name, argClasses);
+      return this;
+    }
+
+    /**
+     * Checks for a method implementation.
+     *
+     * @param targetClass a class instance
+     * @param methodName name of a method (different from constructor)
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder hiddenImpl(Class<?> targetClass, String methodName, Class<?>... argClasses) {
+      // don't do any work if an implementation has been found
+      if (method != null) {
+        return this;
+      }
+
+      try {
+        Method hidden = targetClass.getDeclaredMethod(methodName, argClasses);
+        AccessController.doPrivileged(new MakeAccessible(hidden));
+        this.method = new UnboundMethod(hidden, name);
+      } catch (SecurityException | NoSuchMethodException e) {
+        // unusable or not the right implementation
+      }
+      return this;
+    }
+
+    /**
+     * Checks for a method implementation.
+     *
+     * <p>The name passed to the constructor is the method name used.
+     *
+     * @param targetClass a class instance
+     * @param argClasses argument classes for the method
+     * @return this Builder for method chaining
+     * @see java.lang.Class#forName(String)
+     * @see java.lang.Class#getMethod(String, Class[])
+     */
+    public Builder hiddenImpl(Class<?> targetClass, Class<?>... argClasses) {
+      hiddenImpl(targetClass, name, argClasses);
+      return this;
+    }
+
+    /**
+     * Returns the first valid implementation as a UnboundMethod or throws a RuntimeError if there
+     * is none.
+     *
+     * @return a {@link UnboundMethod} with a valid implementation
+     * @throws RuntimeException if no implementation was found
+     */
+    public UnboundMethod build() {
+      if (method != null) {
+        return method;
+      } else {
+        throw new RuntimeException("Cannot find method: " + name);
+      }
+    }
+
+    /**
+     * Returns the first valid implementation as a BoundMethod or throws a RuntimeError if there is
+     * none.
+     *
+     * @param receiver an Object to receive the method invocation
+     * @return a {@link BoundMethod} with a valid implementation and receiver
+     * @throws IllegalStateException if the method is static
+     * @throws IllegalArgumentException if the receiver's class is incompatible
+     * @throws RuntimeException if no implementation was found
+     */
+    public BoundMethod build(Object receiver) {
+      return build().bind(receiver);
+    }
+
+    /**
+     * Returns the first valid implementation as a UnboundMethod or throws a NoSuchMethodException
+     * if there is none.
+     *
+     * @return a {@link UnboundMethod} with a valid implementation
+     * @throws NoSuchMethodException if no implementation was found
+     */
+    public UnboundMethod buildChecked() throws NoSuchMethodException {
+      if (method != null) {
+        return method;
+      } else {
+        throw new NoSuchMethodException("Cannot find method: " + name);
+      }
+    }
+
+    /**
+     * Returns the first valid implementation as a BoundMethod or throws a NoSuchMethodException if
+     * there is none.
+     *
+     * @param receiver an Object to receive the method invocation
+     * @return a {@link BoundMethod} with a valid implementation and receiver
+     * @throws IllegalStateException if the method is static
+     * @throws IllegalArgumentException if the receiver's class is incompatible
+     * @throws NoSuchMethodException if no implementation was found
+     */
+    public BoundMethod buildChecked(Object receiver) throws NoSuchMethodException {
+      return buildChecked().bind(receiver);
+    }
+
+    /**
+     * Returns the first valid implementation as a StaticMethod or throws a NoSuchMethodException if
+     * there is none.
+     *
+     * @return a {@link StaticMethod} with a valid implementation
+     * @throws IllegalStateException if the method is not static
+     * @throws NoSuchMethodException if no implementation was found
+     */
+    public StaticMethod buildStaticChecked() throws NoSuchMethodException {
+      return buildChecked().asStatic();
+    }
+
+    /**
+     * Returns the first valid implementation as a StaticMethod or throws a RuntimeException if
+     * there is none.
+     *
+     * @return a {@link StaticMethod} with a valid implementation
+     * @throws IllegalStateException if the method is not static
+     * @throws RuntimeException if no implementation was found
+     */
+    public StaticMethod buildStatic() {
+      return build().asStatic();
+    }
+  }
+
+  private static class MakeAccessible implements PrivilegedAction<Void> {
+    private Method hidden;
+
+    MakeAccessible(Method hidden) {
+      this.hidden = hidden;
+    }
+
+    @Override
+    public Void run() {
+      hidden.setAccessible(true);
+      return null;
+    }
+  }
+}
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/PropertyUtil.java b/amoro-core/src/main/java/org/apache/amoro/utils/PropertyUtil.java
new file mode 100644
index 000000000..9b2c50719
--- /dev/null
+++ b/amoro-core/src/main/java/org/apache/amoro/utils/PropertyUtil.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.amoro.utils;
+
+import java.util.Map;
+
+/** Partial Copied from parquet-common */
+public class PropertyUtil {
+  private PropertyUtil() {}
+
+  public static boolean propertyAsBoolean(
+      Map<String, String> properties, String property, boolean defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Boolean.parseBoolean(value);
+    }
+    return defaultValue;
+  }
+
+  public static Boolean propertyAsNullableBoolean(Map<String, String> properties, String property) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Boolean.parseBoolean(value);
+    }
+    return null;
+  }
+
+  public static double propertyAsDouble(
+      Map<String, String> properties, String property, double defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Double.parseDouble(value);
+    }
+    return defaultValue;
+  }
+
+  public static int propertyAsInt(
+      Map<String, String> properties, String property, int defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Integer.parseInt(value);
+    }
+    return defaultValue;
+  }
+
+  public static Integer propertyAsNullableInt(Map<String, String> properties, String property) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Integer.parseInt(value);
+    }
+    return null;
+  }
+
+  public static long propertyAsLong(
+      Map<String, String> properties, String property, long defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Long.parseLong(value);
+    }
+    return defaultValue;
+  }
+
+  public static Long propertyAsNullableLong(Map<String, String> properties, String property) {
+    String value = properties.get(property);
+    if (value != null) {
+      return Long.parseLong(value);
+    }
+    return null;
+  }
+
+  public static String propertyAsString(
+      Map<String, String> properties, String property, String defaultValue) {
+    String value = properties.get(property);
+    if (value != null) {
+      return value;
+    }
+    return defaultValue;
+  }
+}
diff --git a/amoro-core/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory b/amoro-core/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory
index 04900c921..72d74f17d 100644
--- a/amoro-core/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory
+++ b/amoro-core/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory
@@ -16,8 +16,5 @@
 # limitations under the License.
 #
 
-org.apache.amoro.formats.iceberg.IcebergCatalogFactory
 org.apache.amoro.formats.paimon.PaimonCatalogFactory
-org.apache.amoro.formats.mixed.MixedIcebergCatalogFactory
-org.apache.amoro.formats.mixed.MixedHiveCatalogFactory
 org.apache.amoro.formats.hudi.HudiCatalogFactory
\ No newline at end of file
diff --git a/amoro-iceberg-format/pom.xml b/amoro-iceberg-format/pom.xml
new file mode 100644
index 000000000..43d87feb1
--- /dev/null
+++ b/amoro-iceberg-format/pom.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.amoro</groupId>
+        <artifactId>amoro-parent</artifactId>
+        <version>0.8-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>amoro-iceberg-format</artifactId>
+    <name>Amoro Project Iceberg Format</name>
+    <url>https://amoro.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-shade-thrift</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-shade-guava-32</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-shade-jackson-2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-shade-zookeeper-3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.esotericsoftware</groupId>
+            <artifactId>kryo</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-data</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-orc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-parquet</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-aws</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.parquet</groupId>
+            <artifactId>parquet-avro</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-auth</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-client</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.kerby</groupId>
+            <artifactId>kerb-simplekdc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.orc</groupId>
+            <artifactId>orc-core</artifactId>
+            <classifier>nohive</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.paimon</groupId>
+            <artifactId>paimon-bundle</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.roaringbitmap</groupId>
+            <artifactId>RoaringBitmap</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-bundled-guava</artifactId>
+            <version>${iceberg.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.rocksdb</groupId>
+            <artifactId>rocksdbjni</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.lucene</groupId>
+            <artifactId>lucene-core</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-core</artifactId>
+            <version>${parent.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-api</artifactId>
+            <version>${iceberg.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-core</artifactId>
+            <version>${iceberg.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.iceberg</groupId>
+            <artifactId>iceberg-data</artifactId>
+            <version>${iceberg.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/amoro-core/src/main/java/org/apache/amoro/IcebergFileEntry.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/IcebergFileEntry.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/IcebergFileEntry.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/IcebergFileEntry.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/ChangeAction.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/ChangeAction.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/ChangeAction.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/ChangeAction.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/ChangedLsn.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/ChangedLsn.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/ChangedLsn.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/ChangedLsn.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/DataFileType.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/DataFileType.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/DataFileType.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/DataFileType.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/DataTreeNode.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/DataTreeNode.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/DataTreeNode.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/DataTreeNode.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/DefaultKeyedFile.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/DefaultKeyedFile.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/DefaultKeyedFile.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/DefaultKeyedFile.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/FileNameRules.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/FileNameRules.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/FileNameRules.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/FileNameRules.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/PrimaryKeyData.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/PrimaryKeyData.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/PrimaryKeyData.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/PrimaryKeyData.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/data/PrimaryKeyedFile.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/data/PrimaryKeyedFile.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/data/PrimaryKeyedFile.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/data/PrimaryKeyedFile.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
similarity index 96%
rename from amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
index d99129ed7..3406db634 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalog.java
@@ -21,7 +21,7 @@ package org.apache.amoro.formats.iceberg;
 import org.apache.amoro.AmoroTable;
 import org.apache.amoro.FormatCatalog;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.iceberg.Table;
 import org.apache.iceberg.catalog.Catalog;
 import org.apache.iceberg.catalog.Namespace;
@@ -41,7 +41,7 @@ public class IcebergCatalog implements FormatCatalog {
   private final Map<String, String> properties;
 
   public IcebergCatalog(Catalog catalog, Map<String, String> properties, TableMetaStore metaStore) {
-    this.icebergCatalog = MixedCatalogUtil.buildCacheCatalog(catalog, properties);
+    this.icebergCatalog = MixedFormatCatalogUtil.buildCacheCatalog(catalog, properties);
     if (catalog instanceof SupportsNamespaces) {
       this.asNamespaceCatalog = (SupportsNamespaces) catalog;
     }
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java
similarity index 89%
rename from amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java
index 6433900eb..432fa81b3 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergCatalogFactory.java
@@ -23,7 +23,7 @@ import org.apache.amoro.FormatCatalogFactory;
 import org.apache.amoro.TableFormat;
 import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.iceberg.CatalogUtil;
 import org.apache.iceberg.catalog.Catalog;
@@ -37,7 +37,8 @@ public class IcebergCatalogFactory implements FormatCatalogFactory {
       String name, String metastoreType, Map<String, String> properties, TableMetaStore metaStore) {
     Preconditions.checkArgument(StringUtils.isNotBlank(metastoreType), "metastore type is blank");
     properties =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(name, metastoreType, properties);
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
+            name, metastoreType, properties);
 
     Catalog icebergCatalog =
         CatalogUtil.buildIcebergCatalog(name, properties, metaStore.getConfiguration());
@@ -52,7 +53,7 @@ public class IcebergCatalogFactory implements FormatCatalogFactory {
   @Override
   public Map<String, String> convertCatalogProperties(
       String catalogName, String metastoreType, Map<String, String> unifiedCatalogProperties) {
-    return MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+    return MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
         catalogName, metastoreType, unifiedCatalogProperties);
   }
 }
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergSnapshot.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergSnapshot.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergSnapshot.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergSnapshot.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java
similarity index 96%
rename from amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java
index f179cab0d..6377f3783 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/iceberg/IcebergTable.java
@@ -27,7 +27,7 @@ import org.apache.amoro.table.BasicUnkeyedTable;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.iceberg.Snapshot;
 import org.apache.iceberg.Table;
 
@@ -55,7 +55,7 @@ public class IcebergTable implements AmoroTable<UnkeyedTable> {
     UnkeyedTable wrapped =
         new BasicUnkeyedTable(
             identifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 icebergTable, icebergTable.location(), io, metaStore.getConfiguration()),
             io,
             catalogProperties) {
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedCatalog.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedHiveCatalogFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedHiveCatalogFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedHiveCatalogFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedHiveCatalogFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
similarity index 94%
rename from amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
index bebfc0e58..b8b0d4ffb 100644
--- a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedIcebergCatalogFactory.java
@@ -25,7 +25,7 @@ import org.apache.amoro.mixed.CatalogLoader;
 import org.apache.amoro.mixed.MixedFormatCatalog;
 import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 
 import java.util.Map;
 
@@ -50,7 +50,7 @@ public class MixedIcebergCatalogFactory implements FormatCatalogFactory {
   public Map<String, String> convertCatalogProperties(
       String catalogName, String metastoreType, Map<String, String> unifiedCatalogProperties) {
     Map<String, String> properties =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             catalogName, metastoreType, unifiedCatalogProperties);
     properties.put(CatalogMetaProperties.TABLE_FORMATS, format().name());
     return properties;
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedSnapshot.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedSnapshot.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedSnapshot.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedSnapshot.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/formats/mixed/MixedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/formats/mixed/MixedTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIO.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIO.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIO.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIO.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIOAdapter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIOAdapter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIOAdapter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIOAdapter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java
similarity index 94%
rename from amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java
index 2d8c44e07..5317596c9 100644
--- a/amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedFileIOs.java
@@ -21,7 +21,7 @@ package org.apache.amoro.io;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.iceberg.hadoop.HadoopFileIO;
 import org.apache.iceberg.io.FileIO;
 import org.apache.iceberg.util.PropertyUtil;
@@ -39,7 +39,7 @@ public class AuthenticatedFileIOs {
       TableMetaStore tableMetaStore,
       Map<String, String> catalogProperties) {
     tableProperties =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(tableProperties, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(tableProperties, catalogProperties);
     if (!CLOSE_TRASH
         && PropertyUtil.propertyAsBoolean(
             tableProperties,
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedHadoopFileIO.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedHadoopFileIO.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/AuthenticatedHadoopFileIO.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/AuthenticatedHadoopFileIO.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/BasicTableTrashManager.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/BasicTableTrashManager.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/BasicTableTrashManager.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/BasicTableTrashManager.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/CloseableIterableWrapper.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseableIterableWrapper.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/CloseableIterableWrapper.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseableIterableWrapper.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/CloseableIteratorWrapper.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseableIteratorWrapper.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/CloseableIteratorWrapper.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseableIteratorWrapper.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/CloseablePredicate.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseablePredicate.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/CloseablePredicate.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/CloseablePredicate.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/PathInfo.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/PathInfo.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/PathInfo.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/PathInfo.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/RecoverableHadoopFileIO.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/RecoverableHadoopFileIO.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/RecoverableHadoopFileIO.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/RecoverableHadoopFileIO.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/SupportFileRecycleOperations.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/SupportFileRecycleOperations.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/SupportFileRecycleOperations.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/SupportFileRecycleOperations.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/SupportsFileSystemOperations.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/SupportsFileSystemOperations.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/SupportsFileSystemOperations.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/SupportsFileSystemOperations.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/TableTrashManager.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/TableTrashManager.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/TableTrashManager.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/TableTrashManager.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/TableTrashManagers.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/TableTrashManagers.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/TableTrashManagers.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/TableTrashManagers.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/AbstractKeyedDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/AbstractKeyedDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/AbstractKeyedDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/AbstractKeyedDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/AbstractUnkeyedDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/AbstractUnkeyedDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/AbstractUnkeyedDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/AbstractUnkeyedDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/BaseIcebergPosDeleteReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/BaseIcebergPosDeleteReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/BaseIcebergPosDeleteReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/BaseIcebergPosDeleteReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/CombinedDeleteFilter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/CombinedDeleteFilter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/CombinedDeleteFilter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/CombinedDeleteFilter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/DataReaderCommon.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/DataReaderCommon.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/DataReaderCommon.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/DataReaderCommon.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/DeleteFilter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/DeleteFilter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/DeleteFilter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/DeleteFilter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/Deletes.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/Deletes.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/Deletes.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/Deletes.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/GenericCombinedIcebergDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericCombinedIcebergDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/GenericCombinedIcebergDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericCombinedIcebergDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/GenericKeyedDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericKeyedDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/GenericKeyedDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericKeyedDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/GenericUnkeyedDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericUnkeyedDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/GenericUnkeyedDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/GenericUnkeyedDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/MixedDeleteFilter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/MixedDeleteFilter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/MixedDeleteFilter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/MixedDeleteFilter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/ParallelIcebergGenerics.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/ParallelIcebergGenerics.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/ParallelIcebergGenerics.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/ParallelIcebergGenerics.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/ParallelTableScanIterable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/ParallelTableScanIterable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/ParallelTableScanIterable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/ParallelTableScanIterable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/StructForDelete.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/StructForDelete.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/StructForDelete.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/StructForDelete.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/reader/StructLikeFunnel.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/StructLikeFunnel.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/reader/StructLikeFunnel.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/reader/StructLikeFunnel.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/BaseTaskWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/BaseTaskWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/BaseTaskWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/BaseTaskWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/ChangeTaskWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/ChangeTaskWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/ChangeTaskWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/ChangeTaskWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/CommonOutputFileFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/CommonOutputFileFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/CommonOutputFileFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/CommonOutputFileFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/GenericBaseTaskWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericBaseTaskWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/GenericBaseTaskWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericBaseTaskWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/GenericChangeTaskWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericChangeTaskWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/GenericChangeTaskWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericChangeTaskWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/GenericIcebergPartitionedFanoutWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericIcebergPartitionedFanoutWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/GenericIcebergPartitionedFanoutWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericIcebergPartitionedFanoutWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/GenericTaskWriters.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericTaskWriters.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/GenericTaskWriters.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/GenericTaskWriters.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/IcebergFanoutPosDeleteWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/IcebergFanoutPosDeleteWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/IcebergFanoutPosDeleteWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/IcebergFanoutPosDeleteWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/MixedTreeNodePosDeleteWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/MixedTreeNodePosDeleteWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/MixedTreeNodePosDeleteWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/MixedTreeNodePosDeleteWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/OutputFileFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/OutputFileFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/OutputFileFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/OutputFileFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/RecordWithAction.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/RecordWithAction.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/RecordWithAction.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/RecordWithAction.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/SetTreeNode.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/SetTreeNode.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/SetTreeNode.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/SetTreeNode.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/SortedPosDeleteWriter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/SortedPosDeleteWriter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/SortedPosDeleteWriter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/SortedPosDeleteWriter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/TaskWriterBuilder.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/TaskWriterBuilder.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/TaskWriterBuilder.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/TaskWriterBuilder.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/io/writer/TaskWriterKey.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/TaskWriterKey.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/io/writer/TaskWriterKey.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/io/writer/TaskWriterKey.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/Bytes.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/Bytes.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/Bytes.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/Bytes.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/Converter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/Converter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/Converter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/Converter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/FormatVersion.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/FormatVersion.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/FormatVersion.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/FormatVersion.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/JsonToLogDataConverters.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/JsonToLogDataConverters.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/JsonToLogDataConverters.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/JsonToLogDataConverters.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/LogData.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogData.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/LogData.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogData.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/LogDataJsonDeserialization.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataJsonDeserialization.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/LogDataJsonDeserialization.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataJsonDeserialization.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/LogDataJsonSerialization.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataJsonSerialization.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/LogDataJsonSerialization.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataJsonSerialization.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/LogDataToJsonConverters.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataToJsonConverters.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/LogDataToJsonConverters.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/LogDataToJsonConverters.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/MessageBytes.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/MessageBytes.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/MessageBytes.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/MessageBytes.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/TimeFormats.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/TimeFormats.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/TimeFormats.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/TimeFormats.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/data/LogArrayData.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/data/LogArrayData.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/data/LogArrayData.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/data/LogArrayData.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/log/data/LogMapData.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/log/data/LogMapData.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/log/data/LogMapData.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/log/data/LogMapData.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java
similarity index 98%
rename from amoro-core/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java
index 7e9ce4f39..033eb2e16 100644
--- a/amoro-core/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/BasicMixedIcebergCatalog.java
@@ -35,7 +35,7 @@ import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
 import org.apache.amoro.table.blocker.BasicTableBlockerManager;
 import org.apache.amoro.table.blocker.TableBlockerManager;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.amoro.utils.TablePropertyUtil;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.iceberg.PartitionSpec;
@@ -80,7 +80,7 @@ public class BasicMixedIcebergCatalog implements MixedFormatCatalog {
         buildIcebergCatalog(name, properties, metaStore.getConfiguration());
     this.name = name;
     this.tableMetaStore = metaStore;
-    this.icebergCatalog = MixedCatalogUtil.buildCacheCatalog(catalog, properties);
+    this.icebergCatalog = MixedFormatCatalogUtil.buildCacheCatalog(catalog, properties);
     if (catalog instanceof SupportsNamespaces) {
       this.asNamespaceCatalog = (SupportsNamespaces) catalog;
     }
diff --git a/amoro-core/src/main/java/org/apache/amoro/mixed/CatalogLoader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
similarity index 95%
rename from amoro-core/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
index aeaebc25a..2b534937a 100644
--- a/amoro-core/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/CatalogLoader.java
@@ -33,7 +33,7 @@ import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.shade.thrift.org.apache.thrift.TException;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.iceberg.common.DynConstructors;
 
 import java.util.List;
@@ -82,7 +82,8 @@ public class CatalogLoader {
    * @return class name for catalog
    */
   private static String catalogImpl(String metastoreType, Map<String, String> catalogProperties) {
-    Set<TableFormat> tableFormats = MixedCatalogUtil.tableFormats(metastoreType, catalogProperties);
+    Set<TableFormat> tableFormats =
+        MixedFormatCatalogUtil.tableFormats(metastoreType, catalogProperties);
     Preconditions.checkArgument(
         tableFormats.size() == 1, "Catalog support only one table format now.");
     TableFormat tableFormat = tableFormats.iterator().next();
@@ -171,12 +172,12 @@ public class CatalogLoader {
       CatalogMeta catalogMeta = client.getCatalog(catalogName);
       String type = catalogMeta.getCatalogType();
       catalogMeta.putToCatalogProperties(CatalogMetaProperties.AMS_URI, metaStoreUrl);
-      MixedCatalogUtil.mergeCatalogProperties(catalogMeta, properties);
+      MixedFormatCatalogUtil.mergeCatalogProperties(catalogMeta, properties);
       return createCatalog(
           catalogName,
           type,
           catalogMeta.getCatalogProperties(),
-          MixedCatalogUtil.buildMetaStore(catalogMeta));
+          MixedFormatCatalogUtil.buildMetaStore(catalogMeta));
     } catch (NoSuchObjectException e1) {
       throw new IllegalArgumentException("catalog not found, please check catalog name", e1);
     } catch (Exception e) {
@@ -200,7 +201,7 @@ public class CatalogLoader {
       TableMetaStore metaStore) {
     String catalogImpl = catalogImpl(metastoreType, properties);
     properties =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             catalogName, metastoreType, properties);
     MixedFormatCatalog catalog = buildCatalog(catalogImpl);
     catalog.initialize(catalogName, properties, metaStore);
@@ -215,7 +216,7 @@ public class CatalogLoader {
       Map<String, String> properties,
       TableMetaStore metaStore) {
     properties =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             catalogName, metastoreType, properties);
     MixedFormatCatalog catalog = buildCatalog(catalogImpl);
     catalog.initialize(catalogName, properties, metaStore);
diff --git a/amoro-core/src/main/java/org/apache/amoro/mixed/InternalMixedIcebergCatalog.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/InternalMixedIcebergCatalog.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/mixed/InternalMixedIcebergCatalog.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/InternalMixedIcebergCatalog.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/mixed/MixedFormatCatalog.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/MixedFormatCatalog.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/mixed/MixedFormatCatalog.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/MixedFormatCatalog.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/mixed/MixedTables.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/MixedTables.java
similarity index 98%
rename from amoro-core/src/main/java/org/apache/amoro/mixed/MixedTables.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/MixedTables.java
index 10750cbe2..6850d8797 100644
--- a/amoro-core/src/main/java/org/apache/amoro/mixed/MixedTables.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/mixed/MixedTables.java
@@ -31,7 +31,7 @@ import org.apache.amoro.table.MixedTable;
 import org.apache.amoro.table.PrimaryKeySpec;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.amoro.utils.TablePropertyUtil;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
@@ -272,7 +272,7 @@ public class MixedTables {
   }
 
   private Table useMixedTableOperation(Table table, AuthenticatedFileIO io) {
-    return MixedCatalogUtil.useMixedTableOperations(
+    return MixedFormatCatalogUtil.useMixedTableOperations(
         table, table.location(), io, tableMetaStore.getConfiguration());
   }
 }
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/CreateTableTransaction.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/CreateTableTransaction.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/CreateTableTransaction.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/CreateTableTransaction.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/KeyedPartitionRewrite.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/KeyedPartitionRewrite.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/KeyedPartitionRewrite.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/KeyedPartitionRewrite.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/KeyedSchemaUpdate.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/KeyedSchemaUpdate.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/KeyedSchemaUpdate.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/KeyedSchemaUpdate.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedAppendFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedAppendFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedAppendFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedAppendFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedDeleteFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedDeleteFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedDeleteFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedDeleteFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedHadoopTableOperations.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedHadoopTableOperations.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedHadoopTableOperations.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedHadoopTableOperations.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedOverwriteFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedOverwriteFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedOverwriteFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedOverwriteFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedReplacePartitions.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedReplacePartitions.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedReplacePartitions.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedReplacePartitions.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedRewriteFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedRewriteFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedRewriteFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedRewriteFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedRowDelta.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedRowDelta.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedRowDelta.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedRowDelta.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedTableOperations.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedTableOperations.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedTableOperations.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedTableOperations.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedTransaction.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedTransaction.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedTransaction.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedTransaction.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/MixedUpdate.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedUpdate.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/MixedUpdate.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/MixedUpdate.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/OverwriteBaseFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/OverwriteBaseFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/OverwriteBaseFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/OverwriteBaseFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/PartitionPropertiesUpdate.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/PartitionPropertiesUpdate.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/PartitionPropertiesUpdate.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/PartitionPropertiesUpdate.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/PartitionTransactionOperation.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/PartitionTransactionOperation.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/PartitionTransactionOperation.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/PartitionTransactionOperation.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/RewritePartitions.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/RewritePartitions.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/RewritePartitions.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/RewritePartitions.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/SnapshotSummary.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/SnapshotSummary.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/SnapshotSummary.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/SnapshotSummary.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/UpdateKeyedTableProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/UpdateKeyedTableProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/UpdateKeyedTableProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/UpdateKeyedTableProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/op/UpdatePartitionProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/op/UpdatePartitionProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/op/UpdatePartitionProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/op/UpdatePartitionProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/AbstractRewriteFilesExecutor.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/AbstractRewriteFilesExecutor.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/AbstractRewriteFilesExecutor.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/AbstractRewriteFilesExecutor.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/BaseOptimizingInput.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/BaseOptimizingInput.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/BaseOptimizingInput.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/BaseOptimizingInput.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutor.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutor.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutor.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutor.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutorFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutorFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutorFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/IcebergRewriteExecutorFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingCommitterFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingCommitterFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingCommitterFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingCommitterFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingDataReader.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingDataReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingDataReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingDataReader.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingExecutor.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingExecutor.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingExecutor.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingExecutor.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingExecutorFactory.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingExecutorFactory.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingExecutorFactory.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingExecutorFactory.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingInputProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingInputProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingInputProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingInputProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingTaskSummary.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingTaskSummary.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/OptimizingTaskSummary.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/OptimizingTaskSummary.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/RewriteFilesInput.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/RewriteFilesInput.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/RewriteFilesInput.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/RewriteFilesInput.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/RewriteFilesOutput.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/RewriteFilesOutput.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/RewriteFilesOutput.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/RewriteFilesOutput.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/optimizing/TableOptimizing.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/TableOptimizing.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/optimizing/TableOptimizing.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/optimizing/TableOptimizing.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/properties/HiveTableProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/properties/HiveTableProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/properties/HiveTableProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/properties/HiveTableProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/properties/MetaTableProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/properties/MetaTableProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/properties/MetaTableProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/properties/MetaTableProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/BaseCombinedScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BaseCombinedScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/BaseCombinedScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BaseCombinedScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/BasicKeyedTableScan.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BasicKeyedTableScan.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/BasicKeyedTableScan.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BasicKeyedTableScan.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/BasicMixedFileScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BasicMixedFileScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/BasicMixedFileScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/BasicMixedFileScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/ChangeTableIncrementalScan.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/ChangeTableIncrementalScan.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/ChangeTableIncrementalScan.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/ChangeTableIncrementalScan.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/CombinedIcebergScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/CombinedIcebergScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/CombinedIcebergScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/CombinedIcebergScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/CombinedScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/CombinedScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/CombinedScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/CombinedScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/KeyedTableScan.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/KeyedTableScan.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/KeyedTableScan.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/KeyedTableScan.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/KeyedTableScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/KeyedTableScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/KeyedTableScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/KeyedTableScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/MixedFileScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/MixedFileScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/MixedFileScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/MixedFileScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/NodeFileScanTask.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/NodeFileScanTask.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/NodeFileScanTask.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/NodeFileScanTask.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/TableEntriesScan.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/TableEntriesScan.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/TableEntriesScan.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/TableEntriesScan.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/expressions/BasicPartitionEvaluator.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/expressions/BasicPartitionEvaluator.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/expressions/BasicPartitionEvaluator.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/expressions/BasicPartitionEvaluator.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/scan/expressions/RewriteNot.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/scan/expressions/RewriteNot.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/scan/expressions/RewriteNot.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/scan/expressions/RewriteNot.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/BaseLocationKind.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BaseLocationKind.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/BaseLocationKind.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/BaseLocationKind.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/BaseTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BaseTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/BaseTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/BaseTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/BasicKeyedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicKeyedTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/BasicKeyedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicKeyedTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/BasicTableBuilder.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicTableBuilder.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/BasicTableBuilder.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicTableBuilder.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java
similarity index 98%
rename from amoro-core/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java
index 46bfebe88..d5f6f878d 100644
--- a/amoro-core/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/BasicUnkeyedTable.java
@@ -29,7 +29,7 @@ import org.apache.amoro.op.MixedRowDelta;
 import org.apache.amoro.op.MixedTransaction;
 import org.apache.amoro.op.PartitionPropertiesUpdate;
 import org.apache.amoro.op.UpdatePartitionProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.amoro.utils.TablePropertyUtil;
 import org.apache.iceberg.AppendFiles;
 import org.apache.iceberg.DeleteFiles;
@@ -160,7 +160,7 @@ public class BasicUnkeyedTable implements UnkeyedTable, HasTableOperations {
     if (catalogProperties == null) {
       return icebergTable.properties();
     } else {
-      return MixedCatalogUtil.mergeCatalogPropertiesToTable(
+      return MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(
           icebergTable.properties(), catalogProperties);
     }
   }
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/ChangeLocationKind.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/ChangeLocationKind.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/ChangeLocationKind.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/ChangeLocationKind.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/ChangeTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/ChangeTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/ChangeTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/ChangeTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/DistributionHashMode.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/DistributionHashMode.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/DistributionHashMode.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/DistributionHashMode.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/KeyedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/KeyedTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/KeyedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/KeyedTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/LocationKind.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/LocationKind.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/LocationKind.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/LocationKind.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/MetadataColumns.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/MetadataColumns.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/MetadataColumns.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/MetadataColumns.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/MixedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/MixedTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/MixedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/MixedTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/PrimaryKeySpec.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/PrimaryKeySpec.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/PrimaryKeySpec.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/PrimaryKeySpec.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/TableBuilder.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/TableBuilder.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/TableBuilder.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/TableBuilder.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/TableProperties.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/TableProperties.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/TableProperties.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/TableProperties.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/UnkeyedTable.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/UnkeyedTable.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/UnkeyedTable.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/UnkeyedTable.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/WatermarkGenerator.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/WatermarkGenerator.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/WatermarkGenerator.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/WatermarkGenerator.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/WriteOperationKind.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/WriteOperationKind.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/WriteOperationKind.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/WriteOperationKind.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/blocker/BasicTableBlockerManager.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/BasicTableBlockerManager.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/blocker/BasicTableBlockerManager.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/BasicTableBlockerManager.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/blocker/Blocker.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/Blocker.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/blocker/Blocker.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/Blocker.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/blocker/RenewableBlocker.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/RenewableBlocker.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/blocker/RenewableBlocker.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/RenewableBlocker.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/table/blocker/TableBlockerManager.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/TableBlockerManager.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/table/blocker/TableBlockerManager.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/table/blocker/TableBlockerManager.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/CompatiblePropertyUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/CompatiblePropertyUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/CompatiblePropertyUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/CompatiblePropertyUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/ContentFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ContentFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/ContentFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ContentFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/ConvertStructUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ConvertStructUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/ConvertStructUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ConvertStructUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/ExpressionUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ExpressionUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/ExpressionUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ExpressionUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/FileScanTaskUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/FileScanTaskUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/FileScanTaskUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/FileScanTaskUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/IcebergInMemoryLockManager.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/IcebergInMemoryLockManager.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/IcebergInMemoryLockManager.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/IcebergInMemoryLockManager.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/ManifestEntryFields.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ManifestEntryFields.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/ManifestEntryFields.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/ManifestEntryFields.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/MixedDataFiles.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedDataFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/MixedDataFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedDataFiles.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/MixedCatalogUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
similarity index 99%
rename from amoro-core/src/main/java/org/apache/amoro/utils/MixedCatalogUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
index dec833d45..ba3a5e2e1 100644
--- a/amoro-core/src/main/java/org/apache/amoro/utils/MixedCatalogUtil.java
+++ b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedFormatCatalogUtil.java
@@ -52,9 +52,9 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-public class MixedCatalogUtil {
+public class MixedFormatCatalogUtil {
 
-  private static final Logger LOG = LoggerFactory.getLogger(MixedCatalogUtil.class);
+  private static final Logger LOG = LoggerFactory.getLogger(MixedFormatCatalogUtil.class);
 
   /** Return table format set catalog supported. */
   public static Set<TableFormat> tableFormats(CatalogMeta meta) {
@@ -142,7 +142,7 @@ public class MixedCatalogUtil {
     if (catalogMeta.getStorageConfigs() != null) {
       Map<String, String> storageConfigs = catalogMeta.getStorageConfigs();
       if (CatalogMetaProperties.STORAGE_CONFIGS_VALUE_TYPE_HADOOP.equalsIgnoreCase(
-          MixedCatalogUtil.getCompatibleStorageType(storageConfigs))) {
+          MixedFormatCatalogUtil.getCompatibleStorageType(storageConfigs))) {
         String coreSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_CORE_SITE);
         String hdfsSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HDFS_SITE);
         String hiveSite = storageConfigs.get(CatalogMetaProperties.STORAGE_CONFIGS_KEY_HIVE_SITE);
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/MixedTableUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedTableUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/MixedTableUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/MixedTableUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/NodeFilter.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/NodeFilter.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/NodeFilter.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/NodeFilter.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/SchemaUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/SchemaUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/SchemaUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/SchemaUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/SerializationUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/SerializationUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/SerializationUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/SerializationUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/StatisticsFileUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/StatisticsFileUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/StatisticsFileUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/StatisticsFileUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/StructLikeSet.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/StructLikeSet.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/StructLikeSet.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/StructLikeSet.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/TableFileUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/TableFileUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/TableFileUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/TableFileUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/TablePropertyUtil.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/TablePropertyUtil.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/TablePropertyUtil.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/TablePropertyUtil.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/DefaultSizeEstimator.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/DefaultSizeEstimator.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/DefaultSizeEstimator.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/DefaultSizeEstimator.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/RocksDBBackend.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/RocksDBBackend.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/RocksDBBackend.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/RocksDBBackend.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/SimpleMap.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SimpleMap.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/SimpleMap.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SimpleMap.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/SimpleSpillableMap.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SimpleSpillableMap.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/SimpleSpillableMap.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SimpleSpillableMap.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/SizeEstimator.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SizeEstimator.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/SizeEstimator.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/SizeEstimator.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeBaseMap.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeBaseMap.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeBaseMap.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeBaseMap.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeCollections.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeCollections.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeCollections.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeCollections.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeMemoryMap.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeMemoryMap.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeMemoryMap.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeMemoryMap.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeSpillableMap.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeSpillableMap.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeSpillableMap.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeSpillableMap.java
diff --git a/amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeWrapperSizeEstimator.java b/amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeWrapperSizeEstimator.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/amoro/utils/map/StructLikeWrapperSizeEstimator.java
rename to amoro-iceberg-format/src/main/java/org/apache/amoro/utils/map/StructLikeWrapperSizeEstimator.java
diff --git a/amoro-core/src/main/java/org/apache/iceberg/IcebergFindFiles.java b/amoro-iceberg-format/src/main/java/org/apache/iceberg/IcebergFindFiles.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/iceberg/IcebergFindFiles.java
rename to amoro-iceberg-format/src/main/java/org/apache/iceberg/IcebergFindFiles.java
diff --git a/amoro-core/src/main/java/org/apache/iceberg/MixedChangeTableScan.java b/amoro-iceberg-format/src/main/java/org/apache/iceberg/MixedChangeTableScan.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/iceberg/MixedChangeTableScan.java
rename to amoro-iceberg-format/src/main/java/org/apache/iceberg/MixedChangeTableScan.java
diff --git a/amoro-core/src/main/java/org/apache/iceberg/data/PublicGenericReader.java b/amoro-iceberg-format/src/main/java/org/apache/iceberg/data/PublicGenericReader.java
similarity index 100%
rename from amoro-core/src/main/java/org/apache/iceberg/data/PublicGenericReader.java
rename to amoro-iceberg-format/src/main/java/org/apache/iceberg/data/PublicGenericReader.java
diff --git a/amoro-iceberg-format/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory b/amoro-iceberg-format/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory
new file mode 100644
index 000000000..a9aff439e
--- /dev/null
+++ b/amoro-iceberg-format/src/main/resources/META-INF/services/org.apache.amoro.FormatCatalogFactory
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#  *
+#     http://www.apache.org/licenses/LICENSE-2.0
+#  *
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.amoro.formats.iceberg.IcebergCatalogFactory
+org.apache.amoro.formats.mixed.MixedIcebergCatalogFactory
+org.apache.amoro.formats.mixed.MixedHiveCatalogFactory
\ No newline at end of file
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestStatisticsFileUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestStatisticsFileUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestStatisticsFileUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestStatisticsFileUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestTablePropertyUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestTablePropertyUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestTablePropertyUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestTablePropertyUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestUnkeyedExpressionUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestUnkeyedExpressionUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestUnkeyedExpressionUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestUnkeyedExpressionUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestWatermarkGenerator.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestWatermarkGenerator.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestWatermarkGenerator.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestWatermarkGenerator.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/map/TestRocksDBBackend.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestRocksDBBackend.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/map/TestRocksDBBackend.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestRocksDBBackend.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/map/TestSimpleSpillableMap.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestSimpleSpillableMap.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/map/TestSimpleSpillableMap.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestSimpleSpillableMap.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/map/TestSimpleSpilledMap.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestSimpleSpilledMap.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/map/TestSimpleSpilledMap.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestSimpleSpilledMap.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/map/TestStructLikeMap.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestStructLikeMap.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/map/TestStructLikeMap.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestStructLikeMap.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/map/TestStructLikeWrapperSizeEstimator.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestStructLikeWrapperSizeEstimator.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/map/TestStructLikeWrapperSizeEstimator.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/map/TestStructLikeWrapperSizeEstimator.java
diff --git a/amoro-core/src/test/java/org/apache/iceberg/TestIcebergFindFiles.java b/amoro-iceberg-format/src/test/java/org/apache/iceberg/TestIcebergFindFiles.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/iceberg/TestIcebergFindFiles.java
rename to amoro-iceberg-format/src/test/java/org/apache/iceberg/TestIcebergFindFiles.java
diff --git a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-format/pom.xml b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-format/pom.xml
index 6ffd471d1..9f714dfb7 100644
--- a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-format/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-format/pom.xml
@@ -37,7 +37,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.amoro</groupId>
-            <artifactId>amoro-core</artifactId>
+            <artifactId>amoro-iceberg-format</artifactId>
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
diff --git a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-iceberg-bridge/pom.xml b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-iceberg-bridge/pom.xml
index fc6f54923..586f9e426 100644
--- a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-iceberg-bridge/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common-iceberg-bridge/pom.xml
@@ -41,7 +41,7 @@
         <!--amoro-->
         <dependency>
             <groupId>org.apache.amoro</groupId>
-            <artifactId>amoro-core</artifactId>
+            <artifactId>amoro-iceberg-format</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>org.ow2.asm</groupId>
diff --git a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/pom.xml b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/pom.xml
index e26f576a0..81a995458 100644
--- a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/pom.xml
@@ -44,7 +44,7 @@
         <!--amoro-->
         <dependency>
             <groupId>org.apache.amoro</groupId>
-            <artifactId>amoro-core</artifactId>
+            <artifactId>amoro-iceberg-format</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>org.ow2.asm</groupId>
@@ -318,6 +318,14 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-mixed-format-hive</artifactId>
diff --git a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/factories/FlinkUnifiedCatalogFactory.java b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/factories/FlinkUnifiedCatalogFactory.java
index 97c964bc5..8c7fc50ff 100644
--- a/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/factories/FlinkUnifiedCatalogFactory.java
+++ b/amoro-mixed-format/amoro-mixed-format-flink/amoro-mixed-format-flink-common/src/main/java/org/apache/amoro/flink/catalog/factories/FlinkUnifiedCatalogFactory.java
@@ -30,7 +30,7 @@ import org.apache.amoro.client.AmsThriftUrl;
 import org.apache.amoro.flink.catalog.FlinkUnifiedCatalog;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.flink.configuration.ConfigOption;
 import org.apache.flink.table.catalog.Catalog;
 import org.apache.flink.table.factories.CatalogFactory;
@@ -86,7 +86,8 @@ public class FlinkUnifiedCatalogFactory implements CatalogFactory {
     Configuration hadoopConf = unifiedCatalog.authenticationContext().getConfiguration();
 
     Set<TableFormat> tableFormats =
-        MixedCatalogUtil.tableFormats(unifiedCatalog.metastoreType(), unifiedCatalog.properties());
+        MixedFormatCatalogUtil.tableFormats(
+            unifiedCatalog.metastoreType(), unifiedCatalog.properties());
     validate(tableFormats);
 
     return new FlinkUnifiedCatalog(
diff --git a/amoro-mixed-format/amoro-mixed-format-hive/pom.xml b/amoro-mixed-format/amoro-mixed-format-hive/pom.xml
index 79efa4d07..a7b9c0d86 100644
--- a/amoro-mixed-format/amoro-mixed-format-hive/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-hive/pom.xml
@@ -34,7 +34,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.amoro</groupId>
-            <artifactId>amoro-core</artifactId>
+            <artifactId>amoro-iceberg-format</artifactId>
         </dependency>
 
         <dependency>
@@ -101,6 +101,14 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-ams-api</artifactId>
diff --git a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveCatalog.java b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveCatalog.java
index dd1e65c6f..5b04e54b6 100644
--- a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveCatalog.java
+++ b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveCatalog.java
@@ -56,7 +56,7 @@ import org.apache.amoro.table.blocker.BasicTableBlockerManager;
 import org.apache.amoro.table.blocker.TableBlockerManager;
 import org.apache.amoro.utils.CompatiblePropertyUtil;
 import org.apache.amoro.utils.ConvertStructUtil;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
@@ -425,7 +425,7 @@ public class MixedHiveCatalog implements MixedFormatCatalog {
 
     protected void checkProperties() {
       Map<String, String> mergedProperties =
-          MixedCatalogUtil.mergeCatalogPropertiesToTable(properties, catalogProperties);
+          MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(properties, catalogProperties);
       boolean enableStream =
           CompatiblePropertyUtil.propertyAsBoolean(
               mergedProperties,
diff --git a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveTables.java b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveTables.java
index 26f4e3abc..d4ac4a8c9 100644
--- a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveTables.java
+++ b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/catalog/MixedHiveTables.java
@@ -39,7 +39,7 @@ import org.apache.amoro.table.PrimaryKeySpec;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.iceberg.FileFormat;
@@ -116,7 +116,7 @@ public class MixedHiveTables {
     UnkeyedHiveTable baseTable =
         new KeyedHiveTable.HiveBaseInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 baseIcebergTable, baseLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             tableLocation,
@@ -128,7 +128,7 @@ public class MixedHiveTables {
     ChangeTable changeTable =
         new KeyedHiveTable.HiveChangeInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 changeIcebergTable, changeLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -166,7 +166,7 @@ public class MixedHiveTables {
     Table table = tableMetaStore.doAs(() -> tables.load(baseLocation));
     return new UnkeyedHiveTable(
         tableIdentifier,
-        MixedCatalogUtil.useMixedTableOperations(
+        MixedFormatCatalogUtil.useMixedTableOperations(
             table, baseLocation, fileIO, tableMetaStore.getConfiguration()),
         fileIO,
         tableLocation,
@@ -219,7 +219,7 @@ public class MixedHiveTables {
     UnkeyedHiveTable baseTable =
         new KeyedHiveTable.HiveBaseInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 baseIcebergTable, baseLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             tableLocation,
@@ -247,7 +247,7 @@ public class MixedHiveTables {
     ChangeTable changeTable =
         new KeyedHiveTable.HiveChangeInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 changeIcebergTable, changeLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -366,7 +366,7 @@ public class MixedHiveTables {
             catalogProperties);
     return new UnkeyedHiveTable(
         tableIdentifier,
-        MixedCatalogUtil.useMixedTableOperations(
+        MixedFormatCatalogUtil.useMixedTableOperations(
             table, baseLocation, fileIO, tableMetaStore.getConfiguration()),
         fileIO,
         tableLocation,
diff --git a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/utils/HivePartitionUtil.java b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/utils/HivePartitionUtil.java
index 3292787cf..73d0a9081 100644
--- a/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/utils/HivePartitionUtil.java
+++ b/amoro-mixed-format/amoro-mixed-format-hive/src/main/java/org/apache/amoro/hive/utils/HivePartitionUtil.java
@@ -18,6 +18,7 @@
 
 package org.apache.amoro.hive.utils;
 
+import org.apache.amoro.client.ClientPool;
 import org.apache.amoro.hive.HMSClient;
 import org.apache.amoro.hive.HMSClientPool;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
@@ -29,7 +30,6 @@ import org.apache.hadoop.hive.metastore.api.Partition;
 import org.apache.hadoop.hive.metastore.api.PrincipalPrivilegeSet;
 import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
 import org.apache.hadoop.hive.metastore.api.Table;
-import org.apache.iceberg.ClientPool;
 import org.apache.iceberg.DataFile;
 import org.apache.iceberg.DataFiles;
 import org.apache.iceberg.PartitionSpec;
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
index 239948576..dbc65a73d 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-spark/amoro-mixed-format-spark-3-common/pom.xml
@@ -193,6 +193,13 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-mixed-format-hive</artifactId>
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml b/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
index 197d11a73..bcaab550b 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-spark/v3.2/amoro-mixed-format-spark-3.2/pom.xml
@@ -367,6 +367,13 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.hive</groupId>
diff --git a/amoro-mixed-format/amoro-mixed-format-spark/v3.3/amoro-mixed-format-spark-3.3/pom.xml b/amoro-mixed-format/amoro-mixed-format-spark/v3.3/amoro-mixed-format-spark-3.3/pom.xml
index 9c2bcecda..e096ffb07 100644
--- a/amoro-mixed-format/amoro-mixed-format-spark/v3.3/amoro-mixed-format-spark-3.3/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-spark/v3.3/amoro-mixed-format-spark-3.3/pom.xml
@@ -368,6 +368,13 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.hive</groupId>
diff --git a/amoro-mixed-format/amoro-mixed-format-trino/pom.xml b/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
index 599763a9b..ff6580ffa 100644
--- a/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
+++ b/amoro-mixed-format/amoro-mixed-format-trino/pom.xml
@@ -469,6 +469,14 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.amoro</groupId>
+            <artifactId>amoro-iceberg-format</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.amoro</groupId>
             <artifactId>amoro-mixed-format-hive</artifactId>
diff --git a/amoro-mixed-format/amoro-mixed-format-trino/src/main/java/org/apache/amoro/trino/DefaultMixedFormatCatalogFactory.java b/amoro-mixed-format/amoro-mixed-format-trino/src/main/java/org/apache/amoro/trino/DefaultMixedFormatCatalogFactory.java
index 4a909fe82..360540ba1 100644
--- a/amoro-mixed-format/amoro-mixed-format-trino/src/main/java/org/apache/amoro/trino/DefaultMixedFormatCatalogFactory.java
+++ b/amoro-mixed-format/amoro-mixed-format-trino/src/main/java/org/apache/amoro/trino/DefaultMixedFormatCatalogFactory.java
@@ -23,7 +23,7 @@ import org.apache.amoro.api.CatalogMeta;
 import org.apache.amoro.mixed.CatalogLoader;
 import org.apache.amoro.mixed.MixedFormatCatalog;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 
 import javax.inject.Inject;
 
@@ -65,7 +65,7 @@ public class DefaultMixedFormatCatalogFactory implements MixedFormatCatalogFacto
           try (ThreadContextClassLoader ignored =
               new ThreadContextClassLoader(this.getClass().getClassLoader())) {
             CatalogMeta meta = CatalogLoader.loadMeta(mixedFormatConfig.getCatalogUrl());
-            this.tableMetaStore = MixedCatalogUtil.buildMetaStore(meta);
+            this.tableMetaStore = CatalogUtil.buildMetaStore(meta);
           }
         }
       }
diff --git a/amoro-mixed-format/pom.xml b/amoro-mixed-format/pom.xml
index b992c1f15..333ed6d10 100644
--- a/amoro-mixed-format/pom.xml
+++ b/amoro-mixed-format/pom.xml
@@ -1,5 +1,4 @@
-
-
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one
   ~ or more contributor license agreements.  See the NOTICE file
diff --git a/pom.xml b/pom.xml
index 75285ff3d..b8cce93a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,7 @@
     <modules>
         <module>amoro-core</module>
         <module>amoro-ams</module>
+        <module>amoro-iceberg-format</module>
         <module>amoro-mixed-format</module>
     </modules>
 
@@ -240,6 +241,12 @@
                 <version>${project.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.apache.amoro</groupId>
+                <artifactId>amoro-iceberg-format</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.apache.amoro</groupId>
                 <artifactId>amoro-mixed-format-hive</artifactId>
@@ -511,6 +518,12 @@
                 <groupId>software.amazon.awssdk</groupId>
                 <artifactId>url-connection-client</artifactId>
                 <version>${awssdk.version}</version>
+	    </dependency>
+
+	    <dependency>
+                <groupId>software.amazon.awssdk</groupId>
+                <artifactId>s3-transfer-manager</artifactId>
+                <version>${awssdk.version}</version>
             </dependency>
 
             <dependency>


Test patch:
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/RestCatalogServiceTestBase.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/RestCatalogServiceTestBase.java
index 8f83f4ff9..f99c09d20 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/RestCatalogServiceTestBase.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/RestCatalogServiceTestBase.java
@@ -31,8 +31,7 @@ import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.PrimaryKeySpec;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
-import org.apache.iceberg.CatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.rest.RESTCatalog;
@@ -99,10 +98,10 @@ public abstract class RestCatalogServiceTestBase {
     clientProperties.putIfAbsent("warehouse", catalogName());
 
     CatalogMeta catalogMeta = serverCatalog.getMetadata();
-    TableMetaStore store = MixedCatalogUtil.buildMetaStore(catalogMeta);
+    TableMetaStore store = CatalogUtil.buildMetaStore(catalogMeta);
 
     return (RESTCatalog)
-        CatalogUtil.loadCatalog(
+        org.apache.iceberg.CatalogUtil.loadCatalog(
             "org.apache.iceberg.rest.RESTCatalog",
             "test",
             clientProperties,
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalMixedCatalogService.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalMixedCatalogService.java
index 4af369fb3..4514d7ed2 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalMixedCatalogService.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/TestInternalMixedCatalogService.java
@@ -35,7 +35,7 @@ import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.MixedTable;
 import org.apache.amoro.table.TableBuilder;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.amoro.utils.MixedTableUtil;
 import org.apache.iceberg.AppendFiles;
 import org.apache.iceberg.DataFile;
@@ -305,9 +305,7 @@ public class TestInternalMixedCatalogService extends RestCatalogServiceTestBase
 
       MixedFormatCatalog catalog = new BasicMixedCatalog();
       catalog.initialize(
-          meta.getCatalogName(),
-          meta.getCatalogProperties(),
-          MixedCatalogUtil.buildMetaStore(meta));
+          meta.getCatalogName(), meta.getCatalogProperties(), CatalogUtil.buildMetaStore(meta));
       this.historicalCatalog = catalog;
       this.historicalCatalog.createDatabase(database);
     }
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
index 6202ebfa3..263af1dad 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/optimizing/TestIcebergHadoopOptimizing.java
@@ -28,8 +28,7 @@ import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
-import org.apache.amoro.utils.MixedCatalogUtil;
-import org.apache.iceberg.CatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.iceberg.PartitionKey;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
@@ -433,9 +432,10 @@ public class TestIcebergHadoopOptimizing extends AbstractOptimizingTest {
       throw new IllegalStateException("unknown catalog");
     }
 
-    TableMetaStore tms = MixedCatalogUtil.buildMetaStore(serverCatalog.getMetadata());
+    TableMetaStore tms = CatalogUtil.buildMetaStore(serverCatalog.getMetadata());
     Catalog icebergCatalog =
-        CatalogUtil.loadCatalog(impl, catalog, properties, tms.getConfiguration());
+        org.apache.iceberg.CatalogUtil.loadCatalog(
+            impl, catalog, properties, tms.getConfiguration());
 
     Map<String, String> tableProperties = Maps.newHashMap();
     tableProperties.put(
diff --git a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/table/AMSTableTestBase.java b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/table/AMSTableTestBase.java
index 5d35bf383..eecffe8c4 100644
--- a/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/table/AMSTableTestBase.java
+++ b/amoro-ams/amoro-ams-server/src/test/java/org/apache/amoro/server/table/AMSTableTestBase.java
@@ -35,8 +35,8 @@ import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.server.catalog.InternalCatalog;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
 import org.apache.amoro.table.MixedTable;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.amoro.utils.ConvertStructUtil;
-import org.apache.amoro.utils.MixedCatalogUtil;
 import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
 import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.iceberg.catalog.TableIdentifier;
@@ -203,7 +203,7 @@ public class AMSTableTestBase extends TableServiceTestBase {
                 catalogMeta.getCatalogName(),
                 catalogMeta.getCatalogType(),
                 catalogMeta.getCatalogProperties(),
-                MixedCatalogUtil.buildMetaStore(catalogMeta));
+                CatalogUtil.buildMetaStore(catalogMeta));
     catalog
         .newTableBuilder(tableTestHelper.id(), tableTestHelper.tableSchema())
         .withPartitionSpec(tableTestHelper.partitionSpec())
@@ -218,7 +218,7 @@ public class AMSTableTestBase extends TableServiceTestBase {
             catalogMeta.getCatalogName(),
             catalogMeta.getCatalogType(),
             catalogMeta.getCatalogProperties(),
-            MixedCatalogUtil.buildMetaStore(catalogMeta));
+            CatalogUtil.buildMetaStore(catalogMeta));
     catalog
         .newTableBuilder(tableTestHelper.id(), tableTestHelper.tableSchema())
         .withPartitionSpec(tableTestHelper.partitionSpec())
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/PaimonHadoopCatalogTestHelper.java b/amoro-core/src/test/java/org/apache/amoro/formats/PaimonHadoopCatalogTestHelper.java
index 690cdb39b..11cf0c9d3 100644
--- a/amoro-core/src/test/java/org/apache/amoro/formats/PaimonHadoopCatalogTestHelper.java
+++ b/amoro-core/src/test/java/org/apache/amoro/formats/PaimonHadoopCatalogTestHelper.java
@@ -23,7 +23,7 @@ import org.apache.amoro.AmoroCatalog;
 import org.apache.amoro.TableFormat;
 import org.apache.amoro.formats.paimon.PaimonCatalogFactory;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.paimon.catalog.Catalog;
 import org.apache.paimon.catalog.Identifier;
@@ -63,7 +63,7 @@ public class PaimonHadoopCatalogTestHelper extends AbstractFormatCatalogTestHelp
   @Override
   public AmoroCatalog amoroCatalog() {
     PaimonCatalogFactory paimonCatalogFactory = new PaimonCatalogFactory();
-    TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(getCatalogMeta());
+    TableMetaStore metaStore = CatalogUtil.buildMetaStore(getCatalogMeta());
     Map<String, String> paimonCatalogProperties =
         paimonCatalogFactory.convertCatalogProperties(
             catalogName, getMetastoreType(), getCatalogMeta().getCatalogProperties());
diff --git a/amoro-core/src/test/java/org/apache/amoro/BasicTableTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/BasicTableTestHelper.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/BasicTableTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/BasicTableTestHelper.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/DataFileTestHelpers.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/DataFileTestHelpers.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/DataFileTestHelpers.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/DataFileTestHelpers.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/TableTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/TableTestHelper.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/TableTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/TableTestHelper.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/TestTreeNode.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/TestTreeNode.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/TestTreeNode.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/TestTreeNode.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/TestUnifiedCatalog.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/TestUnifiedCatalog.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/TestUnifiedCatalog.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/TestUnifiedCatalog.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/TestedCatalogs.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/TestedCatalogs.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/TestedCatalogs.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/TestedCatalogs.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java
similarity index 96%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java
index baf8fac5c..599cfffd3 100644
--- a/amoro-core/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicCatalogTestHelper.java
@@ -25,7 +25,7 @@ import org.apache.amoro.api.CatalogMeta;
 import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.shade.guava32.com.google.common.base.Preconditions;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.iceberg.CatalogUtil;
 import org.apache.iceberg.catalog.Catalog;
@@ -100,7 +100,7 @@ public class BasicCatalogTestHelper implements CatalogTestHelper {
           "Cannot build mixed-tables for table format:" + tableFormat);
     }
     return new MixedTables(
-        catalogMeta.getCatalogProperties(), MixedCatalogUtil.buildMetaStore(catalogMeta));
+        catalogMeta.getCatalogProperties(), MixedFormatCatalogUtil.buildMetaStore(catalogMeta));
   }
 
   @Override
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java
similarity index 98%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java
index 23037d0d0..9717db05f 100644
--- a/amoro-core/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/BasicMixedCatalog.java
@@ -49,7 +49,7 @@ import org.apache.amoro.table.blocker.BasicTableBlockerManager;
 import org.apache.amoro.table.blocker.TableBlockerManager;
 import org.apache.amoro.utils.CompatiblePropertyUtil;
 import org.apache.amoro.utils.ConvertStructUtil;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.fs.Path;
 import org.apache.iceberg.PartitionSpec;
@@ -214,7 +214,7 @@ public class BasicMixedCatalog implements MixedFormatCatalog {
   protected TableMeta getMixedTableMeta(TableIdentifier identifier) {
     TableMeta tableMeta;
     try {
-      tableMeta = getClient().getTable(MixedCatalogUtil.amsTaleId(identifier));
+      tableMeta = getClient().getTable(MixedFormatCatalogUtil.amsTaleId(identifier));
       return tableMeta;
     } catch (NoSuchObjectException e) {
       throw new NoSuchTableException(e, "load table failed %s.", identifier);
@@ -363,7 +363,7 @@ public class BasicMixedCatalog implements MixedFormatCatalog {
 
     protected void checkProperties() {
       Map<String, String> mergedProperties =
-          MixedCatalogUtil.mergeCatalogPropertiesToTable(properties, catalogProperties);
+          MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(properties, catalogProperties);
       boolean enableStream =
           CompatiblePropertyUtil.propertyAsBoolean(
               mergedProperties,
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/CatalogTestBase.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/CatalogTestBase.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/CatalogTestBase.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/CatalogTestBase.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java
similarity index 93%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java
index 49b882c27..91f6f7c20 100644
--- a/amoro-core/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/CatalogTestHelper.java
@@ -19,7 +19,6 @@
 package org.apache.amoro.catalog;
 
 import org.apache.amoro.TableFormat;
-import org.apache.amoro.TableTestHelper;
 import org.apache.amoro.UnifiedCatalog;
 import org.apache.amoro.api.CatalogMeta;
 import org.apache.amoro.properties.CatalogMetaProperties;
@@ -27,7 +26,7 @@ import org.apache.iceberg.catalog.Catalog;
 
 public interface CatalogTestHelper {
 
-  String TEST_CATALOG_NAME = TableTestHelper.TEST_CATALOG_NAME;
+  String TEST_CATALOG_NAME = "test_catalog";
 
   String metastoreType();
 
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/MixedTables.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/MixedTables.java
similarity index 96%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/MixedTables.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/MixedTables.java
index 81f65d03e..689cfad72 100644
--- a/amoro-core/src/test/java/org/apache/amoro/catalog/MixedTables.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/MixedTables.java
@@ -36,7 +36,7 @@ import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.TableProperties;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
@@ -98,7 +98,7 @@ public class MixedTables {
     BaseTable baseTable =
         new BasicKeyedTable.BaseInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 baseIcebergTable, baseLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -107,7 +107,7 @@ public class MixedTables {
     ChangeTable changeTable =
         new BasicKeyedTable.ChangeInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 changeIcebergTable, changeLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -148,7 +148,7 @@ public class MixedTables {
             catalogProperties);
     return new BasicUnkeyedTable(
         tableIdentifier,
-        MixedCatalogUtil.useMixedTableOperations(
+        MixedFormatCatalogUtil.useMixedTableOperations(
             table, baseLocation, fileIO, tableMetaStore.getConfiguration()),
         fileIO,
         catalogProperties);
@@ -197,7 +197,7 @@ public class MixedTables {
     BaseTable baseTable =
         new BasicKeyedTable.BaseInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 baseIcebergTable, baseLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -215,7 +215,7 @@ public class MixedTables {
     ChangeTable changeTable =
         new BasicKeyedTable.ChangeInternalTable(
             tableIdentifier,
-            MixedCatalogUtil.useMixedTableOperations(
+            MixedFormatCatalogUtil.useMixedTableOperations(
                 changeIcebergTable, changeLocation, fileIO, tableMetaStore.getConfiguration()),
             fileIO,
             catalogProperties);
@@ -261,7 +261,7 @@ public class MixedTables {
             catalogProperties);
     return new BasicUnkeyedTable(
         tableIdentifier,
-        MixedCatalogUtil.useMixedTableOperations(
+        MixedFormatCatalogUtil.useMixedTableOperations(
             table, baseLocation, fileIO, tableMetaStore.getConfiguration()),
         fileIO,
         catalogProperties);
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/TableTestBase.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TableTestBase.java
similarity index 96%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/TableTestBase.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TableTestBase.java
index 5b61e34ac..2dc49c9d9 100644
--- a/amoro-core/src/test/java/org/apache/amoro/catalog/TableTestBase.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TableTestBase.java
@@ -23,7 +23,7 @@ import org.apache.amoro.table.MixedTable;
 import org.apache.amoro.table.TableBuilder;
 import org.apache.amoro.table.TableMetaStore;
 import org.apache.amoro.table.UnkeyedTable;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.amoro.utils.MixedTableUtil;
 import org.junit.After;
 import org.junit.Before;
@@ -41,7 +41,7 @@ public abstract class TableTestBase extends CatalogTestBase {
 
   @Before
   public void setupTable() {
-    this.tableMetaStore = MixedCatalogUtil.buildMetaStore(getCatalogMeta());
+    this.tableMetaStore = MixedFormatCatalogUtil.buildMetaStore(getCatalogMeta());
 
     getUnifiedCatalog().createDatabase(TableTestHelper.TEST_DB_NAME);
     switch (getTestFormat()) {
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/TestCatalogLoader.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TestCatalogLoader.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/TestCatalogLoader.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TestCatalogLoader.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/catalog/TestMixedCatalog.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TestMixedCatalog.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/catalog/TestMixedCatalog.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/catalog/TestMixedCatalog.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/data/TestDefaultKeyedFile.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/data/TestDefaultKeyedFile.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/data/TestDefaultKeyedFile.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/data/TestDefaultKeyedFile.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/data/TestUpsertPushDown.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/data/TestUpsertPushDown.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/data/TestUpsertPushDown.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/data/TestUpsertPushDown.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java
similarity index 94%
rename from amoro-core/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java
index 0fa2420cd..6fad3b3c7 100644
--- a/amoro-core/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/IcebergHadoopCatalogTestHelper.java
@@ -24,7 +24,7 @@ import org.apache.amoro.formats.iceberg.IcebergCatalogFactory;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
@@ -73,7 +73,7 @@ public class IcebergHadoopCatalogTestHelper extends AbstractFormatCatalogTestHel
   @Override
   public AmoroCatalog amoroCatalog() {
     IcebergCatalogFactory icebergCatalogFactory = new IcebergCatalogFactory();
-    TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(getCatalogMeta());
+    TableMetaStore metaStore = MixedFormatCatalogUtil.buildMetaStore(getCatalogMeta());
     Map<String, String> properties =
         icebergCatalogFactory.convertCatalogProperties(
             catalogName, getMetastoreType(), catalogProperties);
@@ -83,9 +83,9 @@ public class IcebergHadoopCatalogTestHelper extends AbstractFormatCatalogTestHel
   @Override
   public Catalog originalCatalog() {
     Map<String, String> props =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             catalogName, getMetastoreType(), catalogProperties);
-    TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(getCatalogMeta());
+    TableMetaStore metaStore = MixedFormatCatalogUtil.buildMetaStore(getCatalogMeta());
     return org.apache.iceberg.CatalogUtil.buildIcebergCatalog(
         catalogName, props, metaStore.getConfiguration());
   }
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java
similarity index 95%
rename from amoro-core/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java
index 67d2fa0f1..da7b00c9d 100644
--- a/amoro-core/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/MixedIcebergHadoopCatalogTestHelper.java
@@ -28,7 +28,7 @@ import org.apache.amoro.shade.guava32.com.google.common.collect.Lists;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Sets;
 import org.apache.amoro.table.TableIdentifier;
 import org.apache.amoro.table.TableMetaStore;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.MixedFormatCatalogUtil;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.types.Types;
@@ -63,7 +63,7 @@ public class MixedIcebergHadoopCatalogTestHelper
   @Override
   public AmoroCatalog amoroCatalog() {
     MixedIcebergCatalogFactory mixedIcebergCatalogFactory = new MixedIcebergCatalogFactory();
-    TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(getCatalogMeta());
+    TableMetaStore metaStore = MixedFormatCatalogUtil.buildMetaStore(getCatalogMeta());
     Map<String, String> properties =
         mixedIcebergCatalogFactory.convertCatalogProperties(
             catalogName, getMetastoreType(), catalogProperties);
@@ -74,7 +74,7 @@ public class MixedIcebergHadoopCatalogTestHelper
   @Override
   public MixedFormatCatalog originalCatalog() {
     CatalogMeta meta = getCatalogMeta();
-    TableMetaStore metaStore = MixedCatalogUtil.buildMetaStore(meta);
+    TableMetaStore metaStore = MixedFormatCatalogUtil.buildMetaStore(meta);
     return CatalogLoader.createCatalog(
         catalogName(), meta.getCatalogType(), meta.getCatalogProperties(), metaStore);
   }
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/TestIcebergAmoroCatalog.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/TestIcebergAmoroCatalog.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/formats/TestIcebergAmoroCatalog.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/formats/TestIcebergAmoroCatalog.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/formats/TestMixedIcebergFormatCatalog.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/formats/TestMixedIcebergFormatCatalog.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/formats/TestMixedIcebergFormatCatalog.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/formats/TestMixedIcebergFormatCatalog.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/IcebergDataTestHelpers.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/MixedDataTestHelpers.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/MixedDataTestHelpers.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/MixedDataTestHelpers.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/MixedDataTestHelpers.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TableDataTestBase.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TableDataTestBase.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TableDataTestBase.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TableDataTestBase.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestBasicTableTrashManager.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestBasicTableTrashManager.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestBasicTableTrashManager.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestBasicTableTrashManager.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestFileNameGenerator.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestFileNameGenerator.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestFileNameGenerator.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestFileNameGenerator.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestIcebergCombinedReader.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergCombinedReader.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestIcebergCombinedReader.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergCombinedReader.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestIcebergCombinedReaderVariousTypes.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergCombinedReaderVariousTypes.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestIcebergCombinedReaderVariousTypes.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergCombinedReaderVariousTypes.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestIcebergFanoutPosDeleteWriter.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergFanoutPosDeleteWriter.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestIcebergFanoutPosDeleteWriter.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestIcebergFanoutPosDeleteWriter.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestMixedTreeNodePosDeleteWriter.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestMixedTreeNodePosDeleteWriter.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestMixedTreeNodePosDeleteWriter.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestMixedTreeNodePosDeleteWriter.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestRecoverableAuthenticatedFileIO.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestRecoverableAuthenticatedFileIO.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestRecoverableAuthenticatedFileIO.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestRecoverableAuthenticatedFileIO.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestTableTrashManagers.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTableTrashManagers.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestTableTrashManagers.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTableTrashManagers.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestTaskReader.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTaskReader.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestTaskReader.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTaskReader.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/io/TestTaskWriter.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTaskWriter.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/io/TestTaskWriter.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/io/TestTaskWriter.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/log/FormatTestBase.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/log/FormatTestBase.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/log/FormatTestBase.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/log/FormatTestBase.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/log/TestLogDataJsonSerialization.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/log/TestLogDataJsonSerialization.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/log/TestLogDataJsonSerialization.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/log/TestLogDataJsonSerialization.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/op/TestOverwriteBaseFile.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestOverwriteBaseFile.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/op/TestOverwriteBaseFile.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestOverwriteBaseFile.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/op/TestRewritePartitions.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestRewritePartitions.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/op/TestRewritePartitions.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestRewritePartitions.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/op/TestUpdatePartitionProperties.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestUpdatePartitionProperties.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/op/TestUpdatePartitionProperties.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestUpdatePartitionProperties.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/op/TestUpdateTable.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestUpdateTable.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/op/TestUpdateTable.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/op/TestUpdateTable.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/optimizing/IcebergRewriteExecutorTest.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/optimizing/IcebergRewriteExecutorTest.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/optimizing/IcebergRewriteExecutorTest.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/optimizing/IcebergRewriteExecutorTest.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/scan/TestBaseCombinedScanTask.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestBaseCombinedScanTask.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/scan/TestBaseCombinedScanTask.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestBaseCombinedScanTask.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/scan/TestKeyedTableScan.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestKeyedTableScan.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/scan/TestKeyedTableScan.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestKeyedTableScan.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/scan/TestMixedChangeTableScan.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestMixedChangeTableScan.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/scan/TestMixedChangeTableScan.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestMixedChangeTableScan.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/scan/TestScanSplitTask.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestScanSplitTask.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/scan/TestScanSplitTask.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestScanSplitTask.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/scan/TestTableEntriesScan.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestTableEntriesScan.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/scan/TestTableEntriesScan.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/scan/TestTableEntriesScan.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/table/blocker/TestBasicTableBlockerManager.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/table/blocker/TestBasicTableBlockerManager.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/table/blocker/TestBasicTableBlockerManager.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/table/blocker/TestBasicTableBlockerManager.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/trace/TestTableTracer.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/trace/TestTableTracer.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/trace/TestTableTracer.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/trace/TestTableTracer.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/trace/TestTableWatermark.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/trace/TestTableWatermark.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/trace/TestTableWatermark.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/trace/TestTableWatermark.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestCompatiblePropertyUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestCompatiblePropertyUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestCompatiblePropertyUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestCompatiblePropertyUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestFileUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestFileUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestFileUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestFileUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestKeyedExpressionUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestKeyedExpressionUtil.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestKeyedExpressionUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestKeyedExpressionUtil.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestMixedDataFiles.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestMixedDataFiles.java
similarity index 100%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestMixedDataFiles.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestMixedDataFiles.java
diff --git a/amoro-core/src/test/java/org/apache/amoro/utils/TestMixedCatalogUtil.java b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestMixedFormatCatalogUtil.java
similarity index 92%
rename from amoro-core/src/test/java/org/apache/amoro/utils/TestMixedCatalogUtil.java
rename to amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestMixedFormatCatalogUtil.java
index b78f95f3b..3aaf6451f 100644
--- a/amoro-core/src/test/java/org/apache/amoro/utils/TestMixedCatalogUtil.java
+++ b/amoro-iceberg-format/src/test/java/org/apache/amoro/utils/TestMixedFormatCatalogUtil.java
@@ -28,7 +28,7 @@ import org.junit.Test;
 import java.util.HashMap;
 import java.util.Map;
 
-public class TestMixedCatalogUtil {
+public class TestMixedFormatCatalogUtil {
   /**
    * when log-store flag is on , fill up with default related props and other user-defined prop
    * should be keep
@@ -54,7 +54,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -75,7 +75,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -100,7 +100,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -127,7 +127,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -164,7 +164,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -202,7 +202,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -235,7 +235,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -266,7 +266,7 @@ public class TestMixedCatalogUtil {
     catalogProperties.put("ams.address", "127.0.0.1");
 
     Map<String, String> result =
-        MixedCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
+        MixedFormatCatalogUtil.mergeCatalogPropertiesToTable(userDefined, catalogProperties);
     Assert.assertEquals(expected, result);
   }
 
@@ -284,13 +284,13 @@ public class TestMixedCatalogUtil {
 
     // hive catalog
     props =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             name, typeHadoop, ImmutableMap.of(keyWarehouse, path));
     Assert.assertEquals(typeHadoop, props.get(type));
 
     // custom
     props =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             name,
             typeCustom,
             ImmutableMap.of(keyWarehouse, path, CatalogProperties.CATALOG_IMPL, restImpl));
@@ -299,13 +299,13 @@ public class TestMixedCatalogUtil {
     Assert.assertThrows(
         IllegalArgumentException.class,
         () -> {
-          MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+          MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
               name, typeCustom, ImmutableMap.of(keyWarehouse, path));
         });
 
     // ams
     props =
-        MixedCatalogUtil.withIcebergCatalogInitializeProperties(
+        MixedFormatCatalogUtil.withIcebergCatalogInitializeProperties(
             name, typeAms, ImmutableMap.of(keyWarehouse, path));
     Assert.assertEquals(name, props.get(keyWarehouse));
     Assert.assertFalse(props.containsKey(type));
diff --git a/amoro-mixed-format/amoro-mixed-format-hive/src/test/java/org/apache/amoro/hive/catalog/HiveCatalogTestHelper.java b/amoro-mixed-format/amoro-mixed-format-hive/src/test/java/org/apache/amoro/hive/catalog/HiveCatalogTestHelper.java
index ce8efd652..5084d032f 100644
--- a/amoro-mixed-format/amoro-mixed-format-hive/src/test/java/org/apache/amoro/hive/catalog/HiveCatalogTestHelper.java
+++ b/amoro-mixed-format/amoro-mixed-format-hive/src/test/java/org/apache/amoro/hive/catalog/HiveCatalogTestHelper.java
@@ -30,7 +30,7 @@ import org.apache.amoro.catalog.CatalogTestHelpers;
 import org.apache.amoro.catalog.MixedTables;
 import org.apache.amoro.properties.CatalogMetaProperties;
 import org.apache.amoro.shade.guava32.com.google.common.collect.Maps;
-import org.apache.amoro.utils.MixedCatalogUtil;
+import org.apache.amoro.utils.CatalogUtil;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.iceberg.CatalogProperties;
@@ -94,7 +94,7 @@ public class HiveCatalogTestHelper implements CatalogTestHelper {
           "Cannot build mixed-tables for table format:" + tableFormat);
     }
     return new MixedTables(
-        catalogMeta.getCatalogProperties(), MixedCatalogUtil.buildMetaStore(catalogMeta));
+        catalogMeta.getCatalogProperties(), CatalogUtil.buildMetaStore(catalogMeta));
   }
 
   @Override