Skip to content

Commit b062d03

Browse files
committed
Implemented support for Java 16 and newer
1 parent 4d5be63 commit b062d03

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

README.MD

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# ConfigAPI
2-
Config API for Bukkit 1.8 - 1.16 based on dynamic proxies
2+
Config API for Bukkit 1.8 - 1.17 based on dynamic proxies
33

44
## Features:
5-
- Works with Bukkit 1.8 - 1.16
6-
- Compatible with Java 8 - 15
5+
- Works with Bukkit 1.8 - 1.17
6+
- Compatible with Java 8 - 17
77
- Multiple configuration files
88
- Fastly create configs via Java interface with `default` getters
99
- Automatic generation of config's YAML file
@@ -20,7 +20,7 @@ maven {
2020
url = 'https://repo.mikigal.pl/releases'
2121
}
2222
23-
compile group: 'pl.mikigal', name: 'ConfigAPI', version: '1.1.5'
23+
compile group: 'pl.mikigal', name: 'ConfigAPI', version: '1.1.6'
2424
```
2525

2626
#### Maven
@@ -33,7 +33,7 @@ compile group: 'pl.mikigal', name: 'ConfigAPI', version: '1.1.5'
3333
<dependency>
3434
<groupId>pl.mikigal</groupId>
3535
<artifactId>ConfigAPI</artifactId>
36-
<version>1.1.5</version>
36+
<version>1.1.6</version>
3737
<scope>compile</scope>
3838
</dependency>
3939
```

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group 'pl.mikigal'
7-
version '1.1.5'
7+
version '1.1.6'
88

99
publishing {
1010
repositories {

src/main/java/pl/mikigal/config/util/ReflectionUtils.java

+54-13
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55

66
import java.lang.invoke.MethodHandles;
77
import java.lang.reflect.Field;
8+
import java.lang.reflect.InvocationTargetException;
89
import java.lang.reflect.Method;
910
import java.lang.reflect.Proxy;
11+
import java.util.HashMap;
12+
import java.util.Map;
1013

1114
/**
1215
* Utilities for reflections
@@ -15,18 +18,7 @@
1518
*/
1619
public class ReflectionUtils {
1720

18-
private static final MethodHandles.Lookup lookup;
19-
20-
static {
21-
try {
22-
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
23-
field.setAccessible(true);
24-
25-
lookup = (MethodHandles.Lookup) field.get(null);
26-
} catch (NoSuchFieldException | IllegalAccessException e) {
27-
throw new InvalidConfigException("Could not get MethodHandles.Lookup", e);
28-
}
29-
}
21+
private static final Map<Class<?>, MethodHandles.Lookup> lookups = new HashMap<>();
3022

3123
/**
3224
* Allows to get default value of method from interface
@@ -36,7 +28,7 @@ public class ReflectionUtils {
3628
public static Object getDefaultValue(Method method) {
3729
try {
3830
Class<?> clazz = method.getDeclaringClass();
39-
return lookup
31+
return getLookup(clazz)
4032
.in(clazz)
4133
.unreflectSpecial(method, clazz)
4234
.bindTo(createHelperProxy(method.getDeclaringClass()))
@@ -46,6 +38,46 @@ public static Object getDefaultValue(Method method) {
4638
}
4739
}
4840

41+
/**
42+
* Creates private lookup for given class
43+
* For Java 8 it gets value of MethodHandles.Lookup.IMPL_LOOKUP, for newer versions invokes MethodHandles.privateLookupIn()
44+
* Reference: https://github.com/OpenFeign/feign/commit/3494a76f160d6622129d59a6c79358dbccf6e6d6
45+
* @param clazz for which you want to create lookup
46+
* @return instance of lookup
47+
*/
48+
private static MethodHandles.Lookup createLookup(Class<?> clazz) {
49+
boolean oldJava = isOldJava();
50+
51+
try {
52+
if (oldJava) {
53+
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
54+
field.setAccessible(true);
55+
56+
return (MethodHandles.Lookup) field.get(null);
57+
}
58+
59+
Object privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class)
60+
.invoke(null, clazz, MethodHandles.lookup());
61+
62+
return (MethodHandles.Lookup) privateLookupIn;
63+
} catch (IllegalAccessException | NoSuchFieldException | NoSuchMethodException | InvocationTargetException e) {
64+
throw new InvalidConfigException("Could not get MethodHandles.Lookup for " + clazz.getName() + " (legacy way: " + oldJava + ")", e);
65+
}
66+
}
67+
68+
/**
69+
* Gets lookup for given class from cache or create new one if it doesn't exist
70+
* @param clazz for which you want to get lookup
71+
* @return instance of lookup for given class
72+
*/
73+
private static MethodHandles.Lookup getLookup(Class<?> clazz) {
74+
if (!lookups.containsKey(clazz)) {
75+
lookups.put(clazz, createLookup(clazz));
76+
}
77+
78+
return lookups.get(clazz);
79+
}
80+
4981
/**
5082
* Creates instance of proxy
5183
* @param clazz class which you want to get instance of
@@ -56,6 +88,15 @@ private static Object createHelperProxy(Class<?> clazz) {
5688
(Object object, Method method, Object[] args) -> null);
5789
}
5890

91+
/**
92+
* Check Java version
93+
* @return true for Java 8, false for Java 9 or newer
94+
*/
95+
private static boolean isOldJava() {
96+
String javaVersion = System.getProperty("java.version");
97+
return javaVersion.startsWith("1.8") || javaVersion.startsWith("8");
98+
}
99+
59100
/**
60101
* Check bukkit versions
61102
* @return false for Minecraft 1.12 or older, true for 1.13 or newer

0 commit comments

Comments
 (0)