Skip to content

Commit

Permalink
Add System.out.println catcher
Browse files Browse the repository at this point in the history
  • Loading branch information
underscore11code committed Jul 27, 2021
1 parent b32a3b1 commit 7b08201
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 additions & 0 deletions patches/server/0731-Add-System.out.println-catcher.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: underscore11code <minecrafter11mrt@gmail.com>
Date: Fri, 23 Jul 2021 23:01:42 -0700
Subject: [PATCH] Add System.out.println catcher


diff --git a/src/main/java/io/papermc/paper/logging/SysoutCatcher.java b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..a29fcbea5ad155e6354d37f822ba2a0c498353a4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/logging/SysoutCatcher.java
@@ -0,0 +1,92 @@
+package io.papermc.paper.logging;
+
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.PrintStream;
+
+public final class SysoutCatcher {
+ private static final String PREFIX = "[SOUT] ";
+
+ public SysoutCatcher() {
+ // Listen to System.out.println
+ PrintStream wrappedOut = new PrintStream(System.out) {
+ @Override
+ public void println(String line) {
+ // Get the current stack trace and the calling method (index 2)
+ StackTraceElement element = Thread.currentThread().getStackTrace()[2];
+ try {
+ // Get the class name at that index and the JavaPlugin that "owns" it
+ Class<?> clazz = tryFindClass(element.getClassName());
+ JavaPlugin plugin = JavaPlugin.getProvidingPlugin(clazz);
+
+ // Instead of just printing the message, send it to the plugin's logger
+ plugin.getLogger().info(PREFIX + line);
+ nag(plugin);
+ } catch (ClassNotFoundException | IllegalArgumentException e) {
+ // If anything happens, the calling class doesn't exist, there is no JavaPlugin that "owns" the calling class, etc
+ // Just print out normally, with some added information
+ e.printStackTrace(); // TODO TEMP DON'T COMMIT
+ Bukkit.getLogger().info(String.format("[%s]" + PREFIX + " %s", element.getClassName(), line));
+ }
+ }
+ };
+
+ // Listen to System.err.println
+ PrintStream wrappedErr = new PrintStream(System.err) {
+ @Override
+ public void println(String line) {
+ // Get the current stack trace and the calling method (index 2)
+ StackTraceElement element = Thread.currentThread().getStackTrace()[2];
+ try {
+ // Get the class name at that index and the JavaPlugin that "owns" it
+ Class<?> clazz = tryFindClass(element.getClassName());
+ JavaPlugin plugin = JavaPlugin.getProvidingPlugin(clazz);
+
+ // Instead of just printing the message, send it to the plugin's logger
+ plugin.getLogger().severe(PREFIX + line);
+ nag(plugin);
+ } catch (ClassNotFoundException | IllegalArgumentException e) {
+ // If anything happens, the calling class doesn't exist, there is no JavaPlugin that "owns" the calling class, etc
+ // Just print out normally, with some added information
+ Bukkit.getLogger().severe(String.format("[%s]" + PREFIX + " %s", element.getClassName(), line));
+ }
+ }
+ };
+
+ // Set the two PrintStreams so they're used
+ System.setOut(wrappedOut);
+ System.setErr(wrappedErr);
+ }
+
+ private void nag(JavaPlugin javaPlugin) {
+ if (isBlacklisted(javaPlugin.getName())) return;
+ Bukkit.getLogger().warning(String.format("Nag author(s): '%s' of '%s' about their usage of System.out/err.print. " +
+ "Please use your plugin's logger instead (JavaPlugin#getLogger).",
+ javaPlugin.getDescription().getAuthors(),
+ javaPlugin.getName()));
+ }
+
+ private boolean isBlacklisted(final String pluginName) {
+ final String nags = System.getProperty("io.papermc.paper.suppress.sout.nags");
+ if (nags == null) return false;
+ for (final String suppressed : nags.split(",")) {
+ if (suppressed.equalsIgnoreCase(pluginName)) return true;
+ }
+ return false;
+ }
+
+ private Class<?> tryFindClass(final String name) throws ClassNotFoundException {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ try {
+ return Class.forName(name, true, plugin.getClass().getClassLoader());
+ } catch (ClassNotFoundException ignored) {}
+ }
+ }
+ throw new ClassNotFoundException(name);
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 9954e45c32a4b6d80fe912ed9d55cd4fc8c4e98b..6d7f16fede01c19f638e1dcdae8b07b79cd86dc0 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -18,6 +18,7 @@ import com.mojang.serialization.Lifecycle;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
+import io.papermc.paper.logging.SysoutCatcher;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import java.awt.image.BufferedImage;
import java.io.File;
@@ -277,6 +278,7 @@ public final class CraftServer implements Server {
public int reloadCount;
private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
public static Exception excessiveVelEx; // Paper - Velocity warnings
+ private final SysoutCatcher sysoutCatcher = new SysoutCatcher(); // Paper

static {
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);

0 comments on commit 7b08201

Please sign in to comment.