More changes and migrations away from Jackson

This commit is contained in:
Camotoy 2024-07-09 12:26:27 -04:00
parent c095c276ef
commit ab4cc97b38
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
22 changed files with 65 additions and 172 deletions

View file

@ -5,10 +5,11 @@ dependencies {
}
platformRelocate("net.md_5.bungee.jni")
platformRelocate("com.fasterxml.jackson")
platformRelocate("io.netty.channel.kqueue") // This is not used because relocating breaks natives, but we must include it or else we get ClassDefNotFound
platformRelocate("net.kyori")
platformRelocate("org.yaml") // Broken as of 1.20
platformRelocate("org.spongepowered")
platformRelocate("io.leangen.geantyref")
platformRelocate("org.bstats")
// These dependencies are already present on the platform

View file

@ -39,7 +39,7 @@ import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
@ -293,7 +293,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserPluginBootstrap
//noinspection ResultOfMethodCallIgnored
getDataFolder().mkdir();
}
this.geyserConfig = ConfigLoaderTemp.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
this.geyserConfig = ConfigLoader.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
return false;

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.platform.fabric;
import com.google.gson.annotations.JsonAdapter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.fabricmc.api.EnvType;
@ -48,7 +49,7 @@ public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
private final String minecraftVersion;
private final EnvType environmentType;
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final boolean onlineMode;

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.platform.neoforge;
import com.google.gson.annotations.JsonAdapter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.minecraft.server.MinecraftServer;
@ -47,7 +48,7 @@ public class GeyserNeoForgeDumpInfo extends BootstrapDumpInfo {
private final String minecraftVersion;
private final Dist dist;
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final boolean onlineMode;
@ -81,4 +82,4 @@ public class GeyserNeoForgeDumpInfo extends BootstrapDumpInfo {
public String version;
public String url;
}
}
}

View file

@ -44,7 +44,7 @@ import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.level.WorldManager;
@ -286,7 +286,7 @@ public abstract class GeyserModBootstrap implements GeyserPluginBootstrap {
dataFolder.toFile().mkdir();
}
this.geyserConfig = ConfigLoaderTemp.load(dataFolder.resolve("config.yml").toFile(), GeyserPluginConfig.class);
this.geyserConfig = ConfigLoader.load(dataFolder.resolve("config.yml").toFile(), GeyserPluginConfig.class);
return true;
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);

View file

@ -33,7 +33,6 @@ dependencies {
}
platformRelocate("it.unimi.dsi.fastutil")
platformRelocate("com.fasterxml.jackson")
// Relocate net.kyori but exclude the component logger
platformRelocate("net.kyori", "net.kyori.adventure.text.logger.slf4j.ComponentLogger")
platformRelocate("org.objectweb.asm")

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.platform.spigot;
import com.google.gson.annotations.JsonAdapter;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
@ -42,7 +43,7 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
private final String platformAPIVersion;
private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final List<PluginInfo> plugins;

View file

@ -53,7 +53,7 @@ import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.level.WorldManager;
@ -485,7 +485,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserPluginBootst
//noinspection ResultOfMethodCallIgnored
getDataFolder().mkdir();
}
this.geyserConfig = ConfigLoaderTemp.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
this.geyserConfig = ConfigLoader.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();

View file

@ -38,7 +38,7 @@ import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserConfig;
import org.geysermc.geyser.configuration.GeyserRemoteConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
@ -160,7 +160,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
@Override
public void onGeyserEnable() {
try {
geyserConfig = ConfigLoaderTemp.load(new File(configFilename), GeyserRemoteConfig.class, this::handleArgsConfigOptions);
geyserConfig = ConfigLoader.load(new File(configFilename), GeyserRemoteConfig.class, this::handleArgsConfigOptions);
} catch (IOException ex) {
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
if (gui == null) {

View file

@ -5,10 +5,11 @@ dependencies {
compileOnlyApi(libs.velocity.api)
}
platformRelocate("com.fasterxml.jackson")
platformRelocate("it.unimi.dsi.fastutil")
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
platformRelocate("org.yaml")
platformRelocate("org.spongepowered")
platformRelocate("io.leangen.geantyref")
platformRelocate("org.bstats")
exclude("com.google.*:*")

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.platform.velocity;
import com.google.gson.annotations.JsonAdapter;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.proxy.ProxyServer;
import lombok.Getter;
@ -42,7 +43,7 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
private final String platformVendor;
private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final List<PluginInfo> plugins;

View file

@ -46,7 +46,7 @@ import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.network.GameProtocol;
@ -248,7 +248,7 @@ public class GeyserVelocityPlugin implements GeyserPluginBootstrap {
//noinspection ResultOfMethodCallIgnored
configFolder.toFile().mkdirs();
}
this.geyserConfig = ConfigLoaderTemp.load(configFolder.resolve("config.yml").toFile(), GeyserPluginConfig.class);
this.geyserConfig = ConfigLoader.load(configFolder.resolve("config.yml").toFile(), GeyserPluginConfig.class);
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();

View file

@ -24,6 +24,7 @@
*/
package org.geysermc.geyser.platform.viaproxy;
import com.google.gson.annotations.JsonAdapter;
import lombok.Getter;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
@ -41,7 +42,7 @@ public class GeyserViaProxyDumpInfo extends BootstrapDumpInfo {
private final String platformVersion;
private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final List<PluginInfo> plugins;

View file

@ -42,7 +42,7 @@ import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
@ -218,7 +218,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserPlugin
private boolean loadConfig() {
try {
this.config = ConfigLoaderTemp.load(new File(ROOT_FOLDER, "config.yml"), GeyserPluginConfig.class, node -> {
this.config = ConfigLoader.load(new File(ROOT_FOLDER, "config.yml"), GeyserPluginConfig.class, node -> {
try {
if (!ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE)) { // TODO
node.node("java", "forward-host").set(true);

View file

@ -39,7 +39,7 @@ import static org.spongepowered.configurate.NodePath.path;
import static org.spongepowered.configurate.transformation.TransformAction.remove;
import static org.spongepowered.configurate.transformation.TransformAction.rename;
public final class ConfigLoaderTemp {
public final class ConfigLoader {
private static final String HEADER = """
--------------------------------
Geyser Configuration File
@ -132,4 +132,7 @@ public final class ConfigLoaderTemp {
return config;
}
private ConfigLoader() {
}
}

View file

@ -1,50 +0,0 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.configuration;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
public enum EmoteOffhandWorkaroundOption {
NO_EMOTES,
EMOTES_AND_OFFHAND,
DISABLED;
public static class Deserializer extends JsonDeserializer<EmoteOffhandWorkaroundOption> {
@Override
public EmoteOffhandWorkaroundOption deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
return switch (value) {
case "no-emotes" -> NO_EMOTES;
case "emotes-and-offhand" -> EMOTES_AND_OFFHAND;
default -> DISABLED;
};
}
}
}

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.dump;
import com.google.gson.annotations.JsonAdapter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.geyser.GeyserImpl;
@ -55,7 +56,7 @@ public class BootstrapDumpInfo {
@AllArgsConstructor
public static class ListenerInfo {
@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
public String ip;
public int port;
}

View file

@ -25,9 +25,6 @@
package org.geysermc.geyser.ping;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -36,7 +33,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* designed for the format received by {@link GeyserLegacyPingPassthrough}.
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class GeyserPingInfo {
@Nullable
@ -58,13 +54,7 @@ public class GeyserPingInfo {
this.players = new Players(maxPlayers, onlinePlayers);
}
@JsonSetter("description")
void setDescription(JsonNode description) {
this.description = description.toString();
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Players {
private int max;

View file

@ -64,7 +64,7 @@ public class CustomSkullRegistryPopulator {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
Path skullConfigPath = bootstrap.getConfigFolder().resolve("custom-skulls.yml");
File skullConfigFile = FileUtils.fileOrCopiedFromResource(skullConfigPath.toFile(), "custom-skulls.yml", Function.identity(), bootstrap);
skullConfig = FileUtils.loadConfigNew(skullConfigFile, GeyserCustomSkullConfiguration.class);
skullConfig = FileUtils.loadConfig(skullConfigFile, GeyserCustomSkullConfiguration.class);
} catch (IOException e) {
GeyserImpl.getInstance().getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), e);
return;

View file

@ -25,76 +25,26 @@
package org.geysermc.geyser.text;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.io.IOException;
import java.io.Serial;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer {
@Serial
private static final long serialVersionUID = 1L;
import java.lang.reflect.Type;
import java.net.InetAddress;
public class AsteriskSerializer implements JsonSerializer<String> {
public static final String[] NON_SENSITIVE_ADDRESSES = {"", "0.0.0.0", "localhost", "127.0.0.1", "auto", "unknown"};
public static boolean showSensitive = false;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = AsteriskSerializer.class)
public @interface Asterisk {
String value() default "***";
/**
* If true, this value will be shown if {@link #showSensitive} is true, or if the IP is determined to not be a public IP
*
* @return true if this should be analyzed and treated as an IP
*/
boolean isIp() default false;
}
String asterisk;
boolean isIp;
@SuppressWarnings("unused") // Used by Jackson for Geyser dumps
public AsteriskSerializer() {
super(Object.class);
}
public AsteriskSerializer(String asterisk, boolean isIp) {
super(Object.class);
this.asterisk = asterisk;
this.isIp = isIp;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) {
Optional<Asterisk> anno = Optional.ofNullable(property)
.map(prop -> prop.getAnnotation(Asterisk.class));
return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null), anno.map(Asterisk::isIp).orElse(false));
}
@Override
public void serialize(Object obj, JsonGenerator gen, SerializerProvider prov) throws IOException {
if (isIp && (showSensitive || !isSensitiveIp((String) obj))) {
gen.writeObject(obj);
return;
public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
if (showSensitive || !isSensitiveIp(src)) {
return new JsonPrimitive(src);
}
gen.writeString(asterisk);
return new JsonPrimitive("***");
}
private boolean isSensitiveIp(String ip) {
@ -103,6 +53,16 @@ public class AsteriskSerializer extends StdSerializer<Object> implements Context
return false;
}
}
try {
InetAddress address = InetAddress.getByName(ip);
if (address.isSiteLocalAddress() || address.isLoopbackAddress()) {
return false;
}
} catch (Exception e) {
// Ignore
}
return true;
}
}

View file

@ -25,11 +25,6 @@
package org.geysermc.geyser.util;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.spongepowered.configurate.ConfigurationNode;
@ -51,26 +46,8 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileUtils {
/**
* Load the given YAML file into the given class
*
* @param src File to load
* @param valueType Class to load file into
* @param <T> the type
* @return The data as the given class
* @throws IOException if the config could not be loaded
*/
public final class FileUtils {
public static <T> T loadConfig(File src, Class<T> valueType) throws IOException {
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory())
// Allow inference of single values as arrays
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
return objectMapper.readValue(src, valueType);
}
public static <T> T loadConfigNew(File src, Class<T> valueType) throws IOException {
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.file(src)
.build();
@ -257,4 +234,7 @@ public class FileUtils {
throw new RuntimeException(e);
}
}
private FileUtils() {
}
}

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
@ -34,7 +33,11 @@ import org.geysermc.geyser.GeyserImpl;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
@ -69,7 +72,7 @@ public class WebUtils {
}
/**
* Makes a web request to the given URL and returns the body as a {@link JsonNode}.
* Makes a web request to the given URL and returns the body as a {@link JsonObject}.
*
* @param reqURL URL to fetch
* @return the response as JSON