manifest addon loading

This commit is contained in:
dfsek
2021-11-16 10:11:44 -07:00
parent 06d09bc422
commit e3b00d45ec
6 changed files with 112 additions and 3 deletions

View File

@@ -1,2 +1,4 @@
dependencies {
"shadedApi"("commons-io:commons-io:2.6")
"shadedImplementation"("com.dfsek.tectonic:yaml:2.1.2")
}

View File

@@ -0,0 +1,15 @@
package com.dfsek.terra.addons.manifest.impl;
import java.net.URL;
import java.net.URLClassLoader;
public class ManifestAddonClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
public ManifestAddonClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
}

View File

@@ -2,14 +2,27 @@ package com.dfsek.terra.addons.manifest.impl;
import ca.solostudios.strata.version.Version;
import ca.solostudios.strata.version.VersionRange;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.yaml.YamlConfiguration;
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.Collections;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import com.dfsek.terra.addons.manifest.impl.config.AddonManifest;
import com.dfsek.terra.addons.manifest.impl.config.WebsiteConfig;
import com.dfsek.terra.addons.manifest.impl.config.loaders.VersionLoader;
import com.dfsek.terra.addons.manifest.impl.config.loaders.VersionRangeLoader;
import com.dfsek.terra.addons.manifest.impl.exception.AddonException;
import com.dfsek.terra.addons.manifest.impl.exception.ManifestException;
import com.dfsek.terra.addons.manifest.impl.exception.ManifestNotPresentException;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon;
@@ -20,8 +33,54 @@ public class ManifestAddonLoader implements BootstrapBaseAddon {
ConfigLoader manifestLoader = new ConfigLoader();
manifestLoader.registerLoader(Version.class, new VersionLoader())
.registerLoader(VersionRange.class, new VersionRangeLoader())
.registerLoader(WebsiteConfig.class, WebsiteConfig::new);
return Collections.emptySet();
.registerLoader(WebsiteConfig.class, WebsiteConfig::new);
try {
return Files.walk(addonsFolder, 1)
.filter(path -> path.toFile().isFile() && path.getFileName().endsWith(".jar"))
.flatMap(path -> {
try {
JarFile jar = new JarFile(path.toFile());
JarEntry manifestEntry = jar.getJarEntry("terra.addon.yml");
if(manifestEntry == null) {
throw new ManifestNotPresentException("Addon " + path + " does not contain addon manifest.");
}
try {
AddonManifest manifest = manifestLoader.load(new AddonManifest(),
new YamlConfiguration(jar.getInputStream(manifestEntry),
"terra.addon.yml"));
ManifestAddonClassLoader loader = new ManifestAddonClassLoader(new URL[]{ path.toUri().toURL() },
parent);
return manifest.getEntryPoints().stream().map(entryPoint -> {
try {
Object in = loader.loadClass(entryPoint).getConstructor().newInstance();
if(!(in instanceof BaseAddon)) {
throw new AddonException(in.getClass() + " does not extend " + BaseAddon.class);
}
return (BaseAddon) in;
} catch(InvocationTargetException e) {
throw new AddonException("Exception occurred while instantiating addon: ", e);
} catch(NoSuchMethodException | IllegalAccessException | InstantiationException e) {
throw new AddonException("No valid default constructor found in entry point " + entryPoint);
} catch(ClassNotFoundException e) {
throw new AddonException("Entry point " + entryPoint + " not found in JAR.");
}
});
} catch(LoadException e) {
throw new ManifestException("Failed to load addon manifest", e);
}
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}).collect(Collectors.toList());
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}
@Override

View File

@@ -0,0 +1,11 @@
package com.dfsek.terra.addons.manifest.impl.exception;
public class AddonException extends RuntimeException {
public AddonException(String message) {
super(message);
}
public AddonException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,11 @@
package com.dfsek.terra.addons.manifest.impl.exception;
public class ManifestException extends AddonException{
public ManifestException(String message) {
super(message);
}
public ManifestException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,11 @@
package com.dfsek.terra.addons.manifest.impl.exception;
public class ManifestNotPresentException extends ManifestException{
public ManifestNotPresentException(String message) {
super(message);
}
public ManifestNotPresentException(String message, Throwable cause) {
super(message, cause);
}
}