|
5 | 5 | import java.io.OutputStream; |
6 | 6 | import java.lang.reflect.Constructor; |
7 | 7 | import java.lang.reflect.InvocationTargetException; |
| 8 | +import java.lang.reflect.Modifier; |
8 | 9 | import java.lang.reflect.RecordComponent; |
9 | 10 | import java.util.ArrayList; |
10 | 11 | import java.util.Arrays; |
@@ -51,14 +52,22 @@ public Object apply(Object input, Schema<Object, ?> schema) { |
51 | 52 |
|
52 | 53 | result = getObject(schema, result, recordConstructor); |
53 | 54 | } else if (!hasParameterlessPublicConstructor(clazz)) { |
54 | | - Constructor<?> primaryConstructor = CLASS2CONSTRUCTOR.computeIfAbsent(clazz, c -> c.getDeclaredConstructors()[0]); |
| 55 | + Constructor<?> primaryConstructor = CLASS2CONSTRUCTOR.computeIfAbsent(clazz, c -> getAnyPublicConstructor(c).orElse(null)); |
| 56 | + |
| 57 | + if (primaryConstructor == null) { |
| 58 | + throw new RuntimeException("Failed to initialize class " + clazz.getName() + ", no appropriate public constructor found"); |
| 59 | + } |
55 | 60 |
|
56 | 61 | result = getObject(schema, result, primaryConstructor); |
57 | 62 | } else { |
58 | 63 | if (result == null) { |
59 | 64 | try { |
60 | | - Constructor<?> primaryConstructor = CLASS2CONSTRUCTOR.computeIfAbsent(clazz, c -> c.getDeclaredConstructors()[0]); |
61 | | - result = primaryConstructor.newInstance(); |
| 65 | + Constructor<?> primaryConstructor = CLASS2CONSTRUCTOR.computeIfAbsent(clazz, c -> getParameterlessPublicConstructor(c).orElse(null)); |
| 66 | + if (primaryConstructor != null) { |
| 67 | + result = primaryConstructor.newInstance(); |
| 68 | + } else { |
| 69 | + throw new RuntimeException("Failed to locate a parameterless public constructor for class " + clazz.getName()); |
| 70 | + } |
62 | 71 | } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { |
63 | 72 | throw new RuntimeException(e); |
64 | 73 | } |
@@ -167,11 +176,19 @@ private Object getObject(Schema<Object, ?> schema, Object result, Constructor<?> |
167 | 176 | } |
168 | 177 |
|
169 | 178 | private boolean hasParameterlessPublicConstructor(Class<?> clazz) { |
170 | | - for (Constructor<?> constructor : clazz.getConstructors()) { |
171 | | - if (constructor.getParameterCount() == 0) { |
172 | | - return true; |
173 | | - } |
174 | | - } |
175 | | - return false; |
| 179 | + return getParameterlessPublicConstructor(clazz).isPresent(); |
| 180 | + } |
| 181 | + |
| 182 | + private Optional<Constructor<?>> getParameterlessPublicConstructor(Class<?> clazz) { |
| 183 | + return Arrays.stream(clazz.getConstructors()) |
| 184 | + .filter(constructor -> constructor.getParameterCount() == 0) |
| 185 | + .filter(constructor -> Modifier.isPublic(constructor.getModifiers())) |
| 186 | + .findFirst(); |
| 187 | + } |
| 188 | + |
| 189 | + private Optional<Constructor<?>> getAnyPublicConstructor(Class<?> clazz) { |
| 190 | + return Arrays.stream(clazz.getConstructors()) |
| 191 | + .filter(constructor -> Modifier.isPublic(constructor.getModifiers())) |
| 192 | + .findFirst(); |
176 | 193 | } |
177 | 194 | } |
0 commit comments