in parquet-avro/src/main/java/org/apache/parquet/avro/AvroRecordConverter.java [183:244]
static SpecificData getModelForSchema(Schema schema) {
final Class<?> clazz;
if (schema != null && (schema.getType() == Schema.Type.RECORD || schema.getType() == Schema.Type.UNION)) {
clazz = SpecificData.get().getClass(schema);
} else {
return null;
}
// If clazz == null, the underlying Avro class for the schema is not on the classpath
if (clazz == null) {
return null;
}
final SpecificData model;
try {
final Field modelField = clazz.getDeclaredField("MODEL$");
modelField.setAccessible(true);
model = (SpecificData) modelField.get(null);
} catch (NoSuchFieldException e) {
LOG.info(String.format(
"Generated Avro class %s did not contain a MODEL$ field. Parquet will use default SpecificData model for " +
"reading and writing.", clazz));
return null;
} catch (IllegalAccessException e) {
LOG.warn(String.format(
"Field `MODEL$` in class %s was inaccessible. Parquet will use default SpecificData model for " +
"reading and writing.", clazz), e);
return null;
}
final String avroVersion = getRuntimeAvroVersion();
// Avro 1.7 and 1.8 don't include conversions in the MODEL$ field by default
if (avroVersion != null && (avroVersion.startsWith("1.8.") || avroVersion.startsWith("1.7."))) {
final Field conversionsField;
try {
conversionsField = clazz.getDeclaredField("conversions");
} catch (NoSuchFieldException e) {
// Avro classes without logical types (denoted by the "conversions" field) can be returned as-is
return model;
}
final Conversion<?>[] conversions;
try {
conversionsField.setAccessible(true);
conversions = (Conversion<?>[]) conversionsField.get(null);
} catch (IllegalAccessException e) {
LOG.warn(String.format("Field `conversions` in class %s was inaccessible. Parquet will use default " +
"SpecificData model for reading and writing.", clazz));
return null;
}
for (int i = 0; i < conversions.length; i++) {
if (conversions[i] != null) {
model.addLogicalTypeConversion(conversions[i]);
}
}
}
return model;
}