diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java new file mode 100644 index 000000000..ba68e0434 --- /dev/null +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addon.loader; + +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.api.addon.BaseAddon; + + +public class ApiAddon implements BaseAddon { + private final Version version; + private final String id; + + public ApiAddon(Version version, String id) { + this.version = version; + this.id = id; + } + + @Override + public Version getVersion() { + return version; + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java new file mode 100644 index 000000000..2bcfb9236 --- /dev/null +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addon.loader; + +import java.net.URL; +import java.net.URLClassLoader; + + +public class ApiAddonClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + public ApiAddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } +} diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java index f6f3317fc..b8350c778 100644 --- a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java @@ -14,6 +14,7 @@ import java.nio.file.Path; import java.util.Collections; import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon; @@ -21,7 +22,8 @@ public class ApiAddonLoader implements BootstrapBaseAddon { private static final Version VERSION = Versions.getVersion(1, 0, 0); @Override - public Iterable loadAddons(Path addonsFolder, ClassLoader parent) { + public Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { + return Collections.emptySet(); } diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java index 50731763b..60ad9451b 100644 --- a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java @@ -13,6 +13,9 @@ import ca.solostudios.strata.version.VersionRange; import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.yaml.YamlConfiguration; + +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,13 +75,9 @@ public class ManifestAddonLoader implements BootstrapBaseAddon { throw new AddonException("Addon " + manifest.getID() + " has unknown schema version: " + manifest.getSchemaVersion()); } - @SuppressWarnings({ "IOResourceOpenedButNotSafelyClosed", "resource" }) - ManifestAddonClassLoader childLoader = new ManifestAddonClassLoader(new URL[]{ addonPath.toUri().toURL() }, - loader); - List initializers = manifest.getEntryPoints().stream().map(entryPoint -> { try { - Object in = childLoader.loadClass(entryPoint).getConstructor().newInstance(); + Object in = loader.loadClass(entryPoint).getConstructor().newInstance(); if(!(in instanceof AddonInitializer)) { throw new AddonException(in.getClass() + " does not extend " + AddonInitializer.class); } @@ -103,7 +102,7 @@ public class ManifestAddonLoader implements BootstrapBaseAddon { } @Override - public Iterable loadAddons(Path addonsFolder, ClassLoader parent) { + public Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { logger.debug("Loading addons..."); try(Stream files = Files.walk(addonsFolder, 1, FileVisitOption.FOLLOW_LINKS)) { @@ -114,16 +113,16 @@ public class ManifestAddonLoader implements BootstrapBaseAddon { .filter(path -> path.toString().endsWith(".jar")) .toList(); - ManifestAddonClassLoader loader = new ManifestAddonClassLoader(addons.stream().map(path -> { + addons.stream().map(path -> { try { return path.toUri().toURL(); } catch(MalformedURLException e) { throw new UncheckedIOException(e); } - }).toArray(URL[]::new), getClass().getClassLoader()); + }).forEach(parent::addURL); return addons.stream() - .map(jar -> loadAddon(jar, loader)) + .map(jar -> loadAddon(jar, parent)) .collect(Collectors.toList()); } catch(IOException e) { throw new UncheckedIOException(e); diff --git a/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java new file mode 100644 index 000000000..b6b3a67ae --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.addon.bootstrap; + +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLStreamHandlerFactory; + + +public class BootstrapAddonClassLoader extends URLClassLoader { + public BootstrapAddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public BootstrapAddonClassLoader(URL[] urls) { + super(urls); + } + + public BootstrapAddonClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { + super(urls, parent, factory); + } + + public BootstrapAddonClassLoader(String name, URL[] urls, ClassLoader parent) { + super(name, urls, parent); + } + + public BootstrapAddonClassLoader(String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { + super(name, urls, parent, factory); + } + + @Override + public void addURL(URL url) { + super.addURL(url); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java index a71506a39..f8f58c3f3 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java +++ b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java @@ -32,5 +32,5 @@ public interface BootstrapBaseAddon extends BaseAddon { * * @return Loaded addons */ - Iterable loadAddons(Path addonsFolder, ClassLoader parent); + Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent); } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index 3241f565a..654470349 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -18,6 +18,9 @@ package com.dfsek.terra; import com.dfsek.tectonic.api.TypeRegistry; + +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.NotNull; @@ -31,6 +34,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; @@ -162,12 +166,14 @@ public abstract class AbstractPlatform implements Platform { Injector platformInjector = new InjectorImpl<>(this); platformInjector.addExplicitTarget(Platform.class); + + BootstrapAddonClassLoader bootstrapAddonClassLoader = new BootstrapAddonClassLoader(new URL[] {}, getClass().getClassLoader()); - bootstrapAddonLoader.loadAddons(addonsFolder, getClass().getClassLoader()) + bootstrapAddonLoader.loadAddons(addonsFolder, bootstrapAddonClassLoader) .forEach(bootstrapAddon -> { platformInjector.inject(bootstrapAddon); - bootstrapAddon.loadAddons(addonsFolder, getClass().getClassLoader()) + bootstrapAddon.loadAddons(addonsFolder, bootstrapAddonClassLoader) .forEach(addonList::add); }); diff --git a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java index 15d0199cc..0b53203a1 100644 --- a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java +++ b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java @@ -19,6 +19,7 @@ package com.dfsek.terra.addon; import ca.solostudios.strata.Versions; import ca.solostudios.strata.version.Version; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,7 +82,7 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon> loadAddons(Path addonsFolder, ClassLoader parent) { + public Iterable> loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { Path bootstrapFolder = addonsFolder.resolve("bootstrap"); logger.debug("Loading bootstrap addons from {}", bootstrapFolder);