diff --git a/common/addons/api-addon-loader b/common/addons/api-addon-loader index cf06b7966..960819639 160000 --- a/common/addons/api-addon-loader +++ b/common/addons/api-addon-loader @@ -1 +1 @@ -Subproject commit cf06b7966265d47a5b8edd43dff17070f802cb45 +Subproject commit 960819639fcda82b4911608b83f1cdc277f63234 diff --git a/common/addons/manifest-addon-loader b/common/addons/manifest-addon-loader index 8e161a721..f388c7b48 160000 --- a/common/addons/manifest-addon-loader +++ b/common/addons/manifest-addon-loader @@ -1 +1 @@ -Subproject commit 8e161a721cbfe3cc27ffc8301129b546e7334240 +Subproject commit f388c7b4864fa0f0b3e3c550081f234f9ce2df54 diff --git a/common/api/addons/build.gradle.kts b/common/api/addons/build.gradle.kts new file mode 100644 index 000000000..4936c5616 --- /dev/null +++ b/common/api/addons/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + "shadedApi"(project(":common:api:util")) +} diff --git a/common/api/addons/src/main/java/com/dfsek/terra/api/addon/AddonEntryPoint.java b/common/api/addons/src/main/java/com/dfsek/terra/api/addon/AddonEntryPoint.java new file mode 100644 index 000000000..cac5b0542 --- /dev/null +++ b/common/api/addons/src/main/java/com/dfsek/terra/api/addon/AddonEntryPoint.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.addon; + +import com.dfsek.terra.api.util.StringIdentifiable; + + +public interface AddonEntryPoint extends StringIdentifiable { +} diff --git a/common/api/addons/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddon.java b/common/api/addons/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddon.java new file mode 100644 index 000000000..ed207682e --- /dev/null +++ b/common/api/addons/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddon.java @@ -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 loadAddons(Path addonsFolder, ClassLoader parent); +} diff --git a/common/api/config/build.gradle.kts b/common/api/config/build.gradle.kts deleted file mode 100644 index 6466b8025..000000000 --- a/common/api/config/build.gradle.kts +++ /dev/null @@ -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") -} - diff --git a/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java b/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java index 859dfe498..ff072ad12 100644 --- a/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java +++ b/common/loader/addon/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java @@ -23,10 +23,6 @@ public class AddonClassLoader extends URLClassLoader { super(urls, parent); } - public AddonClassLoader(URL[] urls) { - super(urls); - } - @SuppressWarnings("unchecked") public static Set> fetchAddonClasses(File file, ClassLoader parent) throws IOException { JarFile jarFile = new JarFile(file); diff --git a/common/loader/addon/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java b/common/loader/addon/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java new file mode 100644 index 000000000..e9f7115a7 --- /dev/null +++ b/common/loader/addon/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java @@ -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 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"; + } +} diff --git a/common/loader/addon/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java b/common/loader/addon/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java index cd347ea0b..45feaa36c 100644 --- a/common/loader/addon/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java +++ b/common/loader/addon/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java @@ -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) {