23
23
import java .lang .reflect .InvocationTargetException ;
24
24
import java .lang .reflect .Type ;
25
25
import java .util .ServiceLoader ;
26
+ import javax .annotation .concurrent .GuardedBy ;
26
27
import net .bytebuddy .ByteBuddy ;
27
28
import net .bytebuddy .asm .AsmVisitorWrapper ;
28
29
import net .bytebuddy .description .type .TypeDescription ;
57
58
"rawtypes"
58
59
})
59
60
public class ConvertHelpers {
61
+
60
62
private static class SchemaInformationProviders {
63
+ @ GuardedBy ("lock" )
61
64
private static final ServiceLoader <SchemaInformationProvider > INSTANCE =
62
65
ServiceLoader .load (SchemaInformationProvider .class );
63
66
}
64
67
65
68
private static final Logger LOG = LoggerFactory .getLogger (ConvertHelpers .class );
69
+ private static final Object lock = new Object ();
66
70
67
71
/** Return value after converting a schema. */
68
72
public static class ConvertedSchemaInformation <T > implements Serializable {
@@ -85,57 +89,60 @@ public ConvertedSchemaInformation(
85
89
public static <T > ConvertedSchemaInformation <T > getConvertedSchemaInformation (
86
90
Schema inputSchema , TypeDescriptor <T > outputType , SchemaRegistry schemaRegistry ) {
87
91
88
- ConvertedSchemaInformation <T > schemaInformation = null ;
89
92
// Try to load schema information from loaded providers
90
- for (SchemaInformationProvider provider : SchemaInformationProviders .INSTANCE ) {
91
- schemaInformation = provider .getConvertedSchemaInformation (inputSchema , outputType );
92
- if (schemaInformation != null ) {
93
- return schemaInformation ;
93
+ try {
94
+ synchronized (lock ) {
95
+ for (SchemaInformationProvider provider : SchemaInformationProviders .INSTANCE ) {
96
+ ConvertedSchemaInformation <T > schemaInformation =
97
+ provider .getConvertedSchemaInformation (inputSchema , outputType );
98
+ if (schemaInformation != null ) {
99
+ return schemaInformation ;
100
+ }
101
+ }
94
102
}
103
+ } catch (Exception e ) {
104
+ LOG .debug ("No Schema information from loaded providers found for type {}" , outputType , e );
95
105
}
96
106
97
- if (schemaInformation == null ) {
98
- // Otherwise, try to find a schema for the output type in the schema registry.
99
- Schema outputSchema = null ;
100
- SchemaCoder <T > outputSchemaCoder = null ;
101
- try {
102
- outputSchema = schemaRegistry .getSchema (outputType );
103
- outputSchemaCoder =
104
- SchemaCoder .of (
105
- outputSchema ,
106
- outputType ,
107
- schemaRegistry .getToRowFunction (outputType ),
108
- schemaRegistry .getFromRowFunction (outputType ));
109
- } catch (NoSuchSchemaException e ) {
110
- LOG .debug ("No schema found for type " + outputType , e );
111
- }
112
- FieldType unboxedType = null ;
113
- // TODO: Properly handle nullable.
114
- if (outputSchema == null || !outputSchema .assignableToIgnoreNullable (inputSchema )) {
115
- // The schema is not convertible directly. Attempt to unbox it and see if the schema matches
116
- // then.
117
- Schema checkedSchema = inputSchema ;
118
- if (inputSchema .getFieldCount () == 1 ) {
119
- unboxedType = inputSchema .getField (0 ).getType ();
120
- if (unboxedType .getTypeName ().isCompositeType ()
121
- && !outputSchema .assignableToIgnoreNullable (unboxedType .getRowSchema ())) {
122
- checkedSchema = unboxedType .getRowSchema ();
123
- } else {
124
- checkedSchema = null ;
125
- }
126
- }
127
- if (checkedSchema != null ) {
128
- throw new RuntimeException (
129
- "Cannot convert between types that don't have equivalent schemas."
130
- + " input schema: "
131
- + checkedSchema
132
- + " output schema: "
133
- + outputSchema );
107
+ // Otherwise, try to find a schema for the output type in the schema registry.
108
+ Schema outputSchema = null ;
109
+ SchemaCoder <T > outputSchemaCoder = null ;
110
+ try {
111
+ outputSchema = schemaRegistry .getSchema (outputType );
112
+ outputSchemaCoder =
113
+ SchemaCoder .of (
114
+ outputSchema ,
115
+ outputType ,
116
+ schemaRegistry .getToRowFunction (outputType ),
117
+ schemaRegistry .getFromRowFunction (outputType ));
118
+ } catch (NoSuchSchemaException e ) {
119
+ LOG .debug ("No schema found for type {}" , outputType , e );
120
+ }
121
+ FieldType unboxedType = null ;
122
+ // TODO: Properly handle nullable.
123
+ if (outputSchema == null || !outputSchema .assignableToIgnoreNullable (inputSchema )) {
124
+ // The schema is not convertible directly. Attempt to unbox it and see if the schema matches
125
+ // then.
126
+ Schema checkedSchema = inputSchema ;
127
+ if (inputSchema .getFieldCount () == 1 ) {
128
+ unboxedType = inputSchema .getField (0 ).getType ();
129
+ if (unboxedType .getTypeName ().isCompositeType ()
130
+ && !outputSchema .assignableToIgnoreNullable (unboxedType .getRowSchema ())) {
131
+ checkedSchema = unboxedType .getRowSchema ();
132
+ } else {
133
+ checkedSchema = null ;
134
134
}
135
135
}
136
- schemaInformation = new ConvertedSchemaInformation <T >(outputSchemaCoder , unboxedType );
136
+ if (checkedSchema != null ) {
137
+ throw new RuntimeException (
138
+ "Cannot convert between types that don't have equivalent schemas."
139
+ + " input schema: "
140
+ + checkedSchema
141
+ + " output schema: "
142
+ + outputSchema );
143
+ }
137
144
}
138
- return schemaInformation ;
145
+ return new ConvertedSchemaInformation <>( outputSchemaCoder , unboxedType ) ;
139
146
}
140
147
141
148
/**
0 commit comments