diff --git a/bungee/build.gradle.kts b/bungee/build.gradle.kts index 83847db20..24357141d 100644 --- a/bungee/build.gradle.kts +++ b/bungee/build.gradle.kts @@ -1,5 +1,4 @@ dependencies { implementation(projects.viaversionCommon) - implementation(projects.compat) compileOnly(libs.bungee) } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1225b9441..429b8eaf7 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -10,6 +10,8 @@ blossom { dependencies { api(projects.viaversionApi) api(projects.viaversionApiLegacy) + implementation(projects.compat.snakeyaml2Compat) + implementation(projects.compat.snakeyaml1Compat) } java { diff --git a/common/src/main/java/com/viaversion/viaversion/util/Config.java b/common/src/main/java/com/viaversion/viaversion/util/Config.java index aed43a539..dcbce9475 100644 --- a/common/src/main/java/com/viaversion/viaversion/util/Config.java +++ b/common/src/main/java/com/viaversion/viaversion/util/Config.java @@ -20,6 +20,9 @@ package com.viaversion.viaversion.util; import com.google.gson.JsonElement; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.configuration.ConfigurationProvider; +import com.viaversion.viaversion.compatibility.YamlCompat; +import com.viaversion.viaversion.compatibility.unsafe.Yaml1Compat; +import com.viaversion.viaversion.compatibility.unsafe.Yaml2Compat; import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import java.io.File; @@ -35,15 +38,15 @@ import java.util.concurrent.ConcurrentSkipListMap; import org.checkerframework.checker.nullness.qual.Nullable; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.representer.Representer; public abstract class Config implements ConfigurationProvider { + private static final YamlCompat YAMP_COMPAT = YamlCompat.isVersion2() ? new Yaml2Compat() : new Yaml1Compat(); private static final ThreadLocal YAML = ThreadLocal.withInitial(() -> { DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); options.setPrettyFlow(false); options.setIndent(2); - return new Yaml(new YamlConstructor(), new Representer(), options); + return new Yaml(YAMP_COMPAT.createSafeConstructor(), YAMP_COMPAT.createRepresenter(options), options); }); private final CommentStore commentStore = new CommentStore('.', 2); @@ -56,7 +59,7 @@ public abstract class Config implements ConfigurationProvider { * * @param configFile The location of where the config is loaded/saved. */ - public Config(File configFile) { + protected Config(File configFile) { this.configFile = configFile; } diff --git a/common/src/main/java/com/viaversion/viaversion/util/YamlConstructor.java b/common/src/main/java/com/viaversion/viaversion/util/YamlConstructor.java deleted file mode 100644 index bd0805288..000000000 --- a/common/src/main/java/com/viaversion/viaversion/util/YamlConstructor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2023 ViaVersion and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.viaversion.viaversion.util; - -import java.util.concurrent.ConcurrentSkipListMap; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.constructor.SafeConstructor; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.nodes.NodeId; -import org.yaml.snakeyaml.nodes.Tag; - -public class YamlConstructor extends SafeConstructor { - public YamlConstructor() { - super(); - yamlClassConstructors.put(NodeId.mapping, new YamlConstructor.ConstructYamlMap()); - yamlConstructors.put(Tag.OMAP, new YamlConstructor.ConstructYamlOmap()); - } - - class Map extends Constructor.ConstructYamlMap { - @Override - public Object construct(Node node) { - Object o = super.construct(node); - if (o instanceof Map && !(o instanceof ConcurrentSkipListMap)) { - return new ConcurrentSkipListMap<>((java.util.Map) o); - } - return o; - } - } - - class ConstructYamlOmap extends Constructor.ConstructYamlOmap { - public Object construct(Node node) { - Object o = super.construct(node); - if (o instanceof Map && !(o instanceof ConcurrentSkipListMap)) { - return new ConcurrentSkipListMap<>((java.util.Map) o); - } - return o; - } - } -} diff --git a/compat/build.gradle.kts b/compat/build.gradle.kts index 2fcada132..5d91813ce 100644 --- a/compat/build.gradle.kts +++ b/compat/build.gradle.kts @@ -1,4 +1,5 @@ dependencies { - api(projects.compat.javaCompatCommon) - api(projects.compat.javaCompatUnsafe) + api(projects.compat.snakeyamlCompatCommon) + api(projects.compat.snakeyaml2Compat) + api(projects.compat.snakeyaml1Compat) } diff --git a/compat/java-compat-common/build.gradle.kts b/compat/java-compat-common/build.gradle.kts deleted file mode 100644 index e69de29bb..000000000 diff --git a/compat/java-compat-common/src/main/java/com/viaversion/viaversion/compatibility/ForcefulFieldModifier.java b/compat/java-compat-common/src/main/java/com/viaversion/viaversion/compatibility/ForcefulFieldModifier.java deleted file mode 100644 index c414347fe..000000000 --- a/compat/java-compat-common/src/main/java/com/viaversion/viaversion/compatibility/ForcefulFieldModifier.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2023 ViaVersion and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.viaversion.viaversion.compatibility; - -import java.lang.reflect.Field; - -/** - * Exposes a way to modify a {@link Field}, regardless of its limitations (given it is accessible by the caller). - *

- * Note: This is explicitly an implementation detail. Do not rely on this within plugins and any - * non-ViaVersion code. - *

- */ -public interface ForcefulFieldModifier { - /** - * Sets the field regardless of field finality. - *

- * Note: This does not set the accessibility of the field. - *

- * - * @param field the field to set the modifiers of. Will throw if {@code null}. - * @param holder the eye of the beholder. For static fields, use {@code null}. - * @param object the new value to set of the object. - */ - void setField(final Field field, final Object holder, final Object object) - throws ReflectiveOperationException; -} diff --git a/compat/java-compat-unsafe/build.gradle.kts b/compat/java-compat-unsafe/build.gradle.kts deleted file mode 100644 index e92b04640..000000000 --- a/compat/java-compat-unsafe/build.gradle.kts +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - api(projects.compat.javaCompatCommon) -} diff --git a/compat/java-compat-unsafe/src/main/java/com/viaversion/viaversion/compatibility/unsafe/UnsafeBackedForcefulFieldModifier.java b/compat/java-compat-unsafe/src/main/java/com/viaversion/viaversion/compatibility/unsafe/UnsafeBackedForcefulFieldModifier.java deleted file mode 100644 index 7d19cedca..000000000 --- a/compat/java-compat-unsafe/src/main/java/com/viaversion/viaversion/compatibility/unsafe/UnsafeBackedForcefulFieldModifier.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion - * Copyright (C) 2016-2023 ViaVersion and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.viaversion.viaversion.compatibility.unsafe; - -import com.viaversion.viaversion.compatibility.ForcefulFieldModifier; -import java.lang.reflect.Field; -import java.util.Objects; - -/** - * @deprecated usage of sun.misc.Unsafe is discouraged and can stop working in future Java releases. - */ -@SuppressWarnings({ - "java:S1191", // SonarLint/-Qube/-Cloud: We need Unsafe for the modifier implementation. - "java:S3011", // ^: We need to circumvent the access restrictions of fields. -}) -@Deprecated -public final class UnsafeBackedForcefulFieldModifier implements ForcefulFieldModifier { - private final sun.misc.Unsafe unsafe; - - public UnsafeBackedForcefulFieldModifier() throws ReflectiveOperationException { - final Field theUnsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeField.setAccessible(true); - this.unsafe = (sun.misc.Unsafe) theUnsafeField.get(null); - } - - @Override - public void setField(final Field field, final Object holder, final Object object) { - Objects.requireNonNull(field, "field must not be null"); - - final Object ufo = holder != null ? holder : this.unsafe.staticFieldBase(field); - final long offset = holder != null ? this.unsafe.objectFieldOffset(field) : this.unsafe.staticFieldOffset(field); - - this.unsafe.putObject(ufo, offset, object); - } -} diff --git a/compat/snakeyaml-compat-common/build.gradle.kts b/compat/snakeyaml-compat-common/build.gradle.kts new file mode 100644 index 000000000..45ffe7145 --- /dev/null +++ b/compat/snakeyaml-compat-common/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + compileOnly(rootProject.libs.snakeYaml2) +} diff --git a/compat/snakeyaml-compat-common/src/main/java/com/viaversion/viaversion/compatibility/YamlCompat.java b/compat/snakeyaml-compat-common/src/main/java/com/viaversion/viaversion/compatibility/YamlCompat.java new file mode 100644 index 000000000..8726f560e --- /dev/null +++ b/compat/snakeyaml-compat-common/src/main/java/com/viaversion/viaversion/compatibility/YamlCompat.java @@ -0,0 +1,38 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.compatibility; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.representer.Representer; + +public interface YamlCompat { + + Representer createRepresenter(DumperOptions dumperOptions); + + SafeConstructor createSafeConstructor(); + + static boolean isVersion2() { + try { + Representer.class.getDeclaredConstructor(DumperOptions.class); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } +} diff --git a/compat/snakeyaml1-compat/build.gradle.kts b/compat/snakeyaml1-compat/build.gradle.kts new file mode 100644 index 000000000..17a8d1e62 --- /dev/null +++ b/compat/snakeyaml1-compat/build.gradle.kts @@ -0,0 +1,4 @@ +dependencies { + api(projects.compat.snakeyamlCompatCommon) + compileOnly(rootProject.libs.snakeYaml) +} diff --git a/compat/snakeyaml1-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml1Compat.java b/compat/snakeyaml1-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml1Compat.java new file mode 100644 index 000000000..e97e53fb7 --- /dev/null +++ b/compat/snakeyaml1-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml1Compat.java @@ -0,0 +1,46 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.compatibility.unsafe; + +import com.viaversion.viaversion.compatibility.YamlCompat; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.NodeId; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; + +public final class Yaml1Compat implements YamlCompat { + + @Override + public Representer createRepresenter(DumperOptions dumperOptions) { + return new Representer(); + } + + @Override + public SafeConstructor createSafeConstructor() { + return new CustomSafeConstructor(); + } + + private static final class CustomSafeConstructor extends SafeConstructor { + + public CustomSafeConstructor() { + yamlClassConstructors.put(NodeId.mapping, new ConstructYamlMap()); + yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap()); + } + } +} diff --git a/compat/snakeyaml2-compat/build.gradle.kts b/compat/snakeyaml2-compat/build.gradle.kts new file mode 100644 index 000000000..0b54f4982 --- /dev/null +++ b/compat/snakeyaml2-compat/build.gradle.kts @@ -0,0 +1,4 @@ +dependencies { + api(projects.compat.snakeyamlCompatCommon) + compileOnly(rootProject.libs.snakeYaml2) +} diff --git a/compat/snakeyaml2-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml2Compat.java b/compat/snakeyaml2-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml2Compat.java new file mode 100644 index 000000000..eaad8b8ab --- /dev/null +++ b/compat/snakeyaml2-compat/src/main/java/com/viaversion/viaversion/compatibility/unsafe/Yaml2Compat.java @@ -0,0 +1,48 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.compatibility.unsafe; + +import com.viaversion.viaversion.compatibility.YamlCompat; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.NodeId; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; + +public final class Yaml2Compat implements YamlCompat { + + @Override + public Representer createRepresenter(DumperOptions dumperOptions) { + return new Representer(dumperOptions); + } + + @Override + public SafeConstructor createSafeConstructor() { + return new CustomSafeConstructor(); + } + + private static final class CustomSafeConstructor extends SafeConstructor { + + public CustomSafeConstructor() { + super(new LoaderOptions()); + yamlClassConstructors.put(NodeId.mapping, new ConstructYamlMap()); + yamlConstructors.put(Tag.OMAP, new ConstructYamlOmap()); + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a7647d8b5..8c492eb9a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ openNBT = "2.1" netty = "4.0.20.Final" guava = "17.0" snakeYaml = "1.18" +snakeYaml2 = "2.0" junit = "5.9.2" checkerQual = "3.29.0" @@ -41,6 +42,7 @@ openNBT = { group = "com.viaversion", name = "opennbt", version.ref = "openNBT" netty = { group = "io.netty", name = "netty-all", version.ref = "netty" } guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } snakeYaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeYaml" } +snakeYaml2 = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeYaml2" } jupiterApi = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } jupiterEngine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } diff --git a/settings.gradle.kts b/settings.gradle.kts index bd0133125..b19c9cbe1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,7 +27,7 @@ rootProject.name = "viaversion-parent" includeBuild("build-logic") include("adventure") -include("compat", "compat:java-compat-common", "compat:java-compat-unsafe", "compat:protocolsupport-compat") +include("compat", "compat:snakeyaml-compat-common", "compat:snakeyaml2-compat", "compat:snakeyaml1-compat", "compat:protocolsupport-compat") setupViaSubproject("api") setupViaSubproject("api-legacy")