Skip to content

Commit

Permalink
Improve logging of JavaProcess & add exception for duplicate plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
serivesmejia committed Oct 26, 2024
1 parent cbbb8c4 commit 3f2c71b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,59 @@

package com.github.serivesmejia.eocvsim.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

/**
* A utility class for executing a Java process to run a main class within this project.
*/
public final class JavaProcess {

public interface ProcessIOReceiver {
void receive(InputStream in, InputStream err);
void receive(InputStream in, InputStream err, int pid);
}

public static class SLF4JIOReceiver implements JavaProcess.ProcessIOReceiver {

private final Logger logger;

public SLF4JIOReceiver(Logger logger) {
this.logger = logger;
}

@Override
public void receive(InputStream out, InputStream err, int pid) {
new Thread(() -> {
Scanner sc = new Scanner(out);
while (sc.hasNextLine()) {
logger.info(sc.nextLine());
}
}, "SLFJ4IOReceiver-out-" + pid).start();

new Thread(() -> {
Scanner sc = new Scanner(err);
while (sc.hasNextLine()) {
logger.error(sc.nextLine());
}
}, "SLF4JIOReceiver-err-" + pid).start();
}

}


private JavaProcess() {}

private static int count;

private static final Logger logger = LoggerFactory.getLogger(JavaProcess.class);

/**
* Executes a Java process with the given class and arguments.
* @param klass the class to execute
Expand Down Expand Up @@ -71,20 +107,28 @@ public static int execClasspath(Class klass, ProcessIOReceiver ioReceiver, Strin
command.addAll(args);
}

System.out.println("Executing command: " + command);
int processCount = count;

logger.info("Executing Java process #{} at \"{}\", main class \"{}\", JVM args \"{}\" and args \"{}\"", processCount, javaBin, className, jvmArgs, args);

count++;

ProcessBuilder builder = new ProcessBuilder(command);

if (ioReceiver != null) {
Process process = builder.start();
ioReceiver.receive(process.getInputStream(), process.getErrorStream());
logger.info("Started #{} with PID {}, inheriting IO to {}", processCount, process.pid(), ioReceiver.getClass().getSimpleName());

ioReceiver.receive(process.getInputStream(), process.getErrorStream(), (int) process.pid());
killOnExit(process);

process.waitFor();
return process.exitValue();
} else {
builder.inheritIO();
Process process = builder.start();
logger.info("Started ${} with PID {}, IO will be inherited to System.out and System.err", processCount, process.pid());

killOnExit(process);

process.waitFor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class PluginLoader(
/**
* Whether the plugin has super access (full system access)
*/
val hasSuperAccess get() = eocvSim.config.superAccessPluginHashes.contains(pluginHash)
val hasSuperAccess get() = eocvSim.config.superAccessPluginHashes.contains(pluginFileHash)

init {
pluginClassLoader = PluginClassLoader(pluginFile, classpath) {
Expand All @@ -103,12 +103,11 @@ class PluginLoader(
}

/**
* Load the plugin from the jar file
* @throws InvalidPluginException if the plugin.toml file is not found
* @throws UnsupportedPluginException if the plugin requests an api version higher than the current one
* Fetch the plugin info from the plugin.toml file
* Fills the pluginName, pluginVersion, pluginAuthor and pluginAuthorEmail fields
*/
fun load() {
if(loaded) return
fun fetchInfoFromToml() {
if(::pluginToml.isInitialized) return

pluginToml = Toml().read(pluginClassLoader.getResourceAsStream("plugin.toml")
?: throw InvalidPluginException("No plugin.toml in the jar file")
Expand All @@ -119,8 +118,19 @@ class PluginLoader(

pluginAuthor = pluginToml.getString("author") ?: throw InvalidPluginException("No author in plugin.toml")
pluginAuthorEmail = pluginToml.getString("author-email", "")
}

/**
* Load the plugin from the jar file
* @throws InvalidPluginException if the plugin.toml file is not found
* @throws UnsupportedPluginException if the plugin requests an api version higher than the current one
*/
fun load() {
if(loaded) return

fetchInfoFromToml()

logger.info("Loading plugin $pluginName v$pluginVersion by $pluginAuthor")
logger.info("Loading plugin $pluginName v$pluginVersion by $pluginAuthor from ${pluginSource.name}")

setupFs()

Expand Down Expand Up @@ -216,7 +226,7 @@ class PluginLoader(
* Get the hash of the plugin file based off the file contents
* @return the hash
*/
val pluginHash by lazy {
val pluginFileHash by lazy {
val messageDigest = MessageDigest.getInstance("SHA-256")
messageDigest.update(pluginFile.readBytes())
SysUtil.byteArray2Hex(messageDigest.digest())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class PluginManager(val eocvSim: EOCVSim) {

val logger by loggerForThis()

private val _loadedPluginHashes = mutableListOf<String>()
val loadedPluginHashes get() = _loadedPluginHashes.toList()

val repositoryManager = PluginRepositoryManager()

private val _pluginFiles = mutableListOf<File>()
Expand Down Expand Up @@ -91,7 +94,7 @@ class PluginManager(val eocvSim: EOCVSim) {
for (pluginFile in pluginFiles) {
loaders[pluginFile] = PluginLoader(
pluginFile,
repositoryManager.classpath(),
repositoryManager.resolvedFiles,
if(pluginFile in repositoryManager.resolvedFiles)
PluginSource.REPOSITORY else PluginSource.FILE,
eocvSim
Expand All @@ -108,7 +111,16 @@ class PluginManager(val eocvSim: EOCVSim) {
fun loadPlugins() {
for ((file, loader) in loaders) {
try {
loader.fetchInfoFromToml()

val hash = loader.hash()

if(hash in _loadedPluginHashes) {
throw IllegalStateException("Plugin ${loader.pluginName} by ${loader.pluginAuthor} is already loaded. Please delete the duplicate from the plugins folder or from repository.toml !")
}

loader.load()
_loadedPluginHashes.add(hash)
} catch (e: Throwable) {
logger.error("Failure loading ${file.name}", e)
loaders.remove(file)
Expand Down Expand Up @@ -176,7 +188,7 @@ class PluginManager(val eocvSim: EOCVSim) {
val name = "${loader.pluginName} by ${loader.pluginAuthor}".replace(" ", "-")

if(JavaProcess.exec(SuperAccessRequestMain::class.java, null, Arrays.asList(name, warning)) == 171) {
eocvSim.config.superAccessPluginHashes.add(loader.pluginHash)
eocvSim.config.superAccessPluginHashes.add(loader.pluginFileHash)
eocvSim.configManager.saveToFile()
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ class PluginRepositoryManager {
val REPOSITORY_FILE = PluginManager.PLUGIN_FOLDER + File.separator + "repository.toml"
val CACHE_FILE = PluginManager.PLUGIN_FOLDER + File.separator + "cache.toml"

val MAVEN_FOLDER = PluginManager.PLUGIN_FOLDER + File.separator + "maven"

val REPOSITORY_TOML_RES = PluginRepositoryManager::class.java.getResourceAsStream("/repository.toml")
val CACHE_TOML_RES = PluginRepositoryManager::class.java.getResourceAsStream("/cache.toml")

Expand All @@ -66,8 +64,6 @@ class PluginRepositoryManager {
SysUtil.copyFileIs(CACHE_TOML_RES, CACHE_FILE, false)
cacheToml = Toml().read(CACHE_FILE)

MAVEN_FOLDER.mkdir()

SysUtil.copyFileIs(REPOSITORY_TOML_RES, REPOSITORY_FILE, false)
pluginsToml = Toml().read(REPOSITORY_FILE)

Expand Down Expand Up @@ -130,14 +126,10 @@ class PluginRepositoryManager {
if(pluginJar == null) {
// the first file is the plugin jar
pluginJar = file
newCache[pluginDep.hexString] = pluginJar!!.absolutePath
}

val destFile = File(MAVEN_FOLDER, file.name)
file.copyTo(destFile, true)

_resolvedFiles += destFile

newCache[pluginDep.hexString] = pluginJar!!.absolutePath
_resolvedFiles += file
}

files += pluginJar!!
Expand All @@ -156,18 +148,6 @@ class PluginRepositoryManager {

return files
}

fun classpath(): List<File> {
val files = mutableListOf<File>()

for(jar in MAVEN_FOLDER.listFiles() ?: arrayOf()) {
if(jar.extension == "jar") {
files += jar
}
}

return files
}
}


Expand Down

0 comments on commit 3f2c71b

Please sign in to comment.