Search SL4J JDK provider in our own classpath

Using the previous behavior it would look for the service file and provider
in the server jar. First it requires relocating the service file to our JDK
provider and let the service only be queryable from our plugin jar.

Fixes #668

Search SL4J JDK provider in our own classpath

Using the previous behavior it would look for the service file and provider
in the server jar. First it requires relocating the service file to our JDK
provider and let the service only be queryable from our plugin jar.

Fixes #668
This commit is contained in:
games647
2021-12-02 14:15:57 +01:00
parent 829ba79400
commit e1c1da199e
6 changed files with 55 additions and 23 deletions

View File

@ -77,6 +77,11 @@
<shadedPattern>fastlogin.paperlib</shadedPattern>
</relocation>
</relocations>
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
<!-- Located in META-INF/services -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
<executions>
<execution>
@ -147,9 +152,9 @@
<!-- PaperSpigot API for correcting usercache usage -->
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.15.2-R0.1-SNAPSHOT</version>
<version>1.18-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -158,7 +163,6 @@
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.7</version>
<scope>compile</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->

View File

@ -79,7 +79,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
private PremiumPlaceholder premiumPlaceholder;
public FastLoginBukkit() {
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
this.logger = CommonUtil.initializeLoggerService(getLogger());
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
}
@ -101,7 +101,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
markInitialized();
@ -153,7 +153,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
if (getServer().getPluginManager().getPlugin("Geyser-Spigot") != null) {
geyserService = new GeyserService(GeyserConnector.getInstance(), core);
}
if (getServer().getPluginManager().getPlugin("floodgate") != null) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
@ -272,7 +272,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(message);
}
/**
* Checks if a plugin is installed on the server
* @param name the name of the plugin
@ -301,7 +301,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
}
/**
* Send warning messages to log if incompatible plugins are used
* Send warning messages to log if incompatible plugins are used
*/
private void dependencyWarnings() {
if (isPluginInstalled("floodgate-bukkit")) {

View File

@ -70,6 +70,11 @@
<shadedPattern>fastlogin.slf4j</shadedPattern>
</relocation>
</relocations>
<!-- Rename the service file too to let SLF4J api find our own relocated jdk logger -->
<!-- Located in META-INF/services -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
<executions>
<execution>
@ -120,8 +125,15 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.16-R0.5-SNAPSHOT</version>
<version>1.18-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<!-- Use our own newer api version -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bedrock player bridge -->

View File

@ -81,7 +81,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
@Override
public void onEnable() {
logger = CommonUtil.createLoggerFromJDK(getLogger());
logger = CommonUtil.initializeLoggerService(getLogger());
scheduler = new AsyncScheduler(logger, getThreadFactory());
core = new FastLoginCore<>(this);

View File

@ -68,6 +68,14 @@
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
<exclusions>
<!-- HikariCP uses an old version of this API that has a typo in the service interface -->
<!-- We will use the api provided by the jdk14 dependency -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Logging framework implements slf4j which is required by hikari-->
@ -149,17 +157,5 @@
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.0-alpha5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

View File

@ -70,7 +70,24 @@ public class CommonUtil {
return new String(chars);
}
public static Logger createLoggerFromJDK(java.util.logging.Logger parent) {
/**
* This creates a SLF4J logger. In the process it initializes the SLF4J service provider. This method looks
* for the provider in the plugin jar instead of in the server jar when creating a Logger. The provider is only
* initialized once, so this method should be called early.
*
* The provider is bound to the service class `SLF4JServiceProvider`. Relocating this class makes it available
* for exclusive own usage. Other dependencies will use the relocated service too, and therefore will find the
* initialized provider.
*
* @param parent JDK logger
* @return slf4j logger
*/
public static Logger initializeLoggerService(java.util.logging.Logger parent) {
// set the class loader to the plugin one to find our own SLF4J provider in the plugin jar and not in the global
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
ClassLoader pluginLoader = CommonUtil.class.getClassLoader();
Thread.currentThread().setContextClassLoader(pluginLoader);
try {
parent.setLevel(Level.ALL);
@ -82,6 +99,9 @@ public class CommonUtil {
parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx);
parent.log(Level.WARNING, "Creating logger instance manually...");
return LoggerFactory.getLogger(parent.getName());
} finally {
// restore previous class loader
Thread.currentThread().setContextClassLoader(oldLoader);
}
}