From 1c5dc1935ae60b274a17b75d7ab737c1600a1e97 Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Fri, 15 May 2020 20:14:00 +0100 Subject: [PATCH] Initial work to mix sources and interceptors priorities. --- .../ConfigValueConfigSourceWrapper.java | 4 + .../io/smallrye/config/SmallRyeConfig.java | 130 +++++++++++------- .../config/SmallRyeConfigBuilder.java | 7 +- .../SmallRyeConfigSourceInterceptor.java | 8 ++ .../config/ConfigSourceSortTestCase.java | 75 ---------- .../config/ConfigSourceWrapperTestCase.java | 5 + 6 files changed, 104 insertions(+), 125 deletions(-) delete mode 100644 implementation/src/test/java/io/smallrye/config/ConfigSourceSortTestCase.java diff --git a/implementation/src/main/java/io/smallrye/config/ConfigValueConfigSourceWrapper.java b/implementation/src/main/java/io/smallrye/config/ConfigValueConfigSourceWrapper.java index 34df75c17..5865f4fdc 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigValueConfigSourceWrapper.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigValueConfigSourceWrapper.java @@ -62,6 +62,10 @@ public int getOrdinal() { return configSource.getOrdinal(); } + ConfigSource unwrap() { + return configSource; + } + static ConfigValueConfigSource wrap(final ConfigSource configSource) { if (configSource instanceof ConfigValueConfigSource) { return (ConfigValueConfigSource) configSource; diff --git a/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java b/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java index caae5b254..60676b042 100644 --- a/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java +++ b/implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java @@ -17,6 +17,7 @@ import static io.smallrye.config.ConfigSourceInterceptor.EMPTY; import static io.smallrye.config.SmallRyeConfigSourceInterceptor.configSourceInterceptor; +import static java.util.stream.Collectors.toList; import java.io.Serializable; import java.lang.reflect.Type; @@ -48,20 +49,8 @@ * @author Jeff Mesnil (c) 2017 Red Hat inc. */ public class SmallRyeConfig implements Config, Serializable { - private static final long serialVersionUID = 8138651532357898263L; - static final Comparator CONFIG_SOURCE_COMPARATOR = new Comparator() { - @Override - public int compare(ConfigSource o1, ConfigSource o2) { - int res = Integer.compare(o2.getOrdinal(), o1.getOrdinal()); - // if 2 config sources have the same ordinal, - // provide consistent order by sorting them - // according to their name. - return res != 0 ? res : o2.getName().compareTo(o1.getName()); - } - }; - private final AtomicReference configSources; private final Map> converters; private final Map>> optionalConverters = new ConcurrentHashMap<>(); @@ -229,14 +218,7 @@ public Iterable getConfigSources() { */ @Deprecated public void addConfigSource(ConfigSource configSource) { - configSources.updateAndGet(configSources -> { - List currentSources = configSources.getSources(); - - int oldSize = currentSources.size(); - List newSources = Arrays.asList(currentSources.toArray(new ConfigSource[oldSize + 1])); - newSources.set(oldSize, configSource); - return new ConfigSources(newSources, configSources); - }); + configSources.updateAndGet(configSources -> new ConfigSources(configSources, configSource)); } public T convert(String value, Class asType) { @@ -270,7 +252,7 @@ private static class ConfigSources implements Serializable { private static final long serialVersionUID = 3483018375584151712L; private final List sources; - private final List interceptors; + private final List interceptors; private final ConfigSourceInterceptorContext interceptorChain; /** @@ -285,23 +267,21 @@ private static class ConfigSources implements Serializable { * @param interceptors the Interceptors to be part of Config. */ ConfigSources(final List sources, final List interceptors) { - sources.sort(CONFIG_SOURCE_COMPARATOR); - interceptors.sort(Comparator.comparingInt(InterceptorWithPriority::getPriority).reversed()); + final List sortInterceptors = new ArrayList<>(); + sortInterceptors.addAll(sources.stream().map(ConfigSourceInterceptorWithPriority::new).collect(toList())); + sortInterceptors.addAll(interceptors.stream().map(ConfigSourceInterceptorWithPriority::new).collect(toList())); + sortInterceptors.sort(Comparator.comparingInt(ConfigSourceInterceptorWithPriority::getPriority)); - List initializedInterceptors = new ArrayList<>(); + final List initInterceptors = new ArrayList<>(); SmallRyeConfigSourceInterceptorContext current = new SmallRyeConfigSourceInterceptorContext(EMPTY, null); - for (int i = sources.size() - 1; i >= 0; i--) { - current = new SmallRyeConfigSourceInterceptorContext(configSourceInterceptor(sources.get(i)), current); - } - - for (int i = interceptors.size() - 1; i >= 0; i--) { - ConfigSourceInterceptor interceptor = interceptors.get(i).getInterceptor(current); - current = new SmallRyeConfigSourceInterceptorContext(interceptor, current); - initializedInterceptors.add(interceptor); + for (ConfigSourceInterceptorWithPriority configSourceInterceptor : sortInterceptors) { + final ConfigSourceInterceptorWithPriority initInterceptor = configSourceInterceptor.getInterceptor(current); + current = new SmallRyeConfigSourceInterceptorContext(initInterceptor.getInterceptor(), current); + initInterceptors.add(initInterceptor); } - this.sources = Collections.unmodifiableList(sources); - this.interceptors = Collections.unmodifiableList(initializedInterceptors); + this.sources = Collections.unmodifiableList(getSources(initInterceptors)); + this.interceptors = Collections.unmodifiableList(initInterceptors); this.interceptorChain = current; } @@ -311,31 +291,42 @@ private static class ConfigSources implements Serializable { * Config Sources are added to the Config. * * @param sources the Config Sources to be part of Config. - * @param configSources the previous ConfigSources + * @param configSource the new ConfigSource to add into the interceptor the chain. */ - ConfigSources(final List sources, final ConfigSources configSources) { - sources.sort(CONFIG_SOURCE_COMPARATOR); + ConfigSources(final ConfigSources sources, final ConfigSource configSource) { + final int oldSize = sources.getInterceptors().size(); + final List newInterceptors = Arrays + .asList(sources.getInterceptors().toArray(new ConfigSourceInterceptorWithPriority[oldSize + 1])); + newInterceptors.set(oldSize, new ConfigSourceInterceptorWithPriority(configSource)); + newInterceptors.sort(Comparator.comparingInt(ConfigSourceInterceptorWithPriority::getPriority)); SmallRyeConfigSourceInterceptorContext current = new SmallRyeConfigSourceInterceptorContext(EMPTY, null); - - for (int i = sources.size() - 1; i >= 0; i--) { - current = new SmallRyeConfigSourceInterceptorContext(configSourceInterceptor(sources.get(i)), current); - } - - for (int i = configSources.getInterceptors().size() - 1; i >= 0; i--) { - current = new SmallRyeConfigSourceInterceptorContext(configSources.getInterceptors().get(i), current); + for (ConfigSourceInterceptorWithPriority configSourceInterceptor : newInterceptors) { + final ConfigSourceInterceptor interceptor = configSourceInterceptor.getInterceptor(); + current = new SmallRyeConfigSourceInterceptorContext(interceptor, current); } - this.sources = Collections.unmodifiableList(sources); - this.interceptors = configSources.getInterceptors(); + this.sources = Collections.unmodifiableList(getSources(newInterceptors)); + this.interceptors = Collections.unmodifiableList(newInterceptors); this.interceptorChain = current; } + private List getSources(final List interceptors) { + final List sources = interceptors.stream() + .map(ConfigSourceInterceptorWithPriority::getInterceptor) + .filter(SmallRyeConfigSourceInterceptor.class::isInstance) + .map(SmallRyeConfigSourceInterceptor.class::cast) + .map(SmallRyeConfigSourceInterceptor::getSource) + .collect(toList()); + Collections.reverse(sources); + return sources; + } + List getSources() { return sources; } - List getInterceptors() { + List getInterceptors() { return interceptors; } @@ -343,4 +334,49 @@ ConfigSourceInterceptorContext getInterceptorChain() { return interceptorChain; } } + + static class ConfigSourceInterceptorWithPriority implements Comparable, Serializable { + private static final long serialVersionUID = 1637460029437579033L; + + final Function interceptor; + final int priority; + final String name; + + public ConfigSourceInterceptorWithPriority(final InterceptorWithPriority interceptor) { + this.interceptor = interceptor::getInterceptor; + this.priority = interceptor.getPriority(); + this.name = "undefined"; + } + + public ConfigSourceInterceptorWithPriority(final ConfigSource configSource) { + this.interceptor = context -> configSourceInterceptor(configSource); + this.priority = configSource.getOrdinal(); + this.name = configSource.getName(); + } + + public ConfigSourceInterceptorWithPriority(final ConfigSourceInterceptor interceptor, final int priority, + final String name) { + this.interceptor = (Serializable & Function) context -> interceptor; + this.priority = priority; + this.name = name; + } + + public ConfigSourceInterceptor getInterceptor() { + return interceptor.apply(null); + } + + public ConfigSourceInterceptorWithPriority getInterceptor(final ConfigSourceInterceptorContext context) { + return new ConfigSourceInterceptorWithPriority(interceptor.apply(context), priority, name); + } + + public int getPriority() { + return priority; + } + + @Override + public int compareTo(final ConfigSourceInterceptorWithPriority other) { + int res = Integer.compare(this.priority, other.priority); + return res != 0 ? res : this.name.compareTo(other.name); + } + } } diff --git a/implementation/src/main/java/io/smallrye/config/SmallRyeConfigBuilder.java b/implementation/src/main/java/io/smallrye/config/SmallRyeConfigBuilder.java index e57f2b321..f609f3638 100644 --- a/implementation/src/main/java/io/smallrye/config/SmallRyeConfigBuilder.java +++ b/implementation/src/main/java/io/smallrye/config/SmallRyeConfigBuilder.java @@ -315,7 +315,8 @@ Converter getConverter() { } static class InterceptorWithPriority { - static final OptionalInt OPTIONAL_DEFAULT_PRIORITY = OptionalInt.of(ConfigSourceInterceptorFactory.DEFAULT_PRIORITY); + private static final OptionalInt OPTIONAL_DEFAULT_PRIORITY = OptionalInt + .of(ConfigSourceInterceptorFactory.DEFAULT_PRIORITY); private final ConfigSourceInterceptorFactory factory; private final int priority; @@ -346,11 +347,11 @@ private InterceptorWithPriority(ConfigSourceInterceptorFactory factory) { this.priority = factory.getPriority().orElse(ConfigSourceInterceptorFactory.DEFAULT_PRIORITY); } - public ConfigSourceInterceptor getInterceptor(ConfigSourceInterceptorContext context) { + ConfigSourceInterceptor getInterceptor(ConfigSourceInterceptorContext context) { return factory.getInterceptor(context); } - public int getPriority() { + int getPriority() { return priority; } } diff --git a/implementation/src/main/java/io/smallrye/config/SmallRyeConfigSourceInterceptor.java b/implementation/src/main/java/io/smallrye/config/SmallRyeConfigSourceInterceptor.java index 838fffbb0..fd52bc665 100644 --- a/implementation/src/main/java/io/smallrye/config/SmallRyeConfigSourceInterceptor.java +++ b/implementation/src/main/java/io/smallrye/config/SmallRyeConfigSourceInterceptor.java @@ -43,6 +43,14 @@ public Iterator iterateValues(final ConfigSourceInterceptorContext return values.iterator(); } + public ConfigSource getSource() { + if (configSource instanceof ConfigValueConfigSourceWrapper) { + return ((ConfigValueConfigSourceWrapper) configSource).unwrap(); + } + + return configSource; + } + public static ConfigSourceInterceptor configSourceInterceptor(final ConfigSource configSource) { return new SmallRyeConfigSourceInterceptor(configSource); } diff --git a/implementation/src/test/java/io/smallrye/config/ConfigSourceSortTestCase.java b/implementation/src/test/java/io/smallrye/config/ConfigSourceSortTestCase.java deleted file mode 100644 index 41d910ea6..000000000 --- a/implementation/src/test/java/io/smallrye/config/ConfigSourceSortTestCase.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2019 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.smallrye.config; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Comparator; -import java.util.Map; - -import org.eclipse.microprofile.config.spi.ConfigSource; -import org.junit.jupiter.api.Test; - -/** - * - */ -public class ConfigSourceSortTestCase { - - static final Comparator CMP = SmallRyeConfig.CONFIG_SOURCE_COMPARATOR; - - static final class DummyConfigSource implements ConfigSource { - private final int ordinal; - - DummyConfigSource(final int ordinal) { - this.ordinal = ordinal; - } - - public int getOrdinal() { - return ordinal; - } - - public Map getProperties() { - return null; - } - - public String getValue(final String propertyName) { - return null; - } - - public String getName() { - return "placeholder"; - } - } - - static ConfigSource src(int ordinal) { - return new DummyConfigSource(ordinal); - } - - @Test - public void ensureCorrectOrdinalSort() { - assertEquals(1, CMP.compare(src(100), src(200))); - assertEquals(1, CMP.compare(src(-100), src(200))); - assertEquals(0, CMP.compare(src(0), src(0))); - assertEquals(0, CMP.compare(src(-100), src(-100))); - assertEquals(1, CMP.compare(src(0), src(Integer.MAX_VALUE))); - assertEquals(1, CMP.compare(src(Integer.MIN_VALUE), src(0))); - assertEquals(-1, CMP.compare(src(0), src(Integer.MIN_VALUE))); - assertEquals(-1, CMP.compare(src(Integer.MAX_VALUE), src(0))); - } -} diff --git a/implementation/src/test/java/io/smallrye/config/ConfigSourceWrapperTestCase.java b/implementation/src/test/java/io/smallrye/config/ConfigSourceWrapperTestCase.java index f66591562..b0835c669 100644 --- a/implementation/src/test/java/io/smallrye/config/ConfigSourceWrapperTestCase.java +++ b/implementation/src/test/java/io/smallrye/config/ConfigSourceWrapperTestCase.java @@ -105,6 +105,11 @@ public String getValue(final String propertyName) { public String getName() { return delegate.getName(); } + + @Override + public int getOrdinal() { + return delegate.getOrdinal(); + } } static T assertIsInstance(Class expected, Object thing) {