Skip to content

Commit

Permalink
Allow interceptors to interpose between "regular" sources and default…
Browse files Browse the repository at this point in the history
… sources (#1128)

We split the interceptors and sources into two groups: those with negative priority and those with positive priority. The positive interceptors come before positive sources, which come before negative interceptors, which come before negative sources.
  • Loading branch information
dmlloyd authored Mar 12, 2024
1 parent 1a8bbc1 commit cf075f8
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 19 deletions.
58 changes: 43 additions & 15 deletions implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -707,32 +707,49 @@ private static class ConfigSources implements Serializable {
sources.add(defaultValues);

// Add all interceptors
List<ConfigSourceInterceptor> interceptors = new ArrayList<>();
List<ConfigSourceInterceptor> negativeInterceptors = new ArrayList<>();
List<ConfigSourceInterceptor> positiveInterceptors = new ArrayList<>();
SmallRyeConfigSources negativeSources = new SmallRyeConfigSources(mapSources(sources), true);
SmallRyeConfigSources positiveSources = new SmallRyeConfigSources(mapSources(sources), false);
List<InterceptorWithPriority> interceptorWithPriorities = buildInterceptors(builder);

// Create the initial chain with initial sources and all interceptors
SmallRyeConfigSourceInterceptorContext current = new SmallRyeConfigSourceInterceptorContext(EMPTY, null, config);
current = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(mapSources(sources)), current,
config);
current = new SmallRyeConfigSourceInterceptorContext(negativeSources, current, config);
for (InterceptorWithPriority interceptorWithPriority : interceptorWithPriorities) {
ConfigSourceInterceptor interceptor = interceptorWithPriority.getInterceptor(current);
interceptors.add(interceptor);
current = new SmallRyeConfigSourceInterceptorContext(interceptor, current, config);
if (interceptorWithPriority.getPriority() < 0) {
ConfigSourceInterceptor interceptor = interceptorWithPriority.getInterceptor(current);
negativeInterceptors.add(interceptor);
current = new SmallRyeConfigSourceInterceptorContext(interceptor, current, config);
}
}
current = new SmallRyeConfigSourceInterceptorContext(positiveSources, current, config);
for (InterceptorWithPriority interceptorWithPriority : interceptorWithPriorities) {
if (interceptorWithPriority.getPriority() >= 0) {
ConfigSourceInterceptor interceptor = interceptorWithPriority.getInterceptor(current);
positiveInterceptors.add(interceptor);
current = new SmallRyeConfigSourceInterceptorContext(interceptor, current, config);
}
}

// Init all late sources
List<String> profiles = getProfiles(interceptors);
List<ConfigSourceWithPriority> sourcesWithPriorities = mapLateSources(sources, interceptors, current, profiles,
builder, config);
List<String> profiles = getProfiles(positiveInterceptors);
List<ConfigSourceWithPriority> sourcesWithPriorities = mapLateSources(sources, negativeInterceptors,
positiveInterceptors, current, profiles, builder, config);
List<ConfigSource> configSources = getSources(sourcesWithPriorities);

// Rebuild the chain with the late sources and new instances of the interceptors
// The new instance will ensure that we get rid of references to factories and other stuff and keep only
// the resolved final source or interceptor to use.
current = new SmallRyeConfigSourceInterceptorContext(EMPTY, null, config);
current = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(sourcesWithPriorities), current,
config);
for (ConfigSourceInterceptor interceptor : interceptors) {
current = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(sourcesWithPriorities, true),
current, config);
for (ConfigSourceInterceptor interceptor : negativeInterceptors) {
current = new SmallRyeConfigSourceInterceptorContext(interceptor, current, config);
}
current = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(sourcesWithPriorities, false),
current, config);
for (ConfigSourceInterceptor interceptor : positiveInterceptors) {
current = new SmallRyeConfigSourceInterceptorContext(interceptor, current, config);
}

Expand Down Expand Up @@ -797,7 +814,8 @@ private static List<String> getProfiles(final List<ConfigSourceInterceptor> inte

private static List<ConfigSourceWithPriority> mapLateSources(
final List<ConfigSource> sources,
final List<ConfigSourceInterceptor> interceptors,
final List<ConfigSourceInterceptor> negativeInterceptors,
final List<ConfigSourceInterceptor> positiveInterceptors,
final ConfigSourceInterceptorContext current,
final List<String> profiles,
final SmallRyeConfigBuilder builder,
Expand All @@ -823,8 +841,14 @@ private static List<ConfigSourceWithPriority> mapLateSources(

// Rebuild the chain with the profiles sources, so profiles values are also available in factories
ConfigSourceInterceptorContext context = new SmallRyeConfigSourceInterceptorContext(EMPTY, null, config);
context = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(currentSources), context, config);
for (ConfigSourceInterceptor interceptor : interceptors) {
context = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(currentSources, true), context,
config);
for (ConfigSourceInterceptor interceptor : negativeInterceptors) {
context = new SmallRyeConfigSourceInterceptorContext(interceptor, context, config);
}
context = new SmallRyeConfigSourceInterceptorContext(new SmallRyeConfigSources(currentSources, false), context,
config);
for (ConfigSourceInterceptor interceptor : positiveInterceptors) {
context = new SmallRyeConfigSourceInterceptorContext(interceptor, context, config);
}

Expand Down Expand Up @@ -942,6 +966,10 @@ ConfigSource getSource() {
return source;
}

int priority() {
return priority;
}

@Override
public int compareTo(final ConfigSourceWithPriority other) {
int res = Integer.compare(this.priority, other.priority);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,18 @@ public OptionalInt getPriority() {
this.priority = factory.getPriority().orElse(DEFAULT_PRIORITY);
}

InterceptorWithPriority(ConfigSourceInterceptor interceptor, int priority) {
this(new ConfigSourceInterceptorFactory() {
public ConfigSourceInterceptor getInterceptor(final ConfigSourceInterceptorContext context) {
return interceptor;
}

public OptionalInt getPriority() {
return OptionalInt.of(priority);
}
});
}

ConfigSourceInterceptor getInterceptor(ConfigSourceInterceptorContext context) {
return factory.getInterceptor(context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ class SmallRyeConfigSources implements ConfigSourceInterceptor {
private static final long serialVersionUID = 7560201715403486552L;

private final List<ConfigValueConfigSource> configSources;
private final boolean negative;

SmallRyeConfigSources(final List<ConfigSourceWithPriority> configSourcesWithPriorities) {
SmallRyeConfigSources(final List<ConfigSourceWithPriority> configSourcesWithPriorities, boolean negative) {
this.negative = negative;
List<ConfigValueConfigSource> configSources = new ArrayList<>();
for (ConfigSourceWithPriority configSource : configSourcesWithPriorities) {
configSources.add(ConfigValueConfigSourceWrapper.wrap(configSource.getSource()));
if ((configSource.priority() < 0) == negative) {
configSources.add(ConfigValueConfigSourceWrapper.wrap(configSource.getSource()));
}
}
this.configSources = configSources;
}
Expand All @@ -34,7 +38,7 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final
return configValue.from().withConfigSourcePosition(i).build();
}
}
return null;
return context.proceed(name);
}

@Override
Expand All @@ -46,9 +50,15 @@ public Iterator<String> iterateNames(final ConfigSourceInterceptorContext contex
names.addAll(propertyNames);
}
}
Iterator<String> iter = context.iterateNames();
iter.forEachRemaining(names::add);
return names.iterator();
}

boolean negative() {
return negative;
}

static final class ConfigValueConfigSourceWrapper implements ConfigValueConfigSource, Serializable {
private static final long serialVersionUID = -1109094614437147326L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final

@Override
public OptionalInt getPriority() {
return OptionalInt.of(Integer.MIN_VALUE);
return OptionalInt.of(0);
}
})
.withSources(new MapBackedConfigSource("test", new HashMap<String, String>() {
Expand Down

0 comments on commit cf075f8

Please sign in to comment.