From 1c6097454f4fac0101cfa86e08ba3c759f5cad09 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Fri, 3 Aug 2018 12:51:07 +1000 Subject: [PATCH] Make tag mutable --- .../com/boydti/fawe/util/ReflectionUtils.java | 43 ++++++++++++++++--- .../main/java/com/sk89q/jnbt/CompoundTag.java | 2 +- .../worldedit/command/HistoryCommands.java | 8 +++- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java b/core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java index dfbb7c45..59130098 100644 --- a/core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java +++ b/core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java @@ -7,11 +7,8 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; + import sun.reflect.ConstructorAccessor; import sun.reflect.FieldAccessor; import sun.reflect.ReflectionFactory; @@ -28,6 +25,10 @@ public class ReflectionUtils { @SuppressWarnings("unchecked") public static > T addEnum(Class enumType, String enumName) { + return addEnum(enumType, enumName, new Class[]{} , new Object[]{}); + } + + public static > T addEnum(Class enumType, String enumName, Class[] additionalTypes, Object[] additionalValues) { // 0. Sanity checks if (!Enum.class.isAssignableFrom(enumType)) { @@ -54,8 +55,8 @@ public class ReflectionUtils { T newValue = (T) makeEnum(enumType, // The target enum class enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED values.size(), - new Class[]{}, // can be used to pass values to the enum constuctor - new Object[]{}); // can be used to pass values to the enum constuctor + additionalTypes, // can be used to pass values to the enum constuctor + additionalValues); // can be used to pass values to the enum constuctor // 4. add new value values.add(newValue); @@ -73,6 +74,31 @@ public class ReflectionUtils { } } + public static > void clearEnum(Class enumType) { + // 0. Sanity checks + if (!Enum.class.isAssignableFrom(enumType)) { + throw new RuntimeException("class " + enumType + " is not an instance of Enum"); + } + // 1. Lookup "$VALUES" holder in enum class and get previous enum instances + Field valuesField = null; + Field[] fields = enumType.getDeclaredFields(); + for (Field field : fields) { + if (field.getName().contains("$VALUES")) { + valuesField = field; + break; + } + } + AccessibleObject.setAccessible(new Field[]{valuesField}, true); + try { + setFailsafeFieldValue(valuesField, null, Array.newInstance(enumType, 0)); + // 6. Clean enum cache + cleanEnumCache(enumType); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage(), e); + } + } + private static Object makeEnum(Class enumClass, String value, int ordinal, Class[] additionalTypes, Object[] additionalValues) throws Exception { Object[] parms = new Object[additionalValues.length + 2]; @@ -134,9 +160,12 @@ public class ReflectionUtils { blankField(enumClass, "enumConstants"); // IBM JDK } + private static Class UNMODIFIABLE_MAP = Collections.unmodifiableMap(Collections.EMPTY_MAP).getClass(); + public static Map getMap(Map map) { try { Class clazz = map.getClass(); + if (clazz != UNMODIFIABLE_MAP) return map; Field m = clazz.getDeclaredField("m"); m.setAccessible(true); return (Map) m.get(map); diff --git a/core/src/main/java/com/sk89q/jnbt/CompoundTag.java b/core/src/main/java/com/sk89q/jnbt/CompoundTag.java index cdd59aa5..fdce7597 100644 --- a/core/src/main/java/com/sk89q/jnbt/CompoundTag.java +++ b/core/src/main/java/com/sk89q/jnbt/CompoundTag.java @@ -19,7 +19,7 @@ public final class CompoundTag extends Tag { */ public CompoundTag(Map value) { super(); - this.value = Collections.unmodifiableMap(value); + this.value = value; } @Override diff --git a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index b10a0042..182daace 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -162,7 +162,13 @@ public class HistoryCommands extends MethodCommands { BBC.COMMAND_SYNTAX.send(player, "/frb " + user + " " + radius + "