From 25186278fceb79de296cd8d232dbf82ea6aa1de0 Mon Sep 17 00:00:00 2001 From: Steve Hawkins Date: Thu, 6 Nov 2025 08:24:34 -0500 Subject: [PATCH] fix: consolidating config logic closes: #42000 Signed-off-by: Steve Hawkins --- core/src/main/java/org/keycloak/Config.java | 106 ++++++++---------- .../MicroProfileConfigProvider.java | 49 +------- .../component/ComponentModelScope.java | 49 +------- .../component/ComponentModelScopeTest.java | 60 ++++++++++ .../keycloak/utils/JsonConfigProvider.java | 88 ++------------- 5 files changed, 122 insertions(+), 230 deletions(-) create mode 100644 server-spi-private/src/test/java/org/keycloak/component/ComponentModelScopeTest.java diff --git a/core/src/main/java/org/keycloak/Config.java b/core/src/main/java/org/keycloak/Config.java index e48b7fa975e..af42377b9a9 100755 --- a/core/src/main/java/org/keycloak/Config.java +++ b/core/src/main/java/org/keycloak/Config.java @@ -20,7 +20,9 @@ package org.keycloak; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.function.Function; import org.keycloak.common.util.StringPropertyReplacer; import org.keycloak.common.util.StringPropertyReplacer.PropertyResolver; @@ -122,7 +124,7 @@ public class Config { } - public static class SystemPropertiesScope implements Scope { + public static class SystemPropertiesScope extends AbstractScope { protected String prefix; @@ -132,66 +134,10 @@ public class Config { @Override public String get(String key) { - return get(key, null); - } - - @Override - public String get(String key, String defaultValue) { - String v = System.getProperty(prefix + key, defaultValue); + String v = System.getProperty(prefix + key, null); return v != null && !v.isEmpty() ? v : null; } - @Override - public String[] getArray(String key) { - String value = get(key); - if (value != null) { - String[] a = value.split(","); - for (int i = 0; i < a.length; i++) { - a[i] = a[i].trim(); - } - return a; - } else { - return null; - } - } - - @Override - public Integer getInt(String key) { - return getInt(key, null); - } - - @Override - public Integer getInt(String key, Integer defaultValue) { - String v = get(key, null); - return v != null ? Integer.valueOf(v) : defaultValue; - } - - @Override - public Long getLong(String key) { - return getLong(key, null); - } - - @Override - public Long getLong(String key, Long defaultValue) { - String v = get(key, null); - return v != null ? Long.valueOf(v) : defaultValue; - } - - @Override - public Boolean getBoolean(String key) { - return getBoolean(key, null); - } - - @Override - public Boolean getBoolean(String key, Boolean defaultValue) { - String v = get(key, null); - if (v != null) { - return Boolean.valueOf(v); - } else { - return defaultValue; - } - } - @Override public Scope scope(String... scope) { StringBuilder sb = new StringBuilder(); @@ -226,15 +172,21 @@ public class Config { String[] getArray(String key); - Integer getInt(String key); + default Integer getInt(String key) { + return getInt(key, null); + } Integer getInt(String key, Integer defaultValue); - Long getLong(String key); + default Long getLong(String key) { + return getLong(key, null); + } Long getLong(String key, Long defaultValue); - Boolean getBoolean(String key); + default Boolean getBoolean(String key) { + return getBoolean(key, null); + } Boolean getBoolean(String key, Boolean defaultValue); @@ -257,4 +209,36 @@ public class Config { */ Scope root(); } + + public static abstract class AbstractScope implements Scope { + + @Override + public String get(String key, String defaultValue) { + return getValue(key, Function.identity(), String.class, defaultValue); + } + + @Override + public Integer getInt(String key, Integer defaultValue) { + return getValue(key, Integer::valueOf, Integer.class, defaultValue); + } + + @Override + public String[] getArray(String key) { + return getValue(key, s -> s.split("\\s*,\\s*"), String[].class, null); + } + + @Override + public Long getLong(String key, Long defaultValue) { + return getValue(key, Long::valueOf, Long.class, defaultValue); + } + + @Override + public Boolean getBoolean(String key, Boolean defaultValue) { + return getValue(key, Boolean::valueOf, Boolean.class, defaultValue); + } + + protected T getValue(String key, Function conversion, Class type, T defaultValue) { + return Optional.ofNullable(get(key)).map(conversion).orElse(defaultValue); + } + } } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/MicroProfileConfigProvider.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/MicroProfileConfigProvider.java index 05381f99ec6..9e435385d23 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/MicroProfileConfigProvider.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/MicroProfileConfigProvider.java @@ -19,10 +19,12 @@ package org.keycloak.quarkus.runtime.configuration; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.keycloak.Config; +import org.keycloak.Config.AbstractScope; import org.keycloak.Config.Scope; import io.smallrye.config.SmallRyeConfig; @@ -64,7 +66,7 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider { return new MicroProfileScope(SPI_PREFIX, scope); } - public class MicroProfileScope implements Config.Scope { + public class MicroProfileScope extends AbstractScope { private final String prefix; private final String separatorPrefix; @@ -80,47 +82,7 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider { @Override public String get(String key) { - return getValue(key, String.class, null); - } - - @Override - public String get(String key, String defaultValue) { - return getValue(key, String.class, defaultValue); - } - - @Override - public String[] getArray(String key) { - return getValue(key, String[].class, null); - } - - @Override - public Integer getInt(String key) { - return getValue(key, Integer.class, null); - } - - @Override - public Integer getInt(String key, Integer defaultValue) { - return getValue(key, Integer.class, defaultValue); - } - - @Override - public Long getLong(String key) { - return getValue(key, Long.class, null); - } - - @Override - public Long getLong(String key, Long defaultValue) { - return getValue(key, Long.class, defaultValue); - } - - @Override - public Boolean getBoolean(String key) { - return getValue(key, Boolean.class, null); - } - - @Override - public Boolean getBoolean(String key, Boolean defaultValue) { - return getValue(key, Boolean.class, defaultValue); + return get(key, null); } @Override @@ -135,7 +97,8 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider { .collect(Collectors.toSet()); } - private T getValue(String key, Class clazz, T defaultValue) { + @Override + protected T getValue(String key, Function conversion, Class clazz, T defaultValue) { if (NS_KEYCLOAK_PREFIX.equals(separatorPrefix)) { return config.getOptionalValue(separatorPrefix.concat(key), clazz).orElse(defaultValue); } diff --git a/server-spi-private/src/main/java/org/keycloak/component/ComponentModelScope.java b/server-spi-private/src/main/java/org/keycloak/component/ComponentModelScope.java index a1b89ee72ef..3ceeeff073f 100644 --- a/server-spi-private/src/main/java/org/keycloak/component/ComponentModelScope.java +++ b/server-spi-private/src/main/java/org/keycloak/component/ComponentModelScope.java @@ -18,13 +18,14 @@ package org.keycloak.component; import java.util.Set; +import org.keycloak.Config.AbstractScope; import org.keycloak.Config.Scope; /** * * @author hmlnarik */ -public class ComponentModelScope implements Scope { +public class ComponentModelScope extends AbstractScope { private final Scope origScope; private final ComponentModel componentConfig; @@ -62,52 +63,8 @@ public class ComponentModelScope implements Scope { @Override public String get(String key) { - return get(key, null); - } - - @Override - public String get(String key, String defaultValue) { final String res = componentConfig.get(prefix + key, null); - return (res == null) ? origScope.get(key, defaultValue) : res; - } - - @Override - public String[] getArray(String key) { - final String[] res = get(prefix + key, "").split("\\s*,\\s*"); - return (res == null) ? origScope.getArray(key) : res; - } - - @Override - public Integer getInt(String key) { - return getInt(key, null); - } - - @Override - public Integer getInt(String key, Integer defaultValue) { - final String res = componentConfig.get(prefix + key, null); - return (res == null) ? origScope.getInt(key, defaultValue) : Integer.valueOf(res); - } - - @Override - public Long getLong(String key) { - return getLong(key, null); - } - - @Override - public Long getLong(String key, Long defaultValue) { - final String res = componentConfig.get(prefix + key, null); - return (res == null) ? origScope.getLong(key, defaultValue) : Long.valueOf(res); - } - - @Override - public Boolean getBoolean(String key) { - return getBoolean(key, null); - } - - @Override - public Boolean getBoolean(String key, Boolean defaultValue) { - final String res = componentConfig.get(prefix + key, null); - return (res == null) ? origScope.getBoolean(key, defaultValue) : Boolean.valueOf(res); + return (res == null) ? origScope.get(key) : res; } @Override diff --git a/server-spi-private/src/test/java/org/keycloak/component/ComponentModelScopeTest.java b/server-spi-private/src/test/java/org/keycloak/component/ComponentModelScopeTest.java new file mode 100644 index 00000000000..c748df6d092 --- /dev/null +++ b/server-spi-private/src/test/java/org/keycloak/component/ComponentModelScopeTest.java @@ -0,0 +1,60 @@ +package org.keycloak.component; + +import java.util.Set; + +import org.keycloak.Config.AbstractScope; +import org.keycloak.Config.Scope; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class ComponentModelScopeTest { + + @Test public void testGetters() { + Scope scope = new AbstractScope() { + + @Override + public Scope scope(String... scope) { + return null; + } + + @Override + public Scope root() { + return null; + } + + @Override + public Set getPropertyNames() { + return null; + } + + @Override + public String get(String key) { + if (key.equals("base")) { + return "x, y"; + } + if (key.equals("int")) { + return "1"; + } + return null; + } + }; + + ComponentModel model = new ComponentModel(); + model.put("component", "a"); + model.put("string", "abc"); + + ComponentModelScope componentModelScope = new ComponentModelScope(scope, model); + + assertArrayEquals(new String[] {"x", "y"}, componentModelScope.getArray("base")); + assertArrayEquals(new String[] {"a"}, componentModelScope.getArray("component")); + + assertEquals(Integer.valueOf(1), componentModelScope.getInt("int")); + assertEquals(Long.valueOf(1), componentModelScope.getLong("int")); + assertEquals("abc", componentModelScope.get("string", "default")); + assertEquals(null, componentModelScope.get("doesn't exist")); + } + +} diff --git a/services/src/test/java/org/keycloak/utils/JsonConfigProvider.java b/services/src/test/java/org/keycloak/utils/JsonConfigProvider.java index 0752bb6c775..46404891d81 100755 --- a/services/src/test/java/org/keycloak/utils/JsonConfigProvider.java +++ b/services/src/test/java/org/keycloak/utils/JsonConfigProvider.java @@ -17,9 +17,11 @@ package org.keycloak.utils; +import java.util.Optional; import java.util.Set; import org.keycloak.Config; +import org.keycloak.Config.AbstractScope; import org.keycloak.Config.Scope; import org.keycloak.common.util.StringPropertyReplacer; import org.keycloak.common.util.SystemEnvProperties; @@ -73,7 +75,7 @@ public class JsonConfigProvider implements Config.ConfigProvider { return StringPropertyReplacer.replaceProperties(value, SystemEnvProperties.UNFILTERED::getProperty); } - public class JsonScope implements Config.Scope { + public class JsonScope extends AbstractScope { private JsonNode config; @@ -83,20 +85,12 @@ public class JsonConfigProvider implements Config.ConfigProvider { @Override public String get(String key) { - return get(key, null); + return Optional.ofNullable(config).map(c -> c.get(key)).map(this::toString).orElse(null); } - @Override - public String get(String key, String defaultValue) { - if (config == null) { - return defaultValue; - } - JsonNode n = config.get(key); - if (n == null) { - return defaultValue; - } + private String toString(JsonNode n) { String v = replaceProperties(n.textValue()); - return !v.isEmpty() ? v : defaultValue; + return !v.isEmpty() ? v : null; } @Override @@ -111,77 +105,11 @@ public class JsonConfigProvider implements Config.ConfigProvider { } else if (n.isArray()) { String[] a = new String[n.size()]; for (int i = 0; i < a.length; i++) { - a[i] = replaceProperties(n.get(i).textValue()); + a[i] = toString(n.get(i)); } return a; } else { - return new String[] { replaceProperties(n.textValue()) }; - } - } - - @Override - public Integer getInt(String key) { - return getInt(key, null); - } - - @Override - public Integer getInt(String key, Integer defaultValue) { - if (config == null) { - return defaultValue; - } - JsonNode n = config.get(key); - if (n == null) { - return defaultValue; - } - if (n.isTextual()) { - String v = replaceProperties(n.textValue()); - return !v.isEmpty() ? Integer.valueOf(v) : defaultValue; - } else { - return n.intValue(); - } - } - - @Override - public Long getLong(String key) { - return getLong(key, null); - } - - @Override - public Long getLong(String key, Long defaultValue) { - if (config == null) { - return defaultValue; - } - JsonNode n = config.get(key); - if (n == null) { - return defaultValue; - } - if (n.isTextual()) { - String v = replaceProperties(n.textValue()); - return !v.isEmpty() ? Long.valueOf(v) : defaultValue; - } else { - return n.longValue(); - } - } - - @Override - public Boolean getBoolean(String key) { - return getBoolean(key, null); - } - - @Override - public Boolean getBoolean(String key, Boolean defaultValue) { - if (config == null) { - return defaultValue; - } - JsonNode n = config.get(key); - if (n == null) { - return defaultValue; - } - if (n.isTextual()) { - String v = replaceProperties(n.textValue()); - return !v.isEmpty() ? Boolean.valueOf(v) : defaultValue; - } else { - return n.booleanValue(); + return new String[] { toString(n) }; } }