Skip to content

Commit

Permalink
* Use BungeeCord's library loading feature
Browse files Browse the repository at this point in the history
* Implement temporary transitive dependency workaround
* Update README
  • Loading branch information
Luluno01 committed Jul 28, 2021
1 parent 82cf995 commit 2bcd701
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 13 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A blacklist and whitelist BungeeCord plugin with support of UUID look up.

This plugin was formerly named BungeeGuard. In order not to conflict with the existing plugin BungeeGuard, this plugin is renamed to BungeeSafeguard from v2.0.

Tested on Waterfall, version: `git:Waterfall-Bootstrap:1.17-R0.1-SNAPSHOT:436f47f:437`.
Tested on Waterfall, version: `git:Waterfall-Bootstrap:1.17-R0.1-SNAPSHOT:93773f9:448`.

- [BungeeSafeguard](#bungeesafeguard)
- [Features](#features)
Expand Down Expand Up @@ -59,7 +59,7 @@ Tested on Waterfall, version: `git:Waterfall-Bootstrap:1.17-R0.1-SNAPSHOT:436f47
* Switch between multiple configuration files (e.g., a config for maintenance mode which whitelists administrators only; from v2.4)
* Optional confirmation before adding or removing list entries (from v2.4, see [Operation Confirmation](#operation-confirmation) for more details)
* Import from old `whitelist.json` or `banned-players.json` (from v2.5, resolves issue #7; see [whitelist import](#whitelist-import) and [blacklist import](#blacklist-import) for more details)
* API support backed by (possibly) well structured and documented code base (from v3.0; see [Developing Extension Plugin for BungeeSafeguard](./developer.md) for more details)
* API support backed by (possibly) well-structured and documented code base (from v3.0; see [Developing Extension Plugin for BungeeSafeguard](./developer.md) for more details)
* Manage the lists via a GUI Web interface (TODO)
* SQL database storage support (TODO)
* Redis storage support (TODO)
Expand All @@ -83,7 +83,7 @@ For **normal users**, we have the followings:
* [Replaceable Storage Backend for Lists](#replaceable-storage-backend-for-lists)
* [Optional Extension Plugins](#optional-extension-plugins)

For **developers** who **want to interact with BungeeSafeguard** in a graceful manner, please refer to [Developing Extension Plugin for BungeeSafeguard](./developer.md).
For **developers** who **want to interact with BungeeSafeguard** gracefully, please refer to [Developing Extension Plugin for BungeeSafeguard](./developer.md).

## Migrate to v2.0

Expand Down Expand Up @@ -124,7 +124,11 @@ TODO: some implementations available
Start from v3.0, BungeeSafeguard exposes a handful of APIs for third-party plugins to manipulate the lists or register custom backend.
For example, you can now implement a standalone plugin that programmatically whitelist or blacklist someone; or a plugin that wraps BungeeSafeguard APIs and exposes them as RESTful API.

TODO: some implementations available
Current available extension plugins:

| Name | Feature |
| ---- | ------- |
| [RESTful-BSG](https://github.com/Luluno01/RESTful-BSG) | Access the whitelist/blacklist via RESTful API |

## Configuration

Expand Down
21 changes: 14 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.5.10'
id 'org.jetbrains.kotlin.jvm' version '1.5.20'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}

Expand All @@ -21,20 +21,27 @@ sourceSets {
}

shadowJar {
// Library loading is delegated to BungeeCord
dependencies {
exclude(dependency('org.jetbrains.kotlin.*:.*:.*'))
exclude(dependency('io.ktor.*:.*:.*'))
exclude(dependency('com.google.code.gson:gson:.*'))
}

archiveBaseName.set('BungeeSafeguard')
archiveVersion.set(project.version as String)
zip64 true
relocate('org.bstats', 'cyou.untitled.bungeesafeguard.bstats')
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
implementation 'com.google.code.gson:gson:2.8.7'
compileOnly "org.jetbrains.kotlin:kotlin-stdlib"
compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
compileOnly 'com.google.code.gson:gson:2.8.7' // Included in BungeeCord
compileOnly "net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT"
implementation 'io.ktor:ktor-client-core:1.6.0'
implementation 'io.ktor:ktor-client-cio:1.6.0'
implementation 'org.bstats:bstats-bungeecord:2.2.1'
compileOnly 'io.ktor:ktor-client-core:1.6.0'
compileOnly 'io.ktor:ktor-client-cio:1.6.0'
implementation 'org.bstats:bstats-bungeecord:2.2.1' // Shaded
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@ class BungeeSafeguardImpl: BungeeSafeguard() {
}
runBlocking /* No more asynchronous tasks will be executed */ {
val backend = Backend.getBackend()
logger.info("Closing backend $backend")
val backendDesc = backend.toString()
logger.info("Closing backend $backendDesc")
backend.close(null)
logger.info("Backend $backend closed")
logger.info("Backend $backendDesc closed")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package cyou.untitled.bungeesafeguard.helpers

import cyou.untitled.bungeesafeguard.BungeeSafeguard
import net.md_5.bungee.api.plugin.Plugin
import java.io.File
import java.net.URL
import java.net.URLClassLoader

@Suppress("MemberVisibilityCanBePrivate", "unused")
object DependencyFixer {
class RelaxedURLClassLoader(urls: Array<out URL>?, parent: ClassLoader?) : URLClassLoader(urls, parent) {
fun insertURL(url: URL) {
addURL(url)
}
}
data class FixResult(val newLibraryLoader: RelaxedURLClassLoader, val removedPaths: List<URL>)

/**
* Get artifact ID from its URL
* @param url URL to the artifact,
* e.g., file:///home/abc/kotlin-stdlib-1.0.0.jar
* @return the artifact ID (not guaranteed to be 100% correct)
*/
fun getArtifactIdFromURL(url: URL): String {
val basename = File(url.file).nameWithoutExtension
return """([\w\-]+?)-(\d.+)""".toRegex().matchEntire(basename)!!.groupValues[1]
}

/**
* Replace the class loader for libraries of given plugin with a custom one
* that prioritizes those libraries of BungeeSafeguard. Specifically, it
* excludes all kotlin*.jar.
* @param plugin the plugin to fix
*/
fun fixLibraryLoader(plugin: Plugin): FixResult {
return fixLibraryLoader(plugin::class.java.classLoader)
}

/**
* Replace the class loader for libraries of given plugin with a custom one
* that prioritizes those libraries of BungeeSafeguard
* @param pluginClassLoader the class loader to be fixed, retrieved by
* `YourPluginClass::class.java.classLoader`
*/
fun fixLibraryLoader(pluginClassLoader: ClassLoader): FixResult {
val bsgLoader = BungeeSafeguard::class.java.classLoader
val cPluginClassLoader = pluginClassLoader.javaClass
val fLibraryLoader = cPluginClassLoader.getDeclaredField("libraryLoader")
fLibraryLoader.isAccessible = true
try {
val parentLibraryLoader = fLibraryLoader.get(bsgLoader) as URLClassLoader
val oldLibraryLoader = fLibraryLoader.get(pluginClassLoader) as URLClassLoader
val bsgArtifacts = parentLibraryLoader.urLs.map { getArtifactIdFromURL(it) }
val removedPaths = mutableListOf<URL>()
val newURLs = oldLibraryLoader.urLs.filter {
!bsgArtifacts.contains(getArtifactIdFromURL(it)).also { remove ->
if (remove) removedPaths.add(it)
}
}
/**
* We must remove duplicated dependencies from the path, otherwise
* they will still be loaded as transitive dependencies by the
* `oldLibraryLoader`
*/
val newLibraryLoader = RelaxedURLClassLoader(newURLs.toTypedArray(), parentLibraryLoader)
fLibraryLoader.set(pluginClassLoader, newLibraryLoader)
return FixResult(newLibraryLoader, removedPaths)
} finally {
fLibraryLoader.isAccessible = false
}
}
}
8 changes: 8 additions & 0 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ name: BungeeSafeguard
main: cyou.untitled.bungeesafeguard.BungeeSafeguardImpl
version: "3.0"
author: Untitled
libraries:
- org.jetbrains.kotlin:kotlin-stdlib:1.5.20
- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0
- com.google.code.gson:gson:2.8.7
- io.ktor:ktor-client-core:1.6.0
- io.ktor:ktor-client-core-jvm:1.6.0 # Somehow, BungeeCord misses this
- io.ktor:ktor-client-cio:1.6.0
- io.ktor:ktor-client-cio-jvm:1.6.0 # Somehow, BungeeCord misses this

0 comments on commit 2bcd701

Please sign in to comment.