Skip to content

Commit 228374c

Browse files
authored
Merge pull request #241 from zonkyio/flyway-plugin-config
#240 Add support for flyway plugin configuration
2 parents a98ddb1 + aa25658 commit 228374c

File tree

3 files changed

+110
-40
lines changed

3 files changed

+110
-40
lines changed

embedded-database-spring-test/src/main/java/io/zonky/test/db/flyway/FlywayDescriptor.java

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public class FlywayDescriptor {
6363
&& !EXCLUDED_FIELDS.contains(field.getName())
6464
&& !EXCLUDED_TYPES.contains(field.getType());
6565

66+
private static final FieldFilter PLUGIN_FIELDS =
67+
field -> !Modifier.isStatic(field.getModifiers())
68+
&& !EXCLUDED_TYPES.contains(field.getType());
69+
6670
private final List<String> locations;
6771
private final List<String> schemas;
6872
private final String table;
@@ -74,6 +78,7 @@ public class FlywayDescriptor {
7478
private final boolean ignoreFutureMigrations;
7579
private final boolean validateOnMigrate;
7680
private final Map<Field, Object> otherFields;
81+
private final Map<Class<?>, Map<Field, Object>> pluginsFields;
7782

7883
private FlywayDescriptor(FlywayWrapper wrapper) {
7984
this.locations = ImmutableList.copyOf(wrapper.getLocations());
@@ -87,27 +92,15 @@ private FlywayDescriptor(FlywayWrapper wrapper) {
8792
this.ignoreFutureMigrations = wrapper.isIgnoreFutureMigrations();
8893
this.validateOnMigrate = wrapper.isValidateOnMigrate();
8994

90-
Map<Field, Object> otherFields = new HashMap<>();
91-
Object config = wrapper.getConfig();
95+
this.otherFields = getFields(wrapper.getConfig(), OTHER_FIELDS);
9296

93-
doWithFields(config.getClass(), field -> {
94-
makeAccessible(field);
95-
Object value = getField(field, config);
96-
97-
if (value != null) {
98-
if (Collection.class.isAssignableFrom(field.getType())) {
99-
value = Lists.newArrayList((Collection<?>) value);
100-
} else if (Map.class.isAssignableFrom(field.getType())) {
101-
value = Maps.newHashMap((Map<?, ?>) value);
102-
} else if (field.getType().isArray()) {
103-
value = Lists.newArrayList((Object[]) value);
104-
}
105-
}
106-
107-
otherFields.put(field, value);
108-
}, OTHER_FIELDS);
109-
110-
this.otherFields = otherFields;
97+
Map<Class<?>, Map<Field, Object>> pluginsFields = new HashMap<>();
98+
List<Object> plugins = wrapper.getConfigurationExtensions();
99+
for (Object plugin : plugins) {
100+
Map<Field, Object> pluginFields = getFields(plugin, PLUGIN_FIELDS);
101+
pluginsFields.put(plugin.getClass(), pluginFields);
102+
}
103+
this.pluginsFields = pluginsFields;
111104
}
112105

113106
public static FlywayDescriptor from(FlywayWrapper wrapper) {
@@ -128,21 +121,13 @@ public void applyTo(FlywayWrapper wrapper) {
128121
wrapper.setIgnoreFutureMigrations(ignoreFutureMigrations);
129122
wrapper.setValidateOnMigrate(validateOnMigrate);
130123

131-
otherFields.forEach((field, value) -> {
132-
makeAccessible(field);
124+
setFields(config, otherFields);
133125

134-
if (value == null) {
135-
setField(field, config, value);
136-
} else if (Collection.class.isAssignableFrom(field.getType())) {
137-
setCollection(field, config, (Collection<?>) value);
138-
} else if (Map.class.isAssignableFrom(field.getType())) {
139-
setMap(field, config, (Map<?, ?>) value);
140-
} else if (field.getType().isArray()) {
141-
setArray(field, config, (List<?>) value);
142-
} else {
143-
setField(field, config, value);
144-
}
145-
});
126+
List<Object> plugins = wrapper.getConfigurationExtensions();
127+
for (Object plugin : plugins) {
128+
Map<Field, Object> pluginFields = pluginsFields.get(plugin.getClass());
129+
setFields(plugin, pluginFields);
130+
}
146131
}
147132

148133
public List<String> getLocations() {
@@ -200,7 +185,8 @@ public boolean equals(Object o) {
200185
&& Objects.equals(repeatableSqlMigrationPrefix, that.repeatableSqlMigrationPrefix)
201186
&& Objects.equals(sqlMigrationSeparator, that.sqlMigrationSeparator)
202187
&& Objects.equals(sqlMigrationSuffixes, that.sqlMigrationSuffixes)
203-
&& Objects.equals(otherFields, that.otherFields);
188+
&& Objects.equals(otherFields, that.otherFields)
189+
&& Objects.equals(pluginsFields, that.pluginsFields);
204190
}
205191

206192
@Override
@@ -209,7 +195,7 @@ public int hashCode() {
209195
sqlMigrationPrefix, repeatableSqlMigrationPrefix,
210196
sqlMigrationSeparator, sqlMigrationSuffixes,
211197
ignoreMissingMigrations, ignoreFutureMigrations,
212-
validateOnMigrate, otherFields);
198+
validateOnMigrate, otherFields, pluginsFields);
213199
}
214200

215201
private static void setCollection(Field field, Object target, Collection<?> value) {
@@ -237,4 +223,46 @@ private static void setArray(Field field, Object config, List<?> value) {
237223
Object[] array = value.toArray((Object[]) Array.newInstance(componentType, 0));
238224
setField(field, config, array);
239225
}
226+
227+
private static Map<Field, Object> getFields(Object targetObject, FieldFilter fieldFilter) {
228+
Map<Field, Object> fieldValues = new HashMap<>();
229+
230+
Class<?> objectClass = targetObject.getClass();
231+
doWithFields(objectClass, field -> {
232+
makeAccessible(field);
233+
Object value = getField(field, targetObject);
234+
235+
if (value != null) {
236+
if (Collection.class.isAssignableFrom(field.getType())) {
237+
value = Lists.newArrayList((Collection<?>) value);
238+
} else if (Map.class.isAssignableFrom(field.getType())) {
239+
value = Maps.newHashMap((Map<?, ?>) value);
240+
} else if (field.getType().isArray()) {
241+
value = Lists.newArrayList((Object[]) value);
242+
}
243+
}
244+
245+
fieldValues.put(field, value);
246+
}, fieldFilter);
247+
248+
return fieldValues;
249+
}
250+
251+
private static void setFields(Object targetObject, Map<Field, Object> fieldValues) {
252+
fieldValues.forEach((field, value) -> {
253+
makeAccessible(field);
254+
255+
if (value == null) {
256+
setField(field, targetObject, value);
257+
} else if (Collection.class.isAssignableFrom(field.getType())) {
258+
setCollection(field, targetObject, (Collection<?>) value);
259+
} else if (Map.class.isAssignableFrom(field.getType())) {
260+
setMap(field, targetObject, (Map<?, ?>) value);
261+
} else if (field.getType().isArray()) {
262+
setArray(field, targetObject, (List<?>) value);
263+
} else {
264+
setField(field, targetObject, value);
265+
}
266+
});
267+
}
240268
}

embedded-database-spring-test/src/main/java/io/zonky/test/db/flyway/FlywayWrapper.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,12 +398,30 @@ public void setCleanDisabled(boolean cleanDisabled) {
398398
setValue(config, "setCleanDisabled", cleanDisabled);
399399
}
400400

401-
private static <T> T getValue(Object target, String method) {
402-
return invokeMethod(target, method);
401+
public List<Object> getConfigurationExtensions() {
402+
if (flywayVersion >= 90) {
403+
try {
404+
Object pluginRegister = getField(getConfig(), "pluginRegister");
405+
Class<?> pluginType = ClassUtils.forName("org.flywaydb.core.extensibility.ConfigurationExtension", classLoader);
406+
return ImmutableList.copyOf(getList(pluginRegister, "getPlugins", pluginType));
407+
} catch (ClassNotFoundException e) {
408+
throw new IllegalStateException("Class not found: " + e.getMessage());
409+
}
410+
} else {
411+
return ImmutableList.of();
412+
}
413+
}
414+
415+
private static <T> T getValue(Object target, String method, Object... args) {
416+
return invokeMethod(target, method, args);
417+
}
418+
419+
private static <E> E[] getArray(Object target, String method, Object... args) {
420+
return invokeMethod(target, method, args);
403421
}
404422

405-
private static <E> E[] getArray(Object target, String method) {
406-
return invokeMethod(target, method);
423+
private static <E> List<E> getList(Object target, String method, Object... args) {
424+
return invokeMethod(target, method, args);
407425
}
408426

409427
private static void setValue(Object target, String method, Object value) {

embedded-database-spring-test/src/test/java/io/zonky/test/db/flyway/FlywayDescriptorTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,30 @@ public void testDynamicFields() throws ClassNotFoundException {
9393
assertThat(descriptor1).isEqualTo(descriptor3);
9494
}
9595

96+
@Test
97+
public void testPluginFields() {
98+
FlywayWrapper wrapper1 = FlywayWrapper.newInstance();
99+
wrapper1.getConfigurationExtensions().stream()
100+
.filter(o -> o.getClass().getSimpleName().equals("PostgreSQLConfigurationExtension"))
101+
.forEach(o -> invokeMethod(o, "setTransactionalLock", false));
102+
103+
FlywayWrapper wrapper2 = FlywayWrapper.newInstance();
104+
wrapper2.getConfigurationExtensions().stream()
105+
.filter(o -> o.getClass().getSimpleName().equals("PostgreSQLConfigurationExtension"))
106+
.forEach(o -> invokeMethod(o, "setTransactionalLock", false));
107+
108+
FlywayDescriptor descriptor1 = FlywayDescriptor.from(wrapper1);
109+
FlywayDescriptor descriptor2 = FlywayDescriptor.from(wrapper2);
110+
111+
assertThat(descriptor1).isEqualTo(descriptor2);
112+
113+
FlywayWrapper wrapper3 = FlywayWrapper.newInstance();
114+
descriptor1.applyTo(wrapper3);
115+
FlywayDescriptor descriptor3 = FlywayDescriptor.from(wrapper3);
116+
117+
assertThat(descriptor1).isEqualTo(descriptor3);
118+
}
119+
96120
@Test
97121
public void testExcludedFields() {
98122
FlywayWrapper wrapper1 = FlywayWrapper.newInstance();

0 commit comments

Comments
 (0)