Don't catch and log exceptions in DependencyLoader

This way whatever uses the DependencyLoader actually knows if something fails and can react to it
instead of just the JVM erroring because something is unexpectedly missing in the class path
This commit is contained in:
Christian Koop 2024-02-02 18:26:21 +01:00
parent c027ab8b4c
commit 193af915e9
No known key found for this signature in database
GPG Key ID: 89A8181384E010A3
2 changed files with 45 additions and 46 deletions

View File

@ -113,6 +113,6 @@ public final class PluginInfo {
} }
public int getDependencyVersion() { public int getDependencyVersion() {
return DependencyLoader.DEPENDENCY_VERSION; return DependencyLoader.getDependencyVersion();
} }
} }

View File

@ -3,10 +3,11 @@ package com.craftaro.core.dependency;
import com.craftaro.core.CraftaroCoreConstants; import com.craftaro.core.CraftaroCoreConstants;
import com.craftaro.core.SongodaCore; import com.craftaro.core.SongodaCore;
import com.georgev22.api.libraryloader.LibraryLoader; import com.georgev22.api.libraryloader.LibraryLoader;
import com.georgev22.api.libraryloader.exceptions.InvalidDependencyException;
import com.georgev22.api.libraryloader.exceptions.UnknownDependencyException;
import me.lucko.jarrelocator.JarRelocator; import me.lucko.jarrelocator.JarRelocator;
import me.lucko.jarrelocator.Relocation; import me.lucko.jarrelocator.Relocation;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.ApiStatus;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -15,15 +16,14 @@ import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
public class DependencyLoader { public class DependencyLoader {
@ApiStatus.Internal private static final int DEPENDENCY_VERSION = 1;
public static final int DEPENDENCY_VERSION = 1;
private final LibraryLoader libraryLoader; private final LibraryLoader libraryLoader;
@ -35,13 +35,13 @@ public class DependencyLoader {
); );
} }
public void loadDependencies(Set<Dependency> dependencies) { public void loadDependencies(Collection<Dependency> dependencies) throws IOException {
for (Dependency dependency : dependencies) { for (Dependency dependency : dependencies) {
loadDependency(dependency); loadDependency(dependency);
} }
} }
public void loadDependency(Dependency dependency) { public void loadDependency(Dependency dependency) throws IOException {
String repositoryUrl = dependency.getRepositoryUrl(); String repositoryUrl = dependency.getRepositoryUrl();
String groupId = dependency.getGroupId(); String groupId = dependency.getGroupId();
String artifactId = dependency.getArtifactId(); String artifactId = dependency.getArtifactId();
@ -63,44 +63,40 @@ public class DependencyLoader {
return; return;
} }
try { SongodaCore.getLogger().info("Downloading dependency " + groupId + ":" + artifactId + ":" + version + " from " + repositoryUrl);
SongodaCore.getLogger().info("Downloading dependency " + groupId + ":" + artifactId + ":" + version + " from " + repositoryUrl); // Construct the URL for the artifact in the Maven repository
// Construct the URL for the artifact in the Maven repository String artifactUrl = repositoryUrl + "/" +
String artifactUrl = repositoryUrl + "/" + groupId.replace('.', '/') + "/" +
groupId.replace('.', '/') + "/" + artifactId + "/" +
artifactId + "/" + version + "/" +
version + "/" + artifactId + "-" + version + ".jar";
artifactId + "-" + version + ".jar";
URL url = new URL(artifactUrl); URL url = new URL(artifactUrl);
URLConnection connection = url.openConnection(); URLConnection connection = url.openConnection();
InputStream in = connection.getInputStream(); InputStream in = connection.getInputStream();
// Define the output file // Define the output file
outputFile.getParentFile().mkdirs(); outputFile.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(outputFile); FileOutputStream out = new FileOutputStream(outputFile);
// Read from the input stream and write to the output stream // Read from the input stream and write to the output stream
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int length; int length;
while ((length = in.read(buffer)) != -1) { while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length); out.write(buffer, 0, length);
}
// Close both streams
in.close();
out.close();
//Load dependency into the classpath
SongodaCore.getLogger().info("Downloaded dependency " + groupId + ":" + artifactId + ":" + version);
loadJarIntoClasspath(outputFile, dependency);
} catch (Exception e) {
e.printStackTrace();
} }
// Close both streams
in.close();
out.close();
//Load dependency into the classpath
SongodaCore.getLogger().info("Downloaded dependency " + groupId + ":" + artifactId + ":" + version);
loadJarIntoClasspath(outputFile, dependency);
} }
public void loadJarIntoClasspath(File file, Dependency dependency) { public void loadJarIntoClasspath(File file, Dependency dependency) throws IOException {
if (!isRelocated(file) && dependency.shouldRelocate()) { if (!isRelocated(file) && dependency.shouldRelocate()) {
SongodaCore.getLogger().info("Loading dependency for relocation " + file); SongodaCore.getLogger().info("Loading dependency for relocation " + file);
//relocate package to com.craftaro.core.third_party to avoid conflicts //relocate package to com.craftaro.core.third_party to avoid conflicts
@ -123,21 +119,24 @@ public class DependencyLoader {
if (e.getMessage().contains("zip file is empty")) { if (e.getMessage().contains("zip file is empty")) {
SongodaCore.getLogger().severe("Try deleting the 'server root/craftaro' folder and restarting the server"); SongodaCore.getLogger().severe("Try deleting the 'server root/craftaro' folder and restarting the server");
} }
e.printStackTrace();
//Delete the new jar cuz it's probably corrupted //Delete the new jar cuz it's probably corrupted
finalJar.delete(); finalJar.delete();
throw e;
} }
} }
try { try {
this.libraryLoader.load(new LibraryLoader.Dependency(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getRepositoryUrl()), true); this.libraryLoader.load(new LibraryLoader.Dependency(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getRepositoryUrl()), true);
} catch (Exception ignored) { } catch (InvalidDependencyException ignored) {
//already loaded //already loaded
} catch (UnknownDependencyException ex) {
throw new RuntimeException(ex);
} }
SongodaCore.getLogger().info("----------------------------"); SongodaCore.getLogger().info("----------------------------");
} }
private boolean isRelocated(File file) { private boolean isRelocated(File file) throws IOException {
try (ZipFile zipFile = new ZipFile(file)) { try (ZipFile zipFile = new ZipFile(file)) {
Enumeration<? extends ZipEntry> entries = zipFile.entries(); Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
@ -147,13 +146,11 @@ public class DependencyLoader {
return true; return true;
} }
} }
} catch (IOException e) {
e.printStackTrace();
} }
return false; return false;
} }
private boolean isLoaded(File file) { private boolean isLoaded(File file) throws IOException {
//Find the first class file in the jar and try Class.forName //Find the first class file in the jar and try Class.forName
try (ZipFile zipFile = new ZipFile(file)) { try (ZipFile zipFile = new ZipFile(file)) {
Enumeration<? extends ZipEntry> entries = zipFile.entries(); Enumeration<? extends ZipEntry> entries = zipFile.entries();
@ -173,9 +170,11 @@ public class DependencyLoader {
} }
} }
} }
} catch (Exception e) {
e.printStackTrace();
} }
return false; return false;
} }
public static int getDependencyVersion() {
return DEPENDENCY_VERSION;
}
} }