Skip to content

Commit 45fb04a

Browse files
committed
Ignore access-checks when creating annotated type-(de)serializers
1 parent 49d1f2e commit 45fb04a

File tree

2 files changed

+73
-34
lines changed

2 files changed

+73
-34
lines changed

src/main/java/de/bluecolored/bluenbt/adapter/DefaultDeserializerFactory.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ public DefaultAdapter(TypeToken<T> type, BlueNBT blueNBT) {
144144
this.type = type;
145145
this.constructor = blueNBT.getInstanceCreator(type);
146146

147+
Map<Class<? extends TypeDeserializer<?>>, TypeDeserializer<?>> typeDeserializerCache = new HashMap<>();
148+
147149
TypeToken<?> typeToken = type;
148150
Class<?> raw;
149151
while (typeToken != null && (raw = typeToken.getRawType()) != Object.class) {
@@ -163,11 +165,10 @@ public DefaultAdapter(TypeToken<T> type, BlueNBT blueNBT) {
163165
TypeDeserializer<?> typeDeserializer;
164166
Class<? extends TypeDeserializer<?>> deserializerType = findDeserializerType(field, fieldType.getRawType());
165167
if (deserializerType != null) {
166-
try {
167-
typeDeserializer = createTypeDeserializerInstance(deserializerType, fieldType, blueNBT);
168-
} catch (Exception ex) {
169-
throw new IllegalStateException("Failed to create instance of TypeDeserializer: " + deserializerType, ex);
170-
}
168+
typeDeserializer = typeDeserializerCache.computeIfAbsent(
169+
deserializerType,
170+
t -> createTypeDeserializerInstance(t, fieldType, blueNBT)
171+
);
171172
} else if (SPECIAL_ACCESSORS.containsKey(fieldType.getType())) {
172173
FieldAccessor accessor = SPECIAL_ACCESSORS.get(fieldType.getType()).apply(field);
173174
for (String name : names)
@@ -247,24 +248,35 @@ private TypeDeserializer<?> createTypeDeserializerInstance(
247248
Class<? extends TypeDeserializer<?>> deserializerType,
248249
TypeToken<?> fieldType,
249250
BlueNBT blueNBT
250-
) throws ReflectiveOperationException {
251-
// try TypeToken & BlueNBT constructor
251+
) {
252252
try {
253-
return deserializerType.getDeclaredConstructor(TypeToken.class, BlueNBT.class).newInstance(fieldType, blueNBT);
254-
} catch (NoSuchMethodException ignore) {}
255253

256-
// try TypeToken constructor
257-
try {
258-
return deserializerType.getDeclaredConstructor(TypeToken.class).newInstance(fieldType);
259-
} catch (NoSuchMethodException ignore) {}
254+
// try TypeToken & BlueNBT constructor
255+
try {
256+
return callConstructor(deserializerType.getDeclaredConstructor(TypeToken.class, BlueNBT.class), fieldType, blueNBT);
257+
} catch (NoSuchMethodException ignore) {}
260258

261-
// try BlueNBT constructor
262-
try {
263-
return deserializerType.getDeclaredConstructor(BlueNBT.class).newInstance(blueNBT);
264-
} catch (NoSuchMethodException ignore) {}
259+
// try TypeToken constructor
260+
try {
261+
return callConstructor(deserializerType.getDeclaredConstructor(TypeToken.class), fieldType);
262+
} catch (NoSuchMethodException ignore) {}
263+
264+
// try BlueNBT constructor
265+
try {
266+
return callConstructor(deserializerType.getDeclaredConstructor(BlueNBT.class), blueNBT);
267+
} catch (NoSuchMethodException ignore) {}
268+
269+
// use no-args constructor
270+
return callConstructor(deserializerType.getDeclaredConstructor());
271+
272+
} catch (ReflectiveOperationException ex) {
273+
throw new IllegalStateException("Failed to create instance of TypeDeserializer: " + deserializerType, ex);
274+
}
275+
}
265276

266-
// use no-args constructor
267-
return deserializerType.getDeclaredConstructor().newInstance();
277+
private <U> U callConstructor(Constructor<U> constructor, Object... args) throws ReflectiveOperationException {
278+
constructor.setAccessible(true);
279+
return constructor.newInstance(args);
268280
}
269281

270282
}

src/main/java/de/bluecolored/bluenbt/adapter/DefaultSerializerFactory.java

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626

2727
import de.bluecolored.bluenbt.*;
2828
import lombok.RequiredArgsConstructor;
29+
import lombok.SneakyThrows;
2930
import org.jetbrains.annotations.Nullable;
3031

3132
import java.io.IOException;
33+
import java.lang.reflect.Constructor;
3234
import java.lang.reflect.Field;
3335
import java.lang.reflect.Modifier;
3436
import java.lang.reflect.Type;
@@ -73,8 +75,7 @@ static class DefaultAdapter<T> implements TypeSerializer<T> {
7375
public DefaultAdapter(TypeToken<T> type, BlueNBT blueNBT) {
7476
this.type = type;
7577

76-
Map<Class<? extends TypeSerializer<?>>, TypeSerializer<?>> typeSerializerCache =
77-
new HashMap<>();
78+
Map<Class<? extends TypeSerializer<?>>, TypeSerializer<?>> typeSerializerCache = new HashMap<>();
7879

7980
TypeToken<?> typeToken = type;
8081
Class<?> raw;
@@ -95,19 +96,10 @@ public DefaultAdapter(TypeToken<T> type, BlueNBT blueNBT) {
9596
TypeSerializer<?> typeSerializer;
9697
Class<? extends TypeSerializer<?>> serializerType = findSerializerType(field, fieldType.getRawType());
9798
if (serializerType != null) {
98-
typeSerializer = typeSerializerCache.computeIfAbsent(serializerType, t -> {
99-
try {
100-
// try BlueNBT constructor
101-
try {
102-
return t.getDeclaredConstructor(BlueNBT.class).newInstance(blueNBT);
103-
} catch (NoSuchMethodException ignore) {}
104-
105-
// use no-args constructor
106-
return t.getDeclaredConstructor().newInstance();
107-
} catch (Exception ex) {
108-
throw new RuntimeException("Failed to create Instance of TypeSerializer!", ex);
109-
}
110-
});
99+
typeSerializer = typeSerializerCache.computeIfAbsent(
100+
serializerType,
101+
t -> createTypeSerializerInstance(t, fieldType, blueNBT)
102+
);
111103
} else if (SPECIAL_ACCESSORS.containsKey(fieldType.getType())) {
112104
FieldWriter accessor = SPECIAL_ACCESSORS.get(fieldType.getType()).apply(field);
113105
fields.put(name, accessor);
@@ -156,6 +148,41 @@ public void write(T value, NBTWriter writer) throws IOException {
156148
return null;
157149
}
158150

151+
private TypeSerializer<?> createTypeSerializerInstance(
152+
Class<? extends TypeSerializer<?>> serializerType,
153+
TypeToken<?> fieldType,
154+
BlueNBT blueNBT
155+
) {
156+
try {
157+
158+
// try TypeToken & BlueNBT constructor
159+
try {
160+
return callConstructor(serializerType.getDeclaredConstructor(TypeToken.class, BlueNBT.class), fieldType, blueNBT);
161+
} catch (NoSuchMethodException ignore) {}
162+
163+
// try TypeToken constructor
164+
try {
165+
return callConstructor(serializerType.getDeclaredConstructor(TypeToken.class), fieldType);
166+
} catch (NoSuchMethodException ignore) {}
167+
168+
// try BlueNBT constructor
169+
try {
170+
return callConstructor(serializerType.getDeclaredConstructor(BlueNBT.class), blueNBT);
171+
} catch (NoSuchMethodException ignore) {}
172+
173+
// use no-args constructor
174+
return callConstructor(serializerType.getDeclaredConstructor());
175+
176+
} catch (ReflectiveOperationException ex) {
177+
throw new IllegalStateException("Failed to create instance of TypeSerializer: " + serializerType, ex);
178+
}
179+
}
180+
181+
private <U> U callConstructor(Constructor<U> constructor, Object... args) throws ReflectiveOperationException {
182+
constructor.setAccessible(true);
183+
return constructor.newInstance(args);
184+
}
185+
159186
}
160187

161188
private interface FieldWriter {

0 commit comments

Comments
 (0)