Skip to content

Commit

Permalink
Implemented support for Java 16 and newer
Browse files Browse the repository at this point in the history
  • Loading branch information
mikigal committed Nov 1, 2021
1 parent 4d5be63 commit b062d03
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 19 deletions.
10 changes: 5 additions & 5 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# ConfigAPI
Config API for Bukkit 1.8 - 1.16 based on dynamic proxies
Config API for Bukkit 1.8 - 1.17 based on dynamic proxies

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

#### Maven
Expand All @@ -33,7 +33,7 @@ compile group: 'pl.mikigal', name: 'ConfigAPI', version: '1.1.5'
<dependency>
<groupId>pl.mikigal</groupId>
<artifactId>ConfigAPI</artifactId>
<version>1.1.5</version>
<version>1.1.6</version>
<scope>compile</scope>
</dependency>
```
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group 'pl.mikigal'
version '1.1.5'
version '1.1.6'

publishing {
repositories {
Expand Down
67 changes: 54 additions & 13 deletions src/main/java/pl/mikigal/config/util/ReflectionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
* Utilities for reflections
Expand All @@ -15,18 +18,7 @@
*/
public class ReflectionUtils {

private static final MethodHandles.Lookup lookup;

static {
try {
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);

lookup = (MethodHandles.Lookup) field.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new InvalidConfigException("Could not get MethodHandles.Lookup", e);
}
}
private static final Map<Class<?>, MethodHandles.Lookup> lookups = new HashMap<>();

/**
* Allows to get default value of method from interface
Expand All @@ -36,7 +28,7 @@ public class ReflectionUtils {
public static Object getDefaultValue(Method method) {
try {
Class<?> clazz = method.getDeclaringClass();
return lookup
return getLookup(clazz)
.in(clazz)
.unreflectSpecial(method, clazz)
.bindTo(createHelperProxy(method.getDeclaringClass()))
Expand All @@ -46,6 +38,46 @@ public static Object getDefaultValue(Method method) {
}
}

/**
* Creates private lookup for given class
* For Java 8 it gets value of MethodHandles.Lookup.IMPL_LOOKUP, for newer versions invokes MethodHandles.privateLookupIn()
* Reference: https://github.com/OpenFeign/feign/commit/3494a76f160d6622129d59a6c79358dbccf6e6d6
* @param clazz for which you want to create lookup
* @return instance of lookup
*/
private static MethodHandles.Lookup createLookup(Class<?> clazz) {
boolean oldJava = isOldJava();

try {
if (oldJava) {
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);

return (MethodHandles.Lookup) field.get(null);
}

Object privateLookupIn = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class)
.invoke(null, clazz, MethodHandles.lookup());

return (MethodHandles.Lookup) privateLookupIn;
} catch (IllegalAccessException | NoSuchFieldException | NoSuchMethodException | InvocationTargetException e) {
throw new InvalidConfigException("Could not get MethodHandles.Lookup for " + clazz.getName() + " (legacy way: " + oldJava + ")", e);
}
}

/**
* Gets lookup for given class from cache or create new one if it doesn't exist
* @param clazz for which you want to get lookup
* @return instance of lookup for given class
*/
private static MethodHandles.Lookup getLookup(Class<?> clazz) {
if (!lookups.containsKey(clazz)) {
lookups.put(clazz, createLookup(clazz));
}

return lookups.get(clazz);
}

/**
* Creates instance of proxy
* @param clazz class which you want to get instance of
Expand All @@ -56,6 +88,15 @@ private static Object createHelperProxy(Class<?> clazz) {
(Object object, Method method, Object[] args) -> null);
}

/**
* Check Java version
* @return true for Java 8, false for Java 9 or newer
*/
private static boolean isOldJava() {
String javaVersion = System.getProperty("java.version");
return javaVersion.startsWith("1.8") || javaVersion.startsWith("8");
}

/**
* Check bukkit versions
* @return false for Minecraft 1.12 or older, true for 1.13 or newer
Expand Down

0 comments on commit b062d03

Please sign in to comment.