mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-13 19:26:14 +00:00
refactor API
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.addons.annotations.Addon;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class AddonClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
public AddonClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
public AddonClassLoader(URL[] urls) {
|
||||
super(urls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Set<Class<? extends TerraAddon>> fetchAddonClasses(File file) throws IOException {
|
||||
JarFile jarFile = new JarFile(file);
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
|
||||
AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, AddonClassLoader.class.getClassLoader());
|
||||
|
||||
Set<Class<? extends TerraAddon>> set = new HashSet<>();
|
||||
while(entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
|
||||
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
|
||||
String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.');
|
||||
|
||||
try {
|
||||
Class<?> clazz = loader.loadClass(className);
|
||||
|
||||
Addon addon = clazz.getAnnotation(Addon.class);
|
||||
|
||||
if(addon == null) continue;
|
||||
|
||||
if(!TerraAddon.class.isAssignableFrom(clazz)) throw new IllegalArgumentException("Addon class must extend TerraAddon.");
|
||||
|
||||
set.add((Class<? extends TerraAddon>) clazz);
|
||||
} catch(ClassNotFoundException e) {
|
||||
throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
32
common/src/main/java/com/dfsek/terra/addon/AddonPool.java
Normal file
32
common/src/main/java/com/dfsek/terra/addon/AddonPool.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.addon.exception.AddonLoadException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class AddonPool {
|
||||
private final Map<String, PreLoadAddon> pool = new HashMap<>();
|
||||
|
||||
public void add(PreLoadAddon addon) throws AddonLoadException {
|
||||
if(pool.containsKey(addon.getId()))
|
||||
throw new AddonLoadException("Duplicate addon ID: " + addon.getId());
|
||||
pool.put(addon.getId(), addon);
|
||||
}
|
||||
|
||||
public PreLoadAddon get(String id) {
|
||||
return pool.get(id);
|
||||
}
|
||||
|
||||
public void buildAll() throws AddonLoadException {
|
||||
for(PreLoadAddon value : pool.values()) {
|
||||
value.rebuildDependencies(this, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<PreLoadAddon> getAddons() {
|
||||
return new HashSet<>(pool.values());
|
||||
}
|
||||
}
|
||||
51
common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java
Normal file
51
common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.dfsek.terra.addon;
|
||||
|
||||
import com.dfsek.terra.addon.exception.AddonLoadException;
|
||||
import com.dfsek.terra.addon.exception.CircularDependencyException;
|
||||
import com.dfsek.terra.addon.exception.DependencyMissingException;
|
||||
import com.dfsek.terra.api.addons.TerraAddon;
|
||||
import com.dfsek.terra.api.addons.annotations.Addon;
|
||||
import com.dfsek.terra.api.addons.annotations.Depends;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PreLoadAddon {
|
||||
private final List<PreLoadAddon> depends = new ArrayList<>();
|
||||
private final Class<? extends TerraAddon> addonClass;
|
||||
private final String id;
|
||||
private final String[] dependencies;
|
||||
|
||||
public PreLoadAddon(Class<? extends TerraAddon> addonClass) {
|
||||
this.addonClass = addonClass;
|
||||
this.id = addonClass.getAnnotation(Addon.class).value();
|
||||
Depends depends = addonClass.getAnnotation(Depends.class);
|
||||
this.dependencies = depends == null ? new String[] {} : depends.value();
|
||||
}
|
||||
|
||||
public List<PreLoadAddon> getDepends() {
|
||||
return depends;
|
||||
}
|
||||
|
||||
public void rebuildDependencies(AddonPool pool, PreLoadAddon origin, boolean levelG1) throws AddonLoadException {
|
||||
if(this.equals(origin) && !levelG1)
|
||||
throw new CircularDependencyException("Detected circular dependency in addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies));
|
||||
|
||||
for(String dependency : dependencies) {
|
||||
PreLoadAddon preLoadAddon = pool.get(dependency);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Class<? extends TerraAddon> getAddonClass() {
|
||||
return addonClass;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class AddonLoadException extends Exception {
|
||||
private static final long serialVersionUID = -4949084729296580176L;
|
||||
|
||||
public AddonLoadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AddonLoadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class CircularDependencyException extends AddonLoadException {
|
||||
private static final long serialVersionUID = 7398510879124125121L;
|
||||
|
||||
public CircularDependencyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CircularDependencyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addon.exception;
|
||||
|
||||
public class DependencyMissingException extends AddonLoadException {
|
||||
private static final long serialVersionUID = -8419489102208521583L;
|
||||
|
||||
public DependencyMissingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyMissingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user