Skip to content

Commit

Permalink
Most likely working value annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
ablax committed Feb 12, 2020
1 parent ea67d9b commit 08bbb0e
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/main/java/me/ablax/decode/ApiManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,16 @@ void register(JavaPlugin javaPlugin) {

components.put(javaPluginClass.getCanonicalName(), javaPlugin);
managersController.populateInjectors(javaPlugin);
managersController.populateValues(javaPlugin);

List<? extends Class<?>> classesList = getClassesList(javaPluginClass);

if (!classesList.isEmpty()) {
managersController.registerAllComponents(classesList);
managersController.registerAllListeners(javaPlugin, classesList);
managersController.registerAllCommands(javaPlugin, classesList);
managersController.populateInjectors(classesList);
managersController.populateValues(javaPlugin, classesList);
} else {
Bukkit.getLogger().severe("I could't find any classes belonging to plugin: " + javaPlugin.getName());
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/me/ablax/decode/annotation/Value.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package me.ablax.decode.annotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Value {

String name();

}
4 changes: 4 additions & 0 deletions src/main/java/me/ablax/decode/managers/ComponentsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class ComponentsManager {
this.components = components;
}

boolean containsClass(Class<?> clazz) {
return components.containsKey(clazz.getCanonicalName());
}

void registerAllComponents(List<? extends Class<?>> allClasses) {
for (Class<?> aClass : allClasses) {
if (aClass.isInterface()) {
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/me/ablax/decode/managers/ManagersController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class ManagersController {

private final ComponentsManager componentsManager;
private final InjectorsManager injectorsManager;
private final ValuesManager valuesManager;
private final ListenersManager listenersManager;
private final CommandsManager commandsManager;

Expand All @@ -23,6 +24,7 @@ public ManagersController(Map<String, Object> components) {
instance = this;
this.componentsManager = new ComponentsManager(components);
this.injectorsManager = new InjectorsManager(components, componentsManager);
this.valuesManager = new ValuesManager(components);
this.listenersManager = new ListenersManager(components, componentsManager);
this.commandsManager = new CommandsManager(components, componentsManager);
}
Expand All @@ -46,4 +48,24 @@ public void registerAllComponents(List<? extends Class<?>> classesList) {
public void populateInjectors(JavaPlugin javaPlugin) {
this.injectorsManager.populateInjectors(javaPlugin);
}

public void populateInjectors(List<? extends Class<?>> classesList) {
for (Class<?> clazz : classesList) {
if (componentsManager.containsClass(clazz)) {
this.injectorsManager.populateInjectors(componentsManager);
}
}
}

public void populateValues(JavaPlugin javaPlugin) {
this.valuesManager.populateValues(javaPlugin);
}

public void populateValues(JavaPlugin javaPlugin, List<? extends Class<?>> classesList) {
for (Class<?> clazz : classesList) {
if (componentsManager.containsClass(clazz)) {
this.valuesManager.populateValues(javaPlugin, clazz);
}
}
}
}
97 changes: 97 additions & 0 deletions src/main/java/me/ablax/decode/managers/ValuesManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package me.ablax.decode.managers;

import me.ablax.decode.annotation.Value;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.logging.Level;

class ValuesManager {

private final Map<String, Object> components;
private sun.misc.Unsafe unsafe;
private boolean useUnsafe = true;

ValuesManager(Map<String, Object> components) {
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
final Object theUnsafe = field.get(null);
unsafe = (sun.misc.Unsafe) theUnsafe;
} catch (Exception e) {
unsafe = null;
useUnsafe = false;
}

this.components = components;
}

void populateValues(Object klass) {
for (Field field : klass.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(Value.class)) {
Class<?> type = field.getType();
final Value annotation = type.getAnnotation(Value.class);
if (klass instanceof Plugin) {
final Object object = ((Plugin) klass).getConfig().get(annotation.name());
populateField(klass, field, object);
}
}
}
}

public void populateValues(JavaPlugin javaPlugin, Class<?> clazz) {
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Value.class)) {
Class<?> type = field.getType();
final Value annotation = type.getAnnotation(Value.class);
final Object object = javaPlugin.getConfig().get(annotation.name());
populateField(components.get(clazz.getCanonicalName()), field, object);
}
}
}

private void populateField(Object klass, Field field, Object injectInstance) {
final boolean accessible = field.isAccessible();
if (!useUnsafe) {
if (!accessible) {
field.setAccessible(true);
}
try {
if (Modifier.isFinal(field.getModifiers())) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
}
} catch (IllegalAccessException ex) {
Bukkit.getLogger().log(Level.SEVERE,
"AdvancedPluginAPI can't work like that. It's not allowed to use Unsafe, neither access private/final/both fields.", ex);
} catch (NoSuchFieldException ex) {
Bukkit.getLogger().log(Level.SEVERE,
"AdvancedPluginAPI can't work like that. It's not allowed to use Unsafe, neither the claimed filed was there. Please report this to owner: ", ex);
}
try {
field.set(klass, injectInstance);
} catch (IllegalAccessException ex) {
Bukkit.getLogger().log(Level.SEVERE,
"AdvancedPluginAPI can't work like that. It's not allowed to use Unsafe, neither access private/final/both fields.", ex);
}
if (!accessible) {
field.setAccessible(false);
}
return;
}

if (!accessible) {
field.setAccessible(true);
}
unsafe.putObject(klass, unsafe.objectFieldOffset(field), injectInstance);
if (!accessible) {
field.setAccessible(false);
}
}

}

0 comments on commit 08bbb0e

Please sign in to comment.