| 85 | |
| 86 | /** |
| 87 | * Reset all {@link AbstractProperty} preferences to the new preference |
| 88 | * @param pref The preference to use |
| 89 | * @throws ReflectiveOperationException if reflection fails |
| 90 | */ |
| 91 | private void resetConfigVariables(Preferences pref) throws ReflectiveOperationException { |
| 92 | final Field classField = ClassLoader.class.getDeclaredField("classes"); |
| 93 | classField.setAccessible(true); |
| 94 | final Field configField = AbstractProperty.class.getDeclaredField("preferences"); |
| 95 | final boolean configIsFinal = Modifier.isFinal(configField.getModifiers()); |
| 96 | try { |
| 97 | if (configIsFinal) { |
| 98 | makeFinalFieldModifiable(configField, true); |
| 99 | } |
| 100 | // We are pretty much requiring that this doesn't change. |
| 101 | @SuppressWarnings("unchecked") |
| 102 | Vector<Class<?>> classes = (Vector<Class<?>>) classField.get(this.getClass().getClassLoader()); |
| 103 | // We need to copy to another list (ConcurrentModificationException) |
| 104 | for (Class<?> clazz : classes.stream().collect(Collectors.toList())) { |
| 105 | for (Field field : clazz.getDeclaredFields()) { |
| 106 | if (Modifier.isStatic(field.getModifiers()) && AbstractProperty.class.isInstance(field.getType())) { |
| 107 | configField.set(field.get(null), pref); |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | } finally { |
| 112 | if (configIsFinal) { |
| 113 | makeFinalFieldModifiable(configField, false); |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * Make a final field modifiable. This should always be called twice (once prior to modification, once after) |
| 120 | * @param field The field to make modifiable |
| 121 | * @param modifiable {@code false} will make the field final |
| 122 | * @throws ReflectiveOperationException If the reflection operations fail |
| 123 | */ |
| 124 | private static void makeFinalFieldModifiable(Field field, boolean modifiable) throws ReflectiveOperationException { |
| 125 | Field modifiersField = Field.class.getDeclaredField("modifiers"); |
| 126 | boolean isModifierAccessible = modifiersField.isAccessible(); |
| 127 | try { |
| 128 | if (!isModifierAccessible) { |
| 129 | modifiersField.setAccessible(true); |
| 130 | } |
| 131 | if (modifiable) { |
| 132 | modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); |
| 133 | } else { |
| 134 | modifiersField.setInt(field, field.getModifiers() | Modifier.FINAL); |
| 135 | } |
| 136 | } finally { |
| 137 | if (!isModifierAccessible) { |
| 138 | modifiersField.setAccessible(false); |
| 139 | } |
| 140 | } |
| 141 | } |