Stop using reflection, update to latest

This commit is contained in:
Matt Worzala 2021-05-20 22:26:35 -04:00
parent d871cb2c9c
commit 51409705e1
No known key found for this signature in database
GPG Key ID: 439DBBE092854841
3 changed files with 150 additions and 0 deletions

View File

@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URL;
import java.nio.file.Path;
import java.util.LinkedList;
import java.util.List;
@ -75,6 +76,8 @@ public final class DiscoveredExtension {
/** The original jar this is from. */
transient private File originalJar;
transient private Path dataDirectory;
/** The class loader that powers it. */
transient private MinestomExtensionClassLoader minestomExtensionClassLoader;
@ -130,6 +133,15 @@ public final class DiscoveredExtension {
return originalJar;
}
@NotNull
public Path getDataDirectory() {
return dataDirectory;
}
public void setDataDirectory(@NotNull Path dataDirectory) {
this.dataDirectory = dataDirectory;
}
MinestomExtensionClassLoader removeMinestomExtensionClassLoader() {
MinestomExtensionClassLoader oldClassLoader = getMinestomExtensionClassLoader();
setMinestomExtensionClassLoader(null);

View File

@ -1,11 +1,19 @@
package net.minestom.server.extensions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@ -77,6 +85,122 @@ public abstract class Extension {
return logger;
}
@NotNull
public Path getDataDirectory() {
return getOrigin().getDataDirectory();
}
/**
* Gets a resource from the extension directory, or from inside the jar if it does not
* exist in the extension directory.
* <p>
* If it does not exist in the extension directory, it will be copied from inside the jar.
* <p>
* The caller is responsible for closing the returned {@link InputStream}.
*
* @param fileName The file to read
* @return The file contents, or null if there was an issue reading the file.
*/
@Nullable
public InputStream getResource(@NotNull String fileName) {
return getResource(Paths.get(fileName));
}
/**
* Gets a resource from the extension directory, or from inside the jar if it does not
* exist in the extension directory.
* <p>
* If it does not exist in the extension directory, it will be copied from inside the jar.
* <p>
* The caller is responsible for closing the returned {@link InputStream}.
*
* @param target The file to read
* @return The file contents, or null if there was an issue reading the file.
*/
@Nullable
public InputStream getResource(@NotNull Path target) {
final Path targetFile = getDataDirectory().resolve(target);
try {
// Copy from jar if the file does not exist in the extension data directory.
if (!Files.exists(targetFile)) {
savePackagedResource(target);
}
return Files.newInputStream(targetFile);
} catch (IOException ex) {
getLogger().info("Failed to read resource {}.", target, ex);
return null;
}
}
/**
* Gets a resource from inside the extension jar.
* <p>
* The caller is responsible for closing the returned {@link InputStream}.
*
* @param fileName The file to read
* @return The file contents, or null if there was an issue reading the file.
*/
public InputStream getPackagedResource(@NotNull String fileName) {
return getPackagedResource(Paths.get(fileName));
}
/**
* Gets a resource from inside the extension jar.
* <p>
* The caller is responsible for closing the returned {@link InputStream}.
*
* @param target The file to read
* @return The file contents, or null if there was an issue reading the file.
*/
@Nullable
public InputStream getPackagedResource(@NotNull Path target) {
try {
final URL url = getOrigin().getMinestomExtensionClassLoader().getResource(target.toString());
if (url == null) {
getLogger().debug("Resource not found: {}", target);
return null;
}
return url.openConnection().getInputStream();
} catch (IOException ex) {
getLogger().debug("Failed to load resource {}.", target, ex);
return null;
}
}
/**
* Copies a resource file to the extension directory, replacing any existing copy.
*
* @param fileName The resource to save
* @return True if the resource was saved successfully, null otherwise
*/
public boolean savePackagedResource(@NotNull String fileName) {
return savePackagedResource(Paths.get(fileName));
}
/**
* Copies a resource file to the extension directory, replacing any existing copy.
*
* @param target The resource to save
* @return True if the resource was saved successfully, null otherwise
*/
public boolean savePackagedResource(@NotNull Path target) {
final Path targetFile = getDataDirectory().resolve(target);
try (InputStream is = getPackagedResource(target)) {
if (is == null) {
return false;
}
Files.createDirectories(targetFile.getParent());
Files.copy(is, targetFile, StandardCopyOption.REPLACE_EXISTING);
return true;
} catch (IOException ex) {
getLogger().debug("Failed to save resource {}.", target, ex);
return false;
}
}
/**
* Adds a new observer to this extension.
* Will be kept as a WeakReference.

View File

@ -24,6 +24,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipFile;
@ -44,6 +46,7 @@ public class ExtensionManager {
private final File extensionFolder = new File("extensions");
private final File dependenciesFolder = new File(extensionFolder, ".libs");
private Path extensionDataRoot = extensionFolder.toPath();
private boolean loaded;
// Option
@ -336,6 +339,7 @@ public class ExtensionManager {
DiscoveredExtension extension = GSON.fromJson(reader, DiscoveredExtension.class);
extension.files.add(new File(extensionClasses).toURI().toURL());
extension.files.add(new File(extensionResources).toURI().toURL());
extension.setDataDirectory(getExtensionDataRoot().resolve(extension.getName()));
// Verify integrity and ensure defaults
DiscoveredExtension.verifyIntegrity(extension);
@ -365,6 +369,7 @@ public class ExtensionManager {
DiscoveredExtension extension = GSON.fromJson(reader, DiscoveredExtension.class);
extension.setOriginalJar(file);
extension.files.add(file.toURI().toURL());
extension.setDataDirectory(getExtensionDataRoot().resolve(extension.getName()));
// Verify integrity and ensure defaults
DiscoveredExtension.verifyIntegrity(extension);
@ -569,6 +574,15 @@ public class ExtensionManager {
return extensionFolder;
}
@NotNull
public Path getExtensionDataRoot() {
return extensionDataRoot;
}
public void setExtensionDataRoot(@NotNull Path dataRoot) {
this.extensionDataRoot = dataRoot;
}
@NotNull
public Collection<Extension> getExtensions() {
return immutableExtensions.values();