Advertisement
Guest User

Untitled

a guest
Sep 24th, 2018
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.01 KB | None | 0 0
  1. package fr.mosca42.util;
  2.  
  3. import java.lang.reflect.Array;
  4. import java.lang.reflect.Constructor;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.Modifier;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.List;
  11.  
  12. import org.bukkit.Material;
  13.  
  14. public class EnumHelper {
  15.  
  16. private static Object reflectionFactory = null;
  17. private static Method newConstructorAccessor = null;
  18. private static Method newInstance = null;
  19. private static Method newFieldAccessor = null;
  20. private static Method fieldAccessorSet = null;
  21. private static boolean isSetup = false;
  22.  
  23. private static Class[][] commonTypes =
  24. {
  25. {Material.class, int.class}
  26. };
  27.  
  28. public static Material addMaterial(String name, int id)
  29. {
  30. return addEnum(Material.class, name, id);
  31. }
  32.  
  33. private static void setup()
  34. {
  35. if (isSetup)
  36. {
  37. return;
  38. }
  39.  
  40. try
  41. {
  42. Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
  43. reflectionFactory = getReflectionFactory.invoke(null);
  44. newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
  45. newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
  46. newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
  47. fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
  48. }
  49. catch (Exception e)
  50. {
  51. e.printStackTrace();
  52. }
  53.  
  54. isSetup = true;
  55. }
  56.  
  57.  
  58. public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues)
  59. {
  60. setup();
  61. return addEnum(commonTypes, enumType, enumName, paramValues);
  62. }
  63.  
  64. @SuppressWarnings("rawtypes")
  65. public static <T extends Enum<? >> T addEnum(Class[][] map, Class<T> enumType, String enumName, Object... paramValues)
  66. {
  67. for (Class[] lookup : map)
  68. {
  69. if (lookup[0] == enumType)
  70. {
  71. Class<?>[] paramTypes = new Class<?>[lookup.length - 1];
  72. if (paramTypes.length > 0)
  73. {
  74. System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length);
  75. }
  76. return addEnum(enumType, enumName, paramTypes, paramValues);
  77. }
  78. }
  79. return null;
  80. }
  81.  
  82. @SuppressWarnings("unchecked")
  83. public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object[] paramValues)
  84. {
  85. if (!isSetup)
  86. {
  87. setup();
  88. }
  89.  
  90. Field valuesField = null;
  91. Field[] fields = enumType.getDeclaredFields();
  92.  
  93. for (Field field : fields)
  94. {
  95. String name = field.getName();
  96. if (name.equals("$VALUES") || name.equals("ENUM$VALUES"))
  97. {
  98. valuesField = field;
  99. break;
  100. }
  101. }
  102.  
  103. int flags = (false ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000;
  104. if (valuesField == null)
  105. {
  106. String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));
  107.  
  108. for (Field field : fields)
  109. {
  110. if ((field.getModifiers() & flags) == flags &&
  111. field.getType().getName().replace('.', '/').equals(valueType))
  112. {
  113. valuesField = field;
  114. break;
  115. }
  116. }
  117. }
  118.  
  119. if (valuesField == null)
  120. {
  121. for (Field field : fields)
  122. {
  123. String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
  124. }
  125. return null;
  126. }
  127.  
  128. valuesField.setAccessible(true);
  129.  
  130. try
  131. {
  132. T[] previousValues = (T[])valuesField.get(enumType);
  133. List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
  134. T newValue = (T)makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
  135. values.add(newValue);
  136. setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
  137. cleanEnumCache(enumType);
  138.  
  139. return newValue;
  140. }
  141. catch (Exception e)
  142. {
  143. e.printStackTrace();
  144. throw new RuntimeException(e.getMessage(), e);
  145. }
  146. }
  147.  
  148. private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception
  149. {
  150. Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
  151. parameterTypes[0] = String.class;
  152. parameterTypes[1] = int.class;
  153. System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
  154. return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
  155. }
  156.  
  157. private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception
  158. {
  159. Object[] parms = new Object[additionalValues.length + 2];
  160. parms[0] = value;
  161. parms[1] = Integer.valueOf(ordinal);
  162. System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
  163. return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {parms}));
  164. }
  165.  
  166. public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception
  167. {
  168. field.setAccessible(true);
  169. Field modifiersField = Field.class.getDeclaredField("modifiers");
  170. modifiersField.setAccessible(true);
  171. modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  172. Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
  173. fieldAccessorSet.invoke(fieldAccessor, target, value);
  174. }
  175.  
  176. private static void blankField(Class<?> enumClass, String fieldName) throws Exception
  177. {
  178. for (Field field : Class.class.getDeclaredFields())
  179. {
  180. if (field.getName().contains(fieldName))
  181. {
  182. field.setAccessible(true);
  183. setFailsafeFieldValue(field, enumClass, null);
  184. break;
  185. }
  186. }
  187. }
  188.  
  189. private static void cleanEnumCache(Class<?> enumClass) throws Exception
  190. {
  191. blankField(enumClass, "enumConstantDirectory");
  192. blankField(enumClass, "enumConstants");
  193. }
  194.  
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement