Skip to content

Commit

Permalink
Merge pull request #4 from TheProgramSrc/fix/modules-class-not-found
Browse files Browse the repository at this point in the history
* Added update system like update folder in bukkit servers
* Fixed modules not being loaded (Class Not Found Exception)
* Fixed Null Pointer Exception when abruptly disabling the api
* Improvements to the module load order
* Fixes to issue templates
  • Loading branch information
Im-Fran authored Dec 17, 2021
2 parents f2e635d + 1f5ea15 commit 40a06db
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: TheProgramSrc
assignees: Im-Fran

---

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Feature request
about: Suggest an idea for this project
title: "[FEATURE REQUEST]"
labels: enhancement
assignees: TheProgramSrc
assignees: Im-Fran

---

Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## v0.1.6 - Snapshot
* Added update system like update folder in bukkit servers
* Fixed modules not being loaded (Class Not Found Exception)
* Fixed Null Pointer Exception when abruptly disabling the api
* Improvements to the module load order
* Fixes to issue templates

## v0.1.4 - Snapshot / v0.1.5 - Snapshot
* Fixed build script not working
* Implemented custom actions

## v0.1.3 - Snapshot
* Added ability to re-deploy a version by specifying it in the environment variable `VERSION`
* Add a way to let know the user the current commit hash of the running release.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class BungeeLoader: Plugin() {
}

override fun onDisable() {
SimpleCoreAPI.instance.moduleManager.disableModules()
SimpleCoreAPI.instance.moduleManager?.disableModules()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SimpleCoreAPI(logger: Logger) {
* The Module Manager
* @return The {@link ModuleManager}
*/
val moduleManager: ModuleManager
val moduleManager: ModuleManager?

/**
* SimpleCoreAPI Properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ object ModuleHelper {
}
if(!sorted.contains(moduleName)) sorted.add(moduleName)
}
return sorted
return sorted.filter { it.isNotBlank() && it.isNotEmpty() }
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
package xyz.theprogramsrc.simplecoreapi.global.module

import xyz.theprogramsrc.simplecoreapi.global.exceptions.*
import xyz.theprogramsrc.simplecoreapi.global.exceptions.InvalidModuleDescriptionException
import xyz.theprogramsrc.simplecoreapi.global.exceptions.InvalidModuleException
import xyz.theprogramsrc.simplecoreapi.global.exceptions.ModuleDownloadException
import xyz.theprogramsrc.simplecoreapi.global.exceptions.ModuleLoadException
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.net.URLClassLoader
import java.nio.file.Files
import java.util.*
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarInputStream
import java.util.logging.Logger
import java.util.zip.ZipEntry


class ModuleManager(private val logger: Logger) {

private var modulesFolder = File("plugins/SimpleCoreAPI/modules")
private val modulesFolder = File("plugins/SimpleCoreAPI/modules")
private val updatesFolder = File("plugins/SimpleCoreAPI/update")
private var loadedModules = mutableMapOf<String, Module>()

init {
if (!modulesFolder.exists()) modulesFolder.mkdirs()
if (!updatesFolder.exists()) updatesFolder.mkdirs()
}

companion object {
Expand Down Expand Up @@ -47,7 +53,10 @@ class ModuleManager(private val logger: Logger) {
val dependencies = mutableListOf<String>()
val loadedModules = mutableSetOf<String>()

// First we load and save all the module descriptions from the avialable modules
// First we update the module jars
updateJars()

// Now we load and save all the module descriptions from the available modules
files.forEach { file ->
try {
// Validate that this file is a module
Expand Down Expand Up @@ -114,11 +123,12 @@ class ModuleManager(private val logger: Logger) {
moduleDependencies[it.key] = it.value.second.dependencies.toList()
}

ModuleHelper.sortModuleDependencies(moduleDependencies).forEach {
if(!loadedModules.contains(it)){
val pair = modules[it]!!
if(loadIntoClasspath(pair.first, pair.second)){
loadedModules.add(it)
ModuleHelper.sortModuleDependencies(moduleDependencies).forEach { moduleName ->
if(!loadedModules.contains(moduleName) && modules.containsKey(moduleName)) {
modules[moduleName]?.let { pair ->
if(loadIntoClasspath(pair.first, pair.second)){
loadedModules.add(moduleName)
}
}
}
}
Expand All @@ -134,22 +144,23 @@ class ModuleManager(private val logger: Logger) {
*/
@Throws(InvalidModuleException::class, ModuleLoadException::class)
private fun loadIntoClasspath(file: File, description: ModuleDescription): Boolean {
var entry: JarEntry
var entry: ZipEntry?
try {
URLClassLoader(arrayOf(file.toURI().toURL()), this.javaClass.classLoader).use { loader ->
FileInputStream(file).use { fileInputStream ->
JarInputStream(fileInputStream).use { jarInputStream ->
while (jarInputStream.nextJarEntry.also { entry = it } != null) {
if (entry.name.endsWith(".class")) {
val name = entry.name.replace("/", ".").replace(".class", "")
val clazz = loader.loadClass(name)
while (jarInputStream.nextEntry.also { entry = it } != null) {
val entryName = entry?.name ?: continue
if (entryName.endsWith(".class")) {
val name = entryName.replace("/", ".").replace(".class", "")
val clazz = Class.forName(name, true, loader)
if (name == description.mainClass) {
if (!Module::class.java.isAssignableFrom(clazz)) {
throw InvalidModuleException("The class ${description.mainClass} must be extended to the Module class!")
}
return try {
logger.info("Loading module ${description.name} v${description.version}")
val moduleClass = Class.forName(description.mainClass).asSubclass(Module::class.java)
val moduleClass = clazz.asSubclass(Module::class.java)
val module = moduleClass.getConstructor().newInstance()
module.init(file, description)
module.onEnable()
Expand Down Expand Up @@ -202,4 +213,16 @@ class ModuleManager(private val logger: Logger) {
loadedModules.clear()
System.gc()
}

/**
* Updates all the jars placed under the update/ folder
*/
private fun updateJars(){
updatesFolder.listFiles()?.filter { it.name.endsWith(".jar") }?.filter { loadDescription(it) != null }?.forEach {
val name = loadDescription(it)?.getProperty("name") ?: return@forEach
val outdatedFile = modulesFolder.listFiles()?.filter { it.name.endsWith(".jar") }?.firstOrNull { loadDescription(it)?.getProperty("name")?.equals(name) ?: false }?.toPath() ?: return@forEach
Files.deleteIfExists(outdatedFile)
Files.move(it.toPath(), outdatedFile)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SpigotLoader: JavaPlugin() {
}

override fun onDisable() {
SimpleCoreAPI.instance.moduleManager.disableModules()
SimpleCoreAPI.instance.moduleManager?.disableModules()
}

}

0 comments on commit 40a06db

Please sign in to comment.