work on addon bootstrapping

This commit is contained in:
dfsek
2021-11-15 18:23:23 -07:00
parent ec17781f4a
commit 9d2b354a33
9 changed files with 87 additions and 17 deletions

View File

@@ -0,0 +1,3 @@
dependencies {
"shadedApi"(project(":common:api:util"))
}

View File

@@ -0,0 +1,7 @@
package com.dfsek.terra.api.addon;
import com.dfsek.terra.api.util.StringIdentifiable;
public interface AddonEntryPoint extends StringIdentifiable {
}

View File

@@ -0,0 +1,16 @@
package com.dfsek.terra.api.addon.bootstrap;
import com.dfsek.terra.api.addon.AddonEntryPoint;
import java.nio.file.Path;
public interface BootstrapAddon extends AddonEntryPoint {
/**
* Load all the relevant addons in the specified path.
* @param addonsFolder Path containing addons.
* @param parent
* @return Loaded addons
*/
Iterable<AddonEntryPoint> loadAddons(Path addonsFolder, ClassLoader parent);
}

View File

@@ -1,10 +0,0 @@
dependencies {
"shadedApi"(project(":common:api:core"))
"shadedApi"("com.dfsek:Paralithic:0.5.0")
"shadedApi"("com.dfsek.tectonic:common:2.1.2")
"shadedApi"("net.jafama:jafama:2.3.2")
}

View File

@@ -23,10 +23,6 @@ public class AddonClassLoader extends URLClassLoader {
super(urls, parent);
}
public AddonClassLoader(URL[] urls) {
super(urls);
}
@SuppressWarnings("unchecked")
public static Set<Class<? extends TerraAddon>> fetchAddonClasses(File file, ClassLoader parent) throws IOException {
JarFile jarFile = new JarFile(file);

View File

@@ -0,0 +1,58 @@
package com.dfsek.terra.addon;
import com.dfsek.terra.addon.exception.AddonLoadException;
import com.dfsek.terra.api.addon.AddonEntryPoint;
import com.dfsek.terra.api.addon.bootstrap.BootstrapAddon;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
public class BootstrapAddonLoader implements BootstrapAddon {
@Override
public Iterable<AddonEntryPoint> loadAddons(Path addonsFolder, ClassLoader parent) {
Path bootstrapAddons = addonsFolder.resolve("bootstrap");
try {
return Files.walk(bootstrapAddons, 1)
.filter(path -> path.toFile().isFile() && path.getFileName().endsWith(".jar"))
.map(path -> {
try {
JarFile jar = new JarFile(path.toFile());
String entry = jar.getManifest().getMainAttributes().getValue("Bootstrap-Addon-Entry-Point");
AddonClassLoader loader = new AddonClassLoader(new URL[] {path.toUri().toURL()}, parent);
try {
Object in = loader.loadClass(entry).getConstructor().newInstance();
if(!(in instanceof AddonEntryPoint)) {
throw new AddonLoadException(in.getClass() + " does not extend " + AddonEntryPoint.class);
}
return (AddonEntryPoint) in;
} catch(InvocationTargetException e) {
throw new AddonLoadException("Exception occurred while instantiating addon: ", e);
} catch(NoSuchMethodException | IllegalAccessException | InstantiationException e) {
throw new AddonLoadException("No valid default constructor found in entry point " + entry);
} catch(ClassNotFoundException e) {
throw new AddonLoadException("Entry point " + entry + " not found in JAR.");
}
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}).collect(Collectors.toList());
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public String getID() {
return "BOOTSTRAP";
}
}

View File

@@ -1,6 +1,6 @@
package com.dfsek.terra.addon.exception;
public class AddonLoadException extends Exception {
public class AddonLoadException extends RuntimeException {
private static final long serialVersionUID = -4949084729296580176L;
public AddonLoadException(String message) {