add dependency injection API

This commit is contained in:
dfsek
2021-02-20 23:23:17 -07:00
parent 45dbe45fb4
commit 3b719d0880
9 changed files with 104 additions and 6 deletions

View File

@@ -0,0 +1,11 @@
package com.dfsek.terra.addons.injection;
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 Inject {
}

View File

@@ -0,0 +1,13 @@
package com.dfsek.terra.addons.injection;
public class InjectionException extends Exception {
private static final long serialVersionUID = -6929631447064215387L;
public InjectionException(String message) {
super(message);
}
public InjectionException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,47 @@
package com.dfsek.terra.addons.injection;
import com.dfsek.terra.api.util.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
public class Injector<T> {
private final T value;
private final Set<Class<? extends T>> targets = new HashSet<>();
public Injector(T value) {
this.value = value;
}
public void addExplicitTarget(Class<? extends T> target) {
targets.add(target);
}
public void inject(Object object) throws InjectionException {
for(Field field : ReflectionUtil.getFields(object.getClass())) {
Inject inject = field.getAnnotation(Inject.class);
if(inject == null) continue;
System.out.println(field);
System.out.println("attempting to inject " + value.getClass() + " to " + field.getClass());
if(value.getClass().equals(field.getType()) || targets.contains(field.getType())) {
System.out.println("injecting...");
int mod = field.getModifiers();
if(Modifier.isFinal(mod)) {
throw new InjectionException("Attempted to inject final field: " + field);
}
if(Modifier.isStatic(mod)) {
throw new InjectionException("Attempted to inject static field: " + field);
}
field.setAccessible(true);
try {
field.set(object, value);
} catch(IllegalAccessException e) {
throw new InjectionException("Failed to inject field: " + field, e);
}
}
}
}
}

View File

@@ -4,6 +4,8 @@ import com.dfsek.terra.addons.addon.TerraAddon;
import com.dfsek.terra.addons.annotations.Addon;
import com.dfsek.terra.addons.annotations.Depends;
import com.dfsek.terra.addons.loading.AddonLoadException;
import com.dfsek.terra.addons.loading.pre.exception.CircularDependencyException;
import com.dfsek.terra.addons.loading.pre.exception.DependencyMissingException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -32,7 +34,8 @@ public class PreLoadAddon {
for(String dependency : dependencies) {
PreLoadAddon preLoadAddon = pool.get(dependency);
if(preLoadAddon == null) throw new DependencyMissingException("Dependency " + dependency + " was not found.");
if(preLoadAddon == null)
throw new DependencyMissingException("Dependency " + dependency + " was not found. Please install " + dependency + " to use " + id + ".");
depends.add(preLoadAddon);
preLoadAddon.rebuildDependencies(pool, origin, false);
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.loading.pre;
package com.dfsek.terra.addons.loading.pre.exception;
import com.dfsek.terra.addons.loading.AddonLoadException;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.loading.pre;
package com.dfsek.terra.addons.loading.pre.exception;
import com.dfsek.terra.addons.loading.AddonLoadException;

View File

@@ -34,7 +34,11 @@ public class TerraEventManager implements EventManager {
try {
if(event instanceof PackEvent && !listenerHolder.global) {
PackEvent packEvent = (PackEvent) event;
if(packEvent.getPack().getTemplate().getAddons().contains(listenerHolder.addon)) {
if(packEvent
.getPack()
.getTemplate()
.getAddons()
.contains(listenerHolder.addon)) {
listenerHolder.method.invoke(listenerHolder.listener, event);
}
} else {

View File

@@ -8,6 +8,7 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -22,7 +23,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Value("addons")
@Default
private Set<TerraAddon> addons;
private Set<TerraAddon> addons = new HashSet<>();
@Value("variables")
@Default

View File

@@ -1,6 +1,8 @@
package com.dfsek.terra.registry;
import com.dfsek.terra.addons.addon.TerraAddon;
import com.dfsek.terra.addons.injection.InjectionException;
import com.dfsek.terra.addons.injection.Injector;
import com.dfsek.terra.addons.loading.AddonClassLoader;
import com.dfsek.terra.addons.loading.AddonLoadException;
import com.dfsek.terra.addons.loading.pre.AddonPool;
@@ -11,6 +13,8 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class AddonRegistry extends TerraRegistry<TerraAddon> {
private final TerraPlugin main;
@@ -39,6 +43,9 @@ public class AddonRegistry extends TerraRegistry<TerraAddon> {
}
public boolean loadAll() {
Injector<TerraPlugin> pluginInjector = new Injector<>(main);
pluginInjector.addExplicitTarget(TerraPlugin.class);
boolean valid = true;
File addonsFolder = new File(main.getDataFolder(), "addons");
addonsFolder.mkdirs();
@@ -59,6 +66,16 @@ public class AddonRegistry extends TerraRegistry<TerraAddon> {
Class<? extends TerraAddon> addonClass = addon.getAddonClass();
Constructor<? extends TerraAddon> constructor;
String logPrefix = "Terra:" + addon.getId();
Logger addonLogger = Logger.getLogger(logPrefix);
if(!LogManager.getLogManager().addLogger(addonLogger)) {
addonLogger = LogManager.getLogManager().getLogger(logPrefix);
}
Injector<Logger> loggerInjector = new Injector<>(addonLogger);
loggerInjector.addExplicitTarget(Logger.class);
try {
constructor = addonClass.getConstructor();
} catch(NoSuchMethodException e) {
@@ -67,7 +84,9 @@ public class AddonRegistry extends TerraRegistry<TerraAddon> {
TerraAddon loadedAddon;
try {
loadedAddon = constructor.newInstance();
} catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
pluginInjector.inject(loadedAddon);
loggerInjector.inject(loadedAddon);
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | InjectionException e) {
throw new AddonLoadException("Failed to load addon \" + " + addon.getId() + "\": ", e);
}
try {