Skip to content

Commit c8a0d2a

Browse files
authored
[jindo] Extract doDelete() template method from HadoopCompliantFileIO (#7668)
Refactor `HadoopCompliantFileIO.delete()` to delegate to a new `protected doDelete(Path, boolean)` template method. This allows subclasses (e.g. JindoFileIO) to intercept delete operations (trash/recycle-bin, audit logging, etc.) while retaining access to the real filesystem delete via `doDelete()`.
1 parent 05c2d3d commit c8a0d2a

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

paimon-filesystems/paimon-jindo/src/main/java/org/apache/paimon/jindo/HadoopCompliantFileIO.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@ public boolean exists(Path path) throws IOException {
200200

201201
@Override
202202
public boolean delete(Path path, boolean recursive) throws IOException {
203+
return doDelete(path, recursive);
204+
}
205+
206+
/**
207+
* Perform the actual filesystem delete. Subclasses that override {@link #delete} can call this
208+
* to execute the real delete when needed.
209+
*/
210+
protected boolean doDelete(Path path, boolean recursive) throws IOException {
203211
org.apache.hadoop.fs.Path hadoopPath = path(path);
204212
return getFileSystem(hadoopPath, false).delete(hadoopPath, recursive);
205213
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.paimon.jindo;
20+
21+
import org.apache.paimon.catalog.CatalogContext;
22+
import org.apache.paimon.fs.Path;
23+
import org.apache.paimon.utils.Pair;
24+
25+
import com.aliyun.jindodata.common.JindoHadoopSystem;
26+
import org.junit.jupiter.api.Test;
27+
28+
import java.io.IOException;
29+
import java.util.ArrayList;
30+
import java.util.List;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/** Tests for the {@code doDelete} template method in {@link HadoopCompliantFileIO}. */
35+
public class TestHadoopCompliantFileIODeleteHook {
36+
37+
@Test
38+
void deleteCallsDoDeleteByDefault() {
39+
TrackingFileIO fileIO = new TrackingFileIO();
40+
Path path = new Path("oss://bucket/warehouse/data.parquet");
41+
42+
try {
43+
fileIO.delete(path, false);
44+
} catch (Exception ignored) {
45+
}
46+
47+
assertThat(fileIO.doDeleteCalled).isTrue();
48+
}
49+
50+
@Test
51+
void subclassCanOverrideDeleteAndRouteToDoDelete() throws IOException {
52+
RoutingFileIO fileIO = new RoutingFileIO();
53+
Path systemPath = new Path("oss://bucket/warehouse/system/data.parquet");
54+
Path normalPath = new Path("oss://bucket/warehouse/data.parquet");
55+
56+
// system path → subclass routes to doDelete (real FS delete)
57+
try {
58+
fileIO.delete(systemPath, false);
59+
} catch (Exception ignored) {
60+
}
61+
assertThat(fileIO.handledPaths).isEmpty();
62+
assertThat(fileIO.doDeleteCalled).isTrue();
63+
64+
// normal path → subclass handles it directly, doDelete not called
65+
fileIO.doDeleteCalled = false;
66+
boolean result = fileIO.delete(normalPath, false);
67+
assertThat(result).isTrue();
68+
assertThat(fileIO.handledPaths).containsExactly(normalPath);
69+
assertThat(fileIO.doDeleteCalled).isFalse();
70+
}
71+
72+
/** Subclass that overrides delete() to route some paths to doDelete and handle others. */
73+
private static class RoutingFileIO extends StubFileIO {
74+
final List<Path> handledPaths = new ArrayList<>();
75+
boolean doDeleteCalled = false;
76+
77+
@Override
78+
public boolean delete(Path path, boolean recursive) throws IOException {
79+
if (path.toString().contains("system")) {
80+
return doDelete(path, recursive);
81+
}
82+
handledPaths.add(path);
83+
return true;
84+
}
85+
86+
@Override
87+
protected boolean doDelete(Path path, boolean recursive) throws IOException {
88+
doDeleteCalled = true;
89+
return super.doDelete(path, recursive);
90+
}
91+
92+
@Override
93+
public boolean isObjectStore() {
94+
return true;
95+
}
96+
}
97+
98+
/** Tracks whether doDelete was called. */
99+
private static class TrackingFileIO extends StubFileIO {
100+
boolean doDeleteCalled = false;
101+
102+
@Override
103+
protected boolean doDelete(Path path, boolean recursive) throws IOException {
104+
doDeleteCalled = true;
105+
return super.doDelete(path, recursive);
106+
}
107+
108+
@Override
109+
public boolean isObjectStore() {
110+
return true;
111+
}
112+
}
113+
114+
/** Minimal stub — no real FS. */
115+
private abstract static class StubFileIO extends HadoopCompliantFileIO {
116+
@Override
117+
public void configure(CatalogContext context) {}
118+
119+
@Override
120+
protected Pair<JindoHadoopSystem, String> createFileSystem(
121+
org.apache.hadoop.fs.Path path, boolean enableCache) {
122+
throw new UnsupportedOperationException("no real FS in test");
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)