Skip to content

Commit c528a52

Browse files
committed
Move static initializer method to an inner class to avoid classloader issues
1 parent 446b63e commit c528a52

File tree

1 file changed

+64
-34
lines changed

1 file changed

+64
-34
lines changed

core/src/main/java/org/apache/iceberg/io/datafile/DataFileServiceRegistry.java

+64-34
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,6 @@
3939
*/
4040
public final class DataFileServiceRegistry {
4141
private static final Logger LOG = LoggerFactory.getLogger(DataFileServiceRegistry.class);
42-
private static final Map<Key, ReaderService> READ_BUILDERS = Maps.newConcurrentMap();
43-
private static final Map<Key, WriterService<?>> WRITE_BUILDERS = Maps.newConcurrentMap();
44-
45-
static {
46-
for (ReaderService service : ServiceLoader.load(ReaderService.class)) {
47-
if (READ_BUILDERS.containsKey(service.key())) {
48-
throw new IllegalArgumentException(
49-
String.format(
50-
"Read service %s clashes with %s. Both serves %s",
51-
service.getClass(), READ_BUILDERS.get(service.key()), service.key()));
52-
}
53-
54-
READ_BUILDERS.putIfAbsent(service.key(), service);
55-
}
56-
57-
for (WriterService<?> service : ServiceLoader.load(WriterService.class)) {
58-
if (WRITE_BUILDERS.containsKey(service.key())) {
59-
throw new IllegalArgumentException(
60-
String.format(
61-
"Write service %s clashes with %s. Both serves %s",
62-
service.getClass(), WRITE_BUILDERS.get(service.key()), service.key()));
63-
}
64-
65-
WRITE_BUILDERS.putIfAbsent(service.key(), service);
66-
}
67-
68-
LOG.info("DataFileServices found: readers={}, writers={}", READ_BUILDERS, WRITE_BUILDERS);
69-
}
7042

7143
private DataFileServiceRegistry() {}
7244

@@ -124,8 +96,7 @@ public static ReaderBuilder readerBuilder(
12496
Schema readSchema,
12597
Map<Integer, ?> idToConstant,
12698
DeleteFilter<?> deleteFilter) {
127-
return READ_BUILDERS
128-
.get(new Key(format, returnType, builderType))
99+
return Registry.readerBuilderFor(format, returnType, builderType)
129100
.builder(inputFile, readSchema, idToConstant, deleteFilter);
130101
}
131102

@@ -162,7 +133,7 @@ public static <S> AppenderBuilder appenderBuilder(
162133
String builderType,
163134
EncryptedOutputFile outputFile,
164135
S rowType) {
165-
return ((WriterService<S>) WRITE_BUILDERS.get(new Key(format, inputType, builderType)))
136+
return Registry.writeBuilderFor(format, inputType, builderType)
166137
.appenderBuilder(outputFile, rowType);
167138
}
168139

@@ -199,7 +170,7 @@ public static <S> DataWriterBuilder dataWriterBuilder(
199170
String builderType,
200171
EncryptedOutputFile outputFile,
201172
S rowType) {
202-
return ((WriterService<S>) WRITE_BUILDERS.get(new Key(format, inputType, builderType)))
173+
return Registry.writeBuilderFor(format, inputType, builderType)
203174
.dataWriterBuilder(outputFile, rowType);
204175
}
205176

@@ -238,7 +209,7 @@ EqualityDeleteWriterBuilder<B> equalityDeleteWriterBuilder(
238209
String builderType,
239210
EncryptedOutputFile outputFile,
240211
S rowType) {
241-
return ((WriterService<S>) WRITE_BUILDERS.get(new Key(format, inputType, builderType)))
212+
return Registry.writeBuilderFor(format, inputType, builderType)
242213
.equalityDeleteWriterBuilder(outputFile, rowType);
243214
}
244215

@@ -277,10 +248,69 @@ PositionDeleteWriterBuilder<B> positionDeleteWriterBuilder(
277248
String builderType,
278249
EncryptedOutputFile outputFile,
279250
S rowType) {
280-
return ((WriterService<S>) WRITE_BUILDERS.get(new Key(format, inputType, builderType)))
251+
return Registry.writeBuilderFor(format, inputType, builderType)
281252
.positionDeleteWriterBuilder(outputFile, rowType);
282253
}
283254

255+
/**
256+
* Internal class providing the actual registry. This is a separate class to avoid class loader
257+
* issues.
258+
*/
259+
private static final class Registry {
260+
private static final Map<Key, ReaderService> READ_BUILDERS = Maps.newConcurrentMap();
261+
private static final Map<Key, WriterService<?>> WRITE_BUILDERS = Maps.newConcurrentMap();
262+
263+
static {
264+
for (ReaderService service : ServiceLoader.load(ReaderService.class)) {
265+
if (READ_BUILDERS.containsKey(service.key())) {
266+
throw new IllegalArgumentException(
267+
String.format(
268+
"Read service %s clashes with %s. Both serves %s",
269+
service.getClass(), READ_BUILDERS.get(service.key()), service.key()));
270+
}
271+
272+
READ_BUILDERS.putIfAbsent(service.key(), service);
273+
}
274+
275+
for (WriterService<?> service : ServiceLoader.load(WriterService.class)) {
276+
if (WRITE_BUILDERS.containsKey(service.key())) {
277+
throw new IllegalArgumentException(
278+
String.format(
279+
"Write service %s clashes with %s. Both serves %s",
280+
service.getClass(), WRITE_BUILDERS.get(service.key()), service.key()));
281+
}
282+
283+
WRITE_BUILDERS.putIfAbsent(service.key(), service);
284+
}
285+
286+
LOG.info("DataFileServices found: readers={}, writers={}", READ_BUILDERS, WRITE_BUILDERS);
287+
}
288+
289+
private static ReaderService readerBuilderFor(
290+
FileFormat format, String inputType, String builderType) {
291+
Key key = new Key(format, inputType, builderType);
292+
ReaderService service = READ_BUILDERS.get(key);
293+
if (service == null) {
294+
throw new IllegalArgumentException(
295+
String.format("No reader builder registered for key %s", key));
296+
}
297+
298+
return service;
299+
}
300+
301+
private static <S> WriterService<S> writeBuilderFor(
302+
FileFormat format, String inputType, String builderType) {
303+
Key key = new Key(format, inputType, builderType);
304+
WriterService<S> service = (WriterService<S>) WRITE_BUILDERS.get(key);
305+
if (service == null) {
306+
throw new IllegalArgumentException(
307+
String.format("No writer builder registered for key %s", key));
308+
}
309+
310+
return service;
311+
}
312+
}
313+
284314
/**
285315
* Service building readers. Implementations should be registered through the {@link
286316
* java.util.ServiceLoader}. {@link DataFileServiceRegistry} is used to collect and serve the

0 commit comments

Comments
 (0)