From 2e7f67fa91aa882be3dd28026d759dae5fc6f56b Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:42:33 -0400 Subject: [PATCH 01/28] Add Uri Loader SPI --- .../src/main/java/module-info.java | 5 ++- .../{Parsers.java => ConfigParsers.java} | 14 +++---- .../io/avaje/config/ConfigServiceLoader.java | 22 +++++++--- .../java/io/avaje/config/CoreComponents.java | 26 ++++++++---- .../io/avaje/config/CoreConfiguration.java | 2 +- .../config/CoreConfigurationBuilder.java | 12 +++++- .../main/java/io/avaje/config/EnvLoader.java | 27 ++++++++++++ .../main/java/io/avaje/config/FileWatch.java | 4 +- .../java/io/avaje/config/InitialLoader.java | 32 ++++++++++++++- .../java/io/avaje/config/URIConfigLoader.java | 24 +++++++++++ .../main/java/io/avaje/config/URILoaders.java | 41 +++++++++++++++++++ .../java/io/avaje/config/FileWatchTest.java | 2 +- 12 files changed, 182 insertions(+), 29 deletions(-) rename avaje-config/src/main/java/io/avaje/config/{Parsers.java => ConfigParsers.java} (80%) create mode 100644 avaje-config/src/main/java/io/avaje/config/EnvLoader.java create mode 100644 avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java create mode 100644 avaje-config/src/main/java/io/avaje/config/URILoaders.java diff --git a/avaje-config-toml/src/main/java/module-info.java b/avaje-config-toml/src/main/java/module-info.java index f796a14..357c7c4 100644 --- a/avaje-config-toml/src/main/java/module-info.java +++ b/avaje-config-toml/src/main/java/module-info.java @@ -1,12 +1,13 @@ +import io.avaje.config.ConfigExtension; import io.avaje.config.toml.TomlParser; module io.avaje.config.toml { - requires io.avaje.config; + requires transitive io.avaje.config; requires org.tomlj; exports io.avaje.config.toml; - provides io.avaje.config.ConfigExtension with TomlParser; + provides ConfigExtension with TomlParser; } diff --git a/avaje-config/src/main/java/io/avaje/config/Parsers.java b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java similarity index 80% rename from avaje-config/src/main/java/io/avaje/config/Parsers.java rename to avaje-config/src/main/java/io/avaje/config/ConfigParsers.java index d86f7a0..8b675ea 100644 --- a/avaje-config/src/main/java/io/avaje/config/Parsers.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java @@ -6,13 +6,13 @@ import java.util.Set; /** - * Holds the non-properties ConfigParsers. + * Holds the ConfigParsers for various extension types. */ -final class Parsers { +public final class ConfigParsers { private final Map parserMap = new HashMap<>(); - Parsers(List otherParsers) { + ConfigParsers(List otherParsers) { parserMap.put("properties", new PropertiesParser()); if (!"true".equals(System.getProperty("skipYaml"))) { initYamlParser(); @@ -45,28 +45,28 @@ private void initParsers(List otherParsers) { /** * Return the extension ConfigParser pairs. */ - Set> entrySet() { + public Set> entrySet() { return parserMap.entrySet(); } /** * Return the ConfigParser for the given extension. */ - ConfigParser get(String extension) { + public ConfigParser get(String extension) { return parserMap.get(extension.toLowerCase()); } /** * Return true if the extension has a matching parser. */ - boolean supportsExtension(String extension) { + public boolean supportsExtension(String extension) { return parserMap.containsKey(extension.toLowerCase()); } /** * Return the set of supported extensions. */ - Set supportedExtensions() { + public Set supportedExtensions() { return parserMap.keySet(); } } diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 495bb28..a2b5f3a 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -5,8 +5,8 @@ import java.util.ServiceLoader; /** - * Load all the avaje-config extensions via ServiceLoader using the single - * common ConfigExtension interface. + * Load all the avaje-config extensions via ServiceLoader using the single common ConfigExtension + * interface. */ final class ConfigServiceLoader { @@ -21,13 +21,15 @@ static ConfigServiceLoader get() { private final ModificationEventRunner eventRunner; private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); - private final Parsers parsers; + private final URILoaders uriLoaders; + private final ConfigParsers parsers; ConfigServiceLoader() { ModificationEventRunner _eventRunner = null; ConfigurationLog _log = null; ResourceLoader _resourceLoader = null; List otherParsers = new ArrayList<>(); + List loaders = new ArrayList<>(); for (var spi : ServiceLoader.load(ConfigExtension.class)) { if (spi instanceof ConfigurationSource) { @@ -36,6 +38,8 @@ static ConfigServiceLoader get() { plugins.add((ConfigurationPlugin) spi); } else if (spi instanceof ConfigParser) { otherParsers.add((ConfigParser) spi); + } else if (spi instanceof URIConfigLoader) { + loaders.add((URIConfigLoader) spi); } else if (spi instanceof ConfigurationLog) { _log = (ConfigurationLog) spi; } else if (spi instanceof ResourceLoader) { @@ -47,14 +51,20 @@ static ConfigServiceLoader get() { this.log = _log == null ? new DefaultConfigurationLog() : _log; this.resourceLoader = _resourceLoader == null ? new DefaultResourceLoader() : _resourceLoader; - this.eventRunner = _eventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : _eventRunner; - this.parsers = new Parsers(otherParsers); + this.eventRunner = + _eventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : _eventRunner; + this.parsers = new ConfigParsers(otherParsers); + this.uriLoaders = new URILoaders(loaders); } - Parsers parsers() { + ConfigParsers parsers() { return parsers; } + public URILoaders uriLoaders() { + return uriLoaders; + } + ConfigurationLog log() { return log; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 586106b..5e86166 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -1,20 +1,27 @@ package io.avaje.config; -import java.util.Collections; import java.util.List; final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; - private final Parsers parsers; + private final ConfigParsers parsers; + private final URILoaders uriLoaders; private final List sources; private final List plugins; - CoreComponents(ModificationEventRunner runner, ConfigurationLog log, Parsers parsers, List sources, List plugins) { + CoreComponents( + ModificationEventRunner runner, + ConfigurationLog log, + ConfigParsers parsers, + URILoaders uriLoaders, + List sources, + List plugins) { this.runner = runner; this.log = log; this.parsers = parsers; + this.uriLoaders = uriLoaders; this.sources = sources; this.plugins = plugins; } @@ -23,15 +30,20 @@ final class CoreComponents { CoreComponents() { this.runner = new CoreConfiguration.ForegroundEventRunner(); this.log = new DefaultConfigurationLog(); - this.parsers = new Parsers(Collections.emptyList()); - this.sources = Collections.emptyList(); - this.plugins = Collections.emptyList(); + this.parsers = new ConfigParsers(List.of()); + this.uriLoaders = new URILoaders(List.of()); + this.sources = List.of(); + this.plugins = List.of(); } - Parsers parsers() { + ConfigParsers parsers() { return parsers; } + public URILoaders uriLoaders() { + return uriLoaders; + } + ConfigurationLog log() { return log; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java index f5abaf2..e8fc571 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java @@ -27,7 +27,7 @@ @NullMarked final class CoreConfiguration implements Configuration { - private final Parsers parsers; + private final ConfigParsers parsers; private final ConfigurationLog log; private final ModifyAwareProperties properties; private final ReentrantLock lock = new ReentrantLock(); diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 45dd828..36fdd3c 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -18,7 +18,8 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); - private final Parsers parsers = serviceLoader.parsers(); + private final ConfigParsers parsers = serviceLoader.parsers(); + private final URILoaders uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); private ModificationEventRunner eventRunner = serviceLoader.eventRunner(); @@ -130,7 +131,14 @@ public Configuration.Builder includeResourceLoading() { @Override public Configuration build() { - var components = new CoreComponents(eventRunner, log, parsers, serviceLoader.sources(), serviceLoader.plugins()); + var components = + new CoreComponents( + eventRunner, + log, + parsers, + uriLoaders, + serviceLoader.sources(), + serviceLoader.plugins()); if (includeResourceLoading) { log.preInitialisation(); initialLoader = new InitialLoader(components, resourceLoader); diff --git a/avaje-config/src/main/java/io/avaje/config/EnvLoader.java b/avaje-config/src/main/java/io/avaje/config/EnvLoader.java new file mode 100644 index 0000000..3d9a5df --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/EnvLoader.java @@ -0,0 +1,27 @@ +package io.avaje.config; + +import static java.util.stream.Collectors.toMap; + +import java.net.URI; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +final class EnvLoader implements URIConfigLoader { + + private static final Set> envVariables = System.getenv().entrySet(); + + @Override + public String supportedScheme() { + + return "env"; + } + + @Override + public Map load(URI uri, ConfigParsers __) { + + return envVariables.stream() + .filter(e -> e.getKey().contains(uri.getPath().substring(1))) + .collect(toMap(Entry::getKey, Entry::getValue)); + } +} diff --git a/avaje-config/src/main/java/io/avaje/config/FileWatch.java b/avaje-config/src/main/java/io/avaje/config/FileWatch.java index 39a58af..9ab7f0e 100644 --- a/avaje-config/src/main/java/io/avaje/config/FileWatch.java +++ b/avaje-config/src/main/java/io/avaje/config/FileWatch.java @@ -11,12 +11,12 @@ final class FileWatch { private final ConfigurationLog log; private final Configuration configuration; - private final Parsers parsers; + private final ConfigParsers parsers; private final List files; private final long delay; private final long period; - FileWatch(CoreConfiguration configuration, List loadedFiles, Parsers parsers) { + FileWatch(CoreConfiguration configuration, List loadedFiles, ConfigParsers parsers) { this.log = configuration.log(); this.configuration = configuration; this.delay = configuration.getLong("config.watch.delay", 60); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index c47e626..0b0c082 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -3,11 +3,13 @@ import static io.avaje.config.InitialLoader.Source.FILE; import static io.avaje.config.InitialLoader.Source.RESOURCE; import static java.lang.System.Logger.Level.WARNING; +import static java.util.stream.Collectors.joining; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.net.URI; import java.util.*; import java.util.regex.Pattern; @@ -41,10 +43,12 @@ enum Source { private final ConfigurationLog log; private final InitialLoadContext loadContext; private final Set profileResourceLoaded = new HashSet<>(); - private final Parsers parsers; + private final ConfigParsers parsers; + private final URILoaders uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { this.parsers = components.parsers(); + this.uriLoaders = components.uriLoaders(); this.log = components.log(); this.loadContext = new InitialLoadContext(log, resourceLoader); } @@ -253,8 +257,17 @@ private void loadViaSystemProperty() { } boolean loadWithExtensionCheck(String fileName) { + + // no need to custom URL load regular cp and file schemes + fileName = fileName.replace("classpath:/", "").replace("file:/", ""); + if (fileName.contains(":/")) { + + return loadURI(fileName); + } + var extension = fileName.substring(fileName.lastIndexOf(".") + 1); if ("properties".equals(extension)) { + return loadProperties(fileName, RESOURCE) | loadProperties(fileName, FILE); } else { var parser = parsers.get(extension); @@ -272,6 +285,23 @@ boolean loadWithExtensionCheck(String fileName) { } } + private boolean loadURI(String uriPath) { + var uri = URI.create(uriPath); + final var scheme = uri.getScheme(); + var loader = uriLoaders.get(scheme); + if (loader != null) { + loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, "uri scheme " + scheme)); + return true; + } + + throw new IllegalArgumentException( + "Expecting only properties or " + + uriLoaders.supportedSchemes().stream().map(s -> s + ":/").collect(joining(",")) + + " uris but got [" + + uriPath + + "]"); + } + /** * Evaluate all the configuration entries and return as properties. */ diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java new file mode 100644 index 0000000..3488961 --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -0,0 +1,24 @@ +package io.avaje.config; + +import java.net.URI; +import java.util.Map; + +/** Additional source to load and update configuration. */ +public interface URIConfigLoader extends ConfigExtension { + + /** URI Scheme Supported by this loader */ + String supportedScheme(); + + /** + * Load additional configuration. + * + *

The {@link Configuration#setProperty(String, String)} method is used when loading the + * additional properties from the source. + * + *

Also note that the source can additionally use {@link Configuration#schedule(long, long, + * Runnable)} to schedule a period task to for example refresh data etc. + * + * @param configuration The configuration with initially properties. + */ + Map load(URI uri, ConfigParsers parsers); +} diff --git a/avaje-config/src/main/java/io/avaje/config/URILoaders.java b/avaje-config/src/main/java/io/avaje/config/URILoaders.java new file mode 100644 index 0000000..f3a687e --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/URILoaders.java @@ -0,0 +1,41 @@ +package io.avaje.config; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** Holds the non-properties ConfigParsers. */ +public final class URILoaders { + + private final Map parserMap = new HashMap<>(); + + URILoaders(List loaders) { + parserMap.put("env", new EnvLoader()); + for (var parser : loaders) { + + parserMap.put(parser.supportedScheme(), parser); + } + } + + /** Return the extension ConfigParser pairs. */ + public Set> entrySet() { + return parserMap.entrySet(); + } + + /** Return the ConfigParser for the given extension. */ + public URIConfigLoader get(String extension) { + return parserMap.get(extension.toLowerCase()); + } + + /** Return true if the extension has a matching parser. */ + public boolean supportsScheme(String extension) { + return parserMap.containsKey(extension.toLowerCase()); + } + + /** Return the set of supported extensions. */ + public Set supportedSchemes() { + return parserMap.keySet(); + } +} diff --git a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java index 1eeb5d0..b8c1eb7 100644 --- a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java +++ b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java @@ -137,7 +137,7 @@ void test_check_whenFileWritten() throws Exception { } private static FileWatch fileWatch(CoreConfiguration config, List files) { - return new FileWatch(config, files, new Parsers(Collections.emptyList())); + return new FileWatch(config, files, new ConfigParsers(Collections.emptyList())); } private void writeContent(String content) throws IOException { From 9c09b7b831bdecc09b1444563b0d53f4c608961c Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:27:46 -0400 Subject: [PATCH 02/28] Delete EnvLoader.java --- .../main/java/io/avaje/config/EnvLoader.java | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 avaje-config/src/main/java/io/avaje/config/EnvLoader.java diff --git a/avaje-config/src/main/java/io/avaje/config/EnvLoader.java b/avaje-config/src/main/java/io/avaje/config/EnvLoader.java deleted file mode 100644 index 3d9a5df..0000000 --- a/avaje-config/src/main/java/io/avaje/config/EnvLoader.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.avaje.config; - -import static java.util.stream.Collectors.toMap; - -import java.net.URI; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -final class EnvLoader implements URIConfigLoader { - - private static final Set> envVariables = System.getenv().entrySet(); - - @Override - public String supportedScheme() { - - return "env"; - } - - @Override - public Map load(URI uri, ConfigParsers __) { - - return envVariables.stream() - .filter(e -> e.getKey().contains(uri.getPath().substring(1))) - .collect(toMap(Entry::getKey, Entry::getValue)); - } -} From 78ac3e2523863493f852b1a1a9adf1714e85f618 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:31:14 -0400 Subject: [PATCH 03/28] Update URILoaders.java --- avaje-config/src/main/java/io/avaje/config/URILoaders.java | 1 - 1 file changed, 1 deletion(-) diff --git a/avaje-config/src/main/java/io/avaje/config/URILoaders.java b/avaje-config/src/main/java/io/avaje/config/URILoaders.java index f3a687e..ebcf4ce 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoaders.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoaders.java @@ -12,7 +12,6 @@ public final class URILoaders { private final Map parserMap = new HashMap<>(); URILoaders(List loaders) { - parserMap.put("env", new EnvLoader()); for (var parser : loaders) { parserMap.put(parser.supportedScheme(), parser); From 9d4e474e20f477f97544057248f0d9ad24f0e5f1 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:58:18 -0400 Subject: [PATCH 04/28] make an interface --- .../java/io/avaje/config/ConfigParsers.java | 40 +++++++++++-------- .../io/avaje/config/ConfigServiceLoader.java | 2 +- .../java/io/avaje/config/CoreComponents.java | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java index 8b675ea..06ef562 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java @@ -3,16 +3,30 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; -/** - * Holds the ConfigParsers for various extension types. - */ -public final class ConfigParsers { +public interface ConfigParsers { + + /** Return the ConfigParser for the given extension. */ + ConfigParser get(String extension); + + /** Return true if the extension has a matching parser. */ + boolean supportsExtension(String extension); + + /** Return the set of supported extensions. */ + Set supportedExtensions(); + + /** Return the extension ConfigParser pairs. */ + Set> entrySet(); +} + +/** Holds the ConfigParsers for various extension types. */ +final class Parsers implements ConfigParsers { private final Map parserMap = new HashMap<>(); - ConfigParsers(List otherParsers) { + Parsers(List otherParsers) { parserMap.put("properties", new PropertiesParser()); if (!"true".equals(System.getProperty("skipYaml"))) { initYamlParser(); @@ -42,30 +56,22 @@ private void initParsers(List otherParsers) { } } - /** - * Return the extension ConfigParser pairs. - */ + @Override public Set> entrySet() { return parserMap.entrySet(); } - /** - * Return the ConfigParser for the given extension. - */ + @Override public ConfigParser get(String extension) { return parserMap.get(extension.toLowerCase()); } - /** - * Return true if the extension has a matching parser. - */ + @Override public boolean supportsExtension(String extension) { return parserMap.containsKey(extension.toLowerCase()); } - /** - * Return the set of supported extensions. - */ + @Override public Set supportedExtensions() { return parserMap.keySet(); } diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index a2b5f3a..b58f602 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -53,7 +53,7 @@ static ConfigServiceLoader get() { this.resourceLoader = _resourceLoader == null ? new DefaultResourceLoader() : _resourceLoader; this.eventRunner = _eventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : _eventRunner; - this.parsers = new ConfigParsers(otherParsers); + this.parsers = new Parsers(otherParsers); this.uriLoaders = new URILoaders(loaders); } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 5e86166..2202d0a 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -30,7 +30,7 @@ final class CoreComponents { CoreComponents() { this.runner = new CoreConfiguration.ForegroundEventRunner(); this.log = new DefaultConfigurationLog(); - this.parsers = new ConfigParsers(List.of()); + this.parsers = new Parsers(List.of()); this.uriLoaders = new URILoaders(List.of()); this.sources = List.of(); this.plugins = List.of(); From 77eb18fc81810c74e0d1696f5e75c2e4b24dbbb1 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:59:33 -0400 Subject: [PATCH 05/28] Update FileWatchTest.java --- avaje-config/src/test/java/io/avaje/config/FileWatchTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java index b8c1eb7..1eeb5d0 100644 --- a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java +++ b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java @@ -137,7 +137,7 @@ void test_check_whenFileWritten() throws Exception { } private static FileWatch fileWatch(CoreConfiguration config, List files) { - return new FileWatch(config, files, new ConfigParsers(Collections.emptyList())); + return new FileWatch(config, files, new Parsers(Collections.emptyList())); } private void writeContent(String content) throws IOException { From 6546ce6533ffd674b44bf34f2e570a6e53648102 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:33:36 -0400 Subject: [PATCH 06/28] Update URILoaders.java --- avaje-config/src/main/java/io/avaje/config/URILoaders.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avaje-config/src/main/java/io/avaje/config/URILoaders.java b/avaje-config/src/main/java/io/avaje/config/URILoaders.java index ebcf4ce..bceaa93 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoaders.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoaders.java @@ -7,7 +7,7 @@ import java.util.Set; /** Holds the non-properties ConfigParsers. */ -public final class URILoaders { +final class URILoaders { private final Map parserMap = new HashMap<>(); From 6b8306421e59271902187ebe980ebdf47b130d5c Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:17:27 -0400 Subject: [PATCH 07/28] Update InitialLoader.java --- avaje-config/src/main/java/io/avaje/config/InitialLoader.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 0b0c082..e0cf465 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -110,7 +110,6 @@ void loadEnvironmentVars() { */ void loadLocalFiles() { loadMain(RESOURCE); - loadViaProfiles(RESOURCE); // external file configuration overrides the resources configuration loadMain(FILE); // load additional profile RESOURCE(s) if added via loadMain() @@ -259,7 +258,7 @@ private void loadViaSystemProperty() { boolean loadWithExtensionCheck(String fileName) { // no need to custom URL load regular cp and file schemes - fileName = fileName.replace("classpath:/", "").replace("file:/", ""); + fileName = fileName.replaceFirst("classpath:/", "").replaceFirst("file:/", ""); if (fileName.contains(":/")) { return loadURI(fileName); From 61996321de165cffbbf85dd7da30c1bb441cf69a Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:00:10 -0400 Subject: [PATCH 08/28] replace configparsers with a map --- .../java/io/avaje/config/ConfigParsers.java | 78 ------------------- .../io/avaje/config/ConfigServiceLoader.java | 55 +++++++++---- .../java/io/avaje/config/CoreComponents.java | 9 ++- .../io/avaje/config/CoreConfiguration.java | 2 +- .../config/CoreConfigurationBuilder.java | 2 +- .../main/java/io/avaje/config/FileWatch.java | 4 +- .../java/io/avaje/config/InitialLoader.java | 6 +- .../java/io/avaje/config/URIConfigLoader.java | 16 ++-- 8 files changed, 59 insertions(+), 113 deletions(-) delete mode 100644 avaje-config/src/main/java/io/avaje/config/ConfigParsers.java diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java deleted file mode 100644 index 06ef562..0000000 --- a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.avaje.config; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public interface ConfigParsers { - - /** Return the ConfigParser for the given extension. */ - ConfigParser get(String extension); - - /** Return true if the extension has a matching parser. */ - boolean supportsExtension(String extension); - - /** Return the set of supported extensions. */ - Set supportedExtensions(); - - /** Return the extension ConfigParser pairs. */ - Set> entrySet(); -} - -/** Holds the ConfigParsers for various extension types. */ -final class Parsers implements ConfigParsers { - - private final Map parserMap = new HashMap<>(); - - Parsers(List otherParsers) { - parserMap.put("properties", new PropertiesParser()); - if (!"true".equals(System.getProperty("skipYaml"))) { - initYamlParser(); - } - if (!"true".equals(System.getProperty("skipCustomParsing"))) { - initParsers(otherParsers); - } - } - - private void initYamlParser() { - YamlLoader yamlLoader; - try { - Class.forName("org.yaml.snakeyaml.Yaml"); - yamlLoader = new YamlLoaderSnake(); - } catch (ClassNotFoundException e) { - yamlLoader = new YamlLoaderSimple(); - } - parserMap.put("yml", yamlLoader); - parserMap.put("yaml", yamlLoader); - } - - private void initParsers(List otherParsers) { - for (ConfigParser parser : otherParsers) { - for (var ext : parser.supportedExtensions()) { - parserMap.put(ext, parser); - } - } - } - - @Override - public Set> entrySet() { - return parserMap.entrySet(); - } - - @Override - public ConfigParser get(String extension) { - return parserMap.get(extension.toLowerCase()); - } - - @Override - public boolean supportsExtension(String extension) { - return parserMap.containsKey(extension.toLowerCase()); - } - - @Override - public Set supportedExtensions() { - return parserMap.keySet(); - } -} diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index b58f602..4190334 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -1,7 +1,10 @@ package io.avaje.config; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.ServiceLoader; /** @@ -22,12 +25,12 @@ static ConfigServiceLoader get() { private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); private final URILoaders uriLoaders; - private final ConfigParsers parsers; + Map parsers; ConfigServiceLoader() { - ModificationEventRunner _eventRunner = null; - ConfigurationLog _log = null; - ResourceLoader _resourceLoader = null; + ModificationEventRunner spiEventRunner = null; + ConfigurationLog spiLog = null; + ResourceLoader spiResourceLoader = null; List otherParsers = new ArrayList<>(); List loaders = new ArrayList<>(); @@ -36,28 +39,54 @@ static ConfigServiceLoader get() { sources.add((ConfigurationSource) spi); } else if (spi instanceof ConfigurationPlugin) { plugins.add((ConfigurationPlugin) spi); - } else if (spi instanceof ConfigParser) { + } else if (spi instanceof ConfigParser + && !"true".equals(System.getProperty("skipCustomParsing"))) { otherParsers.add((ConfigParser) spi); } else if (spi instanceof URIConfigLoader) { loaders.add((URIConfigLoader) spi); } else if (spi instanceof ConfigurationLog) { - _log = (ConfigurationLog) spi; + spiLog = (ConfigurationLog) spi; } else if (spi instanceof ResourceLoader) { - _resourceLoader = (ResourceLoader) spi; + spiResourceLoader = (ResourceLoader) spi; } else if (spi instanceof ModificationEventRunner) { - _eventRunner = (ModificationEventRunner) spi; + spiEventRunner = (ModificationEventRunner) spi; } } - this.log = _log == null ? new DefaultConfigurationLog() : _log; - this.resourceLoader = _resourceLoader == null ? new DefaultResourceLoader() : _resourceLoader; + this.log = spiLog == null ? new DefaultConfigurationLog() : spiLog; + this.resourceLoader = spiResourceLoader == null ? new DefaultResourceLoader() : spiResourceLoader; this.eventRunner = - _eventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : _eventRunner; - this.parsers = new Parsers(otherParsers); + spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; this.uriLoaders = new URILoaders(loaders); + this.parsers = initParsers(otherParsers); } - ConfigParsers parsers() { + Map initParsers(List parsers) { + + var parserMap = new HashMap(); + parserMap.put("properties", new PropertiesParser()); + if (!"true".equals(System.getProperty("skipYaml"))) { + + YamlLoader yamlLoader; + try { + Class.forName("org.yaml.snakeyaml.Yaml"); + yamlLoader = new YamlLoaderSnake(); + } catch (ClassNotFoundException e) { + yamlLoader = new YamlLoaderSimple(); + } + parserMap.put("yml", yamlLoader); + parserMap.put("yaml", yamlLoader); + } + + for (ConfigParser parser : parsers) { + for (var ext : parser.supportedExtensions()) { + parserMap.put(ext, parser); + } + } + return Collections.unmodifiableMap(parserMap); + } + + Map parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 2202d0a..50c493e 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -1,12 +1,13 @@ package io.avaje.config; import java.util.List; +import java.util.Map; final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; - private final ConfigParsers parsers; + private final Map parsers; private final URILoaders uriLoaders; private final List sources; private final List plugins; @@ -14,7 +15,7 @@ final class CoreComponents { CoreComponents( ModificationEventRunner runner, ConfigurationLog log, - ConfigParsers parsers, + Map parsers, URILoaders uriLoaders, List sources, List plugins) { @@ -30,13 +31,13 @@ final class CoreComponents { CoreComponents() { this.runner = new CoreConfiguration.ForegroundEventRunner(); this.log = new DefaultConfigurationLog(); - this.parsers = new Parsers(List.of()); + this.parsers = Map.of(); this.uriLoaders = new URILoaders(List.of()); this.sources = List.of(); this.plugins = List.of(); } - ConfigParsers parsers() { + Map parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java index e8fc571..c062839 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java @@ -27,7 +27,7 @@ @NullMarked final class CoreConfiguration implements Configuration { - private final ConfigParsers parsers; + private final Map parsers; private final ConfigurationLog log; private final ModifyAwareProperties properties; private final ReentrantLock lock = new ReentrantLock(); diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 36fdd3c..597f4c8 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -18,7 +18,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); - private final ConfigParsers parsers = serviceLoader.parsers(); + private final Map parsers = serviceLoader.parsers(); private final URILoaders uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); diff --git a/avaje-config/src/main/java/io/avaje/config/FileWatch.java b/avaje-config/src/main/java/io/avaje/config/FileWatch.java index 9ab7f0e..05c1663 100644 --- a/avaje-config/src/main/java/io/avaje/config/FileWatch.java +++ b/avaje-config/src/main/java/io/avaje/config/FileWatch.java @@ -11,12 +11,12 @@ final class FileWatch { private final ConfigurationLog log; private final Configuration configuration; - private final ConfigParsers parsers; + private final Map parsers; private final List files; private final long delay; private final long period; - FileWatch(CoreConfiguration configuration, List loadedFiles, ConfigParsers parsers) { + FileWatch(CoreConfiguration configuration, List loadedFiles, Map parsers) { this.log = configuration.log(); this.configuration = configuration; this.delay = configuration.getLong("config.watch.delay", 60); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index e0cf465..8a7055e 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -43,7 +43,7 @@ enum Source { private final ConfigurationLog log; private final InitialLoadContext loadContext; private final Set profileResourceLoaded = new HashSet<>(); - private final ConfigParsers parsers; + private final Map parsers; private final URILoaders uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { @@ -156,7 +156,7 @@ private void loadCommandLineArg(String arg) { private boolean isValidExtension(String arg) { var extension = arg.substring(arg.lastIndexOf(".") + 1); - return "properties".equals(extension) || parsers.supportsExtension(extension); + return "properties".equals(extension) || parsers.containsKey(extension); } /** @@ -273,7 +273,7 @@ boolean loadWithExtensionCheck(String fileName) { if (parser == null) { throw new IllegalArgumentException( "Expecting only properties or " - + parsers.supportedExtensions() + + parsers.keySet() + " file extensions but got [" + fileName + "]"); diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index 3488961..cf644ab 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -3,22 +3,16 @@ import java.net.URI; import java.util.Map; -/** Additional source to load and update configuration. */ +/** URI based source to load and update configuration based on the provided URI scheme. */ public interface URIConfigLoader extends ConfigExtension { /** URI Scheme Supported by this loader */ String supportedScheme(); /** - * Load additional configuration. - * - *

The {@link Configuration#setProperty(String, String)} method is used when loading the - * additional properties from the source. - * - *

Also note that the source can additionally use {@link Configuration#schedule(long, long, - * Runnable)} to schedule a period task to for example refresh data etc. - * - * @param configuration The configuration with initially properties. + * @param uri uri from which to load data + * @param parsers config parses available to assist in parsing data + * @return key/value map of loaded properties */ - Map load(URI uri, ConfigParsers parsers); + Map load(URI uri, Map parsers); } From e8ab6cbff83dad08b8ca1435e9e1eb834b0756ab Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:13:58 -0400 Subject: [PATCH 09/28] fix tests --- .../src/main/java/io/avaje/config/ConfigServiceLoader.java | 2 +- .../src/main/java/io/avaje/config/CoreComponents.java | 4 ++-- .../src/main/java/io/avaje/config/URIConfigLoader.java | 5 +++-- .../src/test/java/io/avaje/config/FileWatchTest.java | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 4190334..aff3ceb 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -25,7 +25,7 @@ static ConfigServiceLoader get() { private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); private final URILoaders uriLoaders; - Map parsers; + private final Map parsers; ConfigServiceLoader() { ModificationEventRunner spiEventRunner = null; diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 50c493e..b643a36 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -31,8 +31,8 @@ final class CoreComponents { CoreComponents() { this.runner = new CoreConfiguration.ForegroundEventRunner(); this.log = new DefaultConfigurationLog(); - this.parsers = Map.of(); - this.uriLoaders = new URILoaders(List.of()); + this.parsers = ConfigServiceLoader.get().parsers(); + this.uriLoaders = ConfigServiceLoader.get().uriLoaders(); this.sources = List.of(); this.plugins = List.of(); } diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index cf644ab..035d481 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -3,7 +3,7 @@ import java.net.URI; import java.util.Map; -/** URI based source to load and update configuration based on the provided URI scheme. */ +/** Custom URI configuration loader. Used when a matching uri scheme is found in load.properties */ public interface URIConfigLoader extends ConfigExtension { /** URI Scheme Supported by this loader */ @@ -11,7 +11,8 @@ public interface URIConfigLoader extends ConfigExtension { /** * @param uri uri from which to load data - * @param parsers config parses available to assist in parsing data + * @param parsers map of {@link ConfigParser} available to assist in parsing data, keyed by {@link + * ConfigParser#supportedExtensions()} * @return key/value map of loaded properties */ Map load(URI uri, Map parsers); diff --git a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java index 1eeb5d0..5510045 100644 --- a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java +++ b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Properties; import static org.assertj.core.api.Assertions.assertThat; @@ -137,7 +138,7 @@ void test_check_whenFileWritten() throws Exception { } private static FileWatch fileWatch(CoreConfiguration config, List files) { - return new FileWatch(config, files, new Parsers(Collections.emptyList())); + return new FileWatch(config, files, ConfigServiceLoader.get().parsers()); } private void writeContent(String content) throws IOException { From e9a7162b89cb59a533863f3218b4f0dbca5a1014 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:22:26 -0400 Subject: [PATCH 10/28] replace URILoaders with a map --- .../io/avaje/config/ConfigServiceLoader.java | 18 +++++---- .../java/io/avaje/config/CoreComponents.java | 6 +-- .../config/CoreConfigurationBuilder.java | 2 +- .../java/io/avaje/config/InitialLoader.java | 4 +- .../main/java/io/avaje/config/URILoaders.java | 40 ------------------- 5 files changed, 17 insertions(+), 53 deletions(-) delete mode 100644 avaje-config/src/main/java/io/avaje/config/URILoaders.java diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index aff3ceb..22d707d 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -1,11 +1,14 @@ package io.avaje.config; +import static java.util.stream.Collectors.toMap; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import java.util.function.Function; /** * Load all the avaje-config extensions via ServiceLoader using the single common ConfigExtension @@ -24,7 +27,7 @@ static ConfigServiceLoader get() { private final ModificationEventRunner eventRunner; private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); - private final URILoaders uriLoaders; + private final Map uriLoaders; private final Map parsers; ConfigServiceLoader() { @@ -39,8 +42,7 @@ static ConfigServiceLoader get() { sources.add((ConfigurationSource) spi); } else if (spi instanceof ConfigurationPlugin) { plugins.add((ConfigurationPlugin) spi); - } else if (spi instanceof ConfigParser - && !"true".equals(System.getProperty("skipCustomParsing"))) { + } else if (spi instanceof ConfigParser && !Boolean.getBoolean("skipCustomParsing")) { otherParsers.add((ConfigParser) spi); } else if (spi instanceof URIConfigLoader) { loaders.add((URIConfigLoader) spi); @@ -54,18 +56,20 @@ static ConfigServiceLoader get() { } this.log = spiLog == null ? new DefaultConfigurationLog() : spiLog; - this.resourceLoader = spiResourceLoader == null ? new DefaultResourceLoader() : spiResourceLoader; + this.resourceLoader = + spiResourceLoader == null ? new DefaultResourceLoader() : spiResourceLoader; this.eventRunner = spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; - this.uriLoaders = new URILoaders(loaders); + this.parsers = initParsers(otherParsers); + this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigLoader::supportedScheme, Function.identity())); } Map initParsers(List parsers) { var parserMap = new HashMap(); parserMap.put("properties", new PropertiesParser()); - if (!"true".equals(System.getProperty("skipYaml"))) { + if (!Boolean.getBoolean("skipYaml")) { YamlLoader yamlLoader; try { @@ -90,7 +94,7 @@ Map parsers() { return parsers; } - public URILoaders uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index b643a36..59ba397 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -8,7 +8,7 @@ final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; private final Map parsers; - private final URILoaders uriLoaders; + private final Map uriLoaders; private final List sources; private final List plugins; @@ -16,7 +16,7 @@ final class CoreComponents { ModificationEventRunner runner, ConfigurationLog log, Map parsers, - URILoaders uriLoaders, + Map uriLoaders, List sources, List plugins) { this.runner = runner; @@ -41,7 +41,7 @@ Map parsers() { return parsers; } - public URILoaders uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 597f4c8..7b3f123 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -19,7 +19,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); private final Map parsers = serviceLoader.parsers(); - private final URILoaders uriLoaders = serviceLoader.uriLoaders(); + private final Map uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); private ModificationEventRunner eventRunner = serviceLoader.eventRunner(); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 8a7055e..f7b80c2 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -44,7 +44,7 @@ enum Source { private final InitialLoadContext loadContext; private final Set profileResourceLoaded = new HashSet<>(); private final Map parsers; - private final URILoaders uriLoaders; + private final Map uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { this.parsers = components.parsers(); @@ -295,7 +295,7 @@ private boolean loadURI(String uriPath) { throw new IllegalArgumentException( "Expecting only properties or " - + uriLoaders.supportedSchemes().stream().map(s -> s + ":/").collect(joining(",")) + + uriLoaders.keySet().stream().map(s -> s + ":/").collect(joining(",")) + " uris but got [" + uriPath + "]"); diff --git a/avaje-config/src/main/java/io/avaje/config/URILoaders.java b/avaje-config/src/main/java/io/avaje/config/URILoaders.java deleted file mode 100644 index bceaa93..0000000 --- a/avaje-config/src/main/java/io/avaje/config/URILoaders.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.avaje.config; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** Holds the non-properties ConfigParsers. */ -final class URILoaders { - - private final Map parserMap = new HashMap<>(); - - URILoaders(List loaders) { - for (var parser : loaders) { - - parserMap.put(parser.supportedScheme(), parser); - } - } - - /** Return the extension ConfigParser pairs. */ - public Set> entrySet() { - return parserMap.entrySet(); - } - - /** Return the ConfigParser for the given extension. */ - public URIConfigLoader get(String extension) { - return parserMap.get(extension.toLowerCase()); - } - - /** Return true if the extension has a matching parser. */ - public boolean supportsScheme(String extension) { - return parserMap.containsKey(extension.toLowerCase()); - } - - /** Return the set of supported extensions. */ - public Set supportedSchemes() { - return parserMap.keySet(); - } -} From dc4c6610c5ee40bcf2ca715555ec7dcb0702ccb4 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:28:49 -0400 Subject: [PATCH 11/28] prevent duplicate loading --- .../main/java/io/avaje/config/InitialLoader.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index f7b80c2..745e7f6 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -267,20 +267,20 @@ boolean loadWithExtensionCheck(String fileName) { var extension = fileName.substring(fileName.lastIndexOf(".") + 1); if ("properties".equals(extension)) { - return loadProperties(fileName, RESOURCE) | loadProperties(fileName, FILE); + return loadProperties(fileName, RESOURCE) || loadProperties(fileName, FILE); } else { var parser = parsers.get(extension); if (parser == null) { throw new IllegalArgumentException( - "Expecting only properties or " - + parsers.keySet() - + " file extensions but got [" - + fileName - + "]"); + "Expecting only properties or " + + parsers.keySet() + + " file extensions but got [" + + fileName + + "]"); } return loadCustomExtension(fileName, parser, RESOURCE) - | loadCustomExtension(fileName, parser, FILE); + || loadCustomExtension(fileName, parser, FILE); } } From 00abb12fcd736e3fd30a6179d955b0fa2ab22abc Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:31:36 -0400 Subject: [PATCH 12/28] Revert "prevent duplicate loading" This reverts commit dc4c6610c5ee40bcf2ca715555ec7dcb0702ccb4. --- .../main/java/io/avaje/config/InitialLoader.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 745e7f6..f7b80c2 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -267,20 +267,20 @@ boolean loadWithExtensionCheck(String fileName) { var extension = fileName.substring(fileName.lastIndexOf(".") + 1); if ("properties".equals(extension)) { - return loadProperties(fileName, RESOURCE) || loadProperties(fileName, FILE); + return loadProperties(fileName, RESOURCE) | loadProperties(fileName, FILE); } else { var parser = parsers.get(extension); if (parser == null) { throw new IllegalArgumentException( - "Expecting only properties or " - + parsers.keySet() - + " file extensions but got [" - + fileName - + "]"); + "Expecting only properties or " + + parsers.keySet() + + " file extensions but got [" + + fileName + + "]"); } return loadCustomExtension(fileName, parser, RESOURCE) - || loadCustomExtension(fileName, parser, FILE); + | loadCustomExtension(fileName, parser, FILE); } } From b2a5c261d6502483176120dd26dd76c82dc5fe98 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:59:40 -0400 Subject: [PATCH 13/28] Update InitialLoader.java --- .../java/io/avaje/config/InitialLoader.java | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index f7b80c2..304fe0e 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.io.UncheckedIOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.*; import java.util.regex.Pattern; @@ -257,12 +258,7 @@ private void loadViaSystemProperty() { boolean loadWithExtensionCheck(String fileName) { - // no need to custom URL load regular cp and file schemes - fileName = fileName.replaceFirst("classpath:/", "").replaceFirst("file:/", ""); - if (fileName.contains(":/")) { - - return loadURI(fileName); - } + if (loadURI(fileName)) return true; var extension = fileName.substring(fileName.lastIndexOf(".") + 1); if ("properties".equals(extension)) { @@ -272,33 +268,42 @@ boolean loadWithExtensionCheck(String fileName) { var parser = parsers.get(extension); if (parser == null) { throw new IllegalArgumentException( - "Expecting only properties or " - + parsers.keySet() - + " file extensions but got [" - + fileName - + "]"); + "Expecting only properties or " + + parsers.keySet() + + " file extensions or " + + uriLoaders.keySet().stream().map(s -> s + ":/").collect(joining(",")) + + "uri schemes but got [" + + fileName + + "]"); } return loadCustomExtension(fileName, parser, RESOURCE) - | loadCustomExtension(fileName, parser, FILE); + | loadCustomExtension(fileName, parser, FILE); } } - private boolean loadURI(String uriPath) { - var uri = URI.create(uriPath); - final var scheme = uri.getScheme(); + private boolean loadURI(String fileName) { + URI uri; + try { + uri = new URI(fileName); + } catch (URISyntaxException e) { + return false; + } + + var scheme = uri.getScheme(); + + if (scheme == null || "classpath".equals(scheme) || "file".equals(scheme)) { + + return false; + } + var loader = uriLoaders.get(scheme); + if (loader != null) { loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, "uri scheme " + scheme)); return true; } - - throw new IllegalArgumentException( - "Expecting only properties or " - + uriLoaders.keySet().stream().map(s -> s + ":/").collect(joining(",")) - + " uris but got [" - + uriPath - + "]"); + return false; } /** From f02a32a2bcad5023a65f3bc1b2e8ee40be81a2fd Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 8 Oct 2024 22:57:14 -0400 Subject: [PATCH 14/28] Update InitialLoader.java --- avaje-config/src/main/java/io/avaje/config/InitialLoader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 304fe0e..7da117a 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -111,6 +111,7 @@ void loadEnvironmentVars() { */ void loadLocalFiles() { loadMain(RESOURCE); + loadViaProfiles(RESOURCE); // external file configuration overrides the resources configuration loadMain(FILE); // load additional profile RESOURCE(s) if added via loadMain() From 6aecc8958ecf342a7b5599b135a4968a700a98a7 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sun, 13 Oct 2024 13:59:58 -0400 Subject: [PATCH 15/28] add redact function --- .../src/main/java/io/avaje/config/InitialLoader.java | 2 +- .../src/main/java/io/avaje/config/URIConfigLoader.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 7da117a..fd1082b 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -301,7 +301,7 @@ private boolean loadURI(String fileName) { var loader = uriLoaders.get(scheme); if (loader != null) { - loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, "uri scheme " + scheme)); + loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, loader.redact(uri))); return true; } return false; diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index 035d481..addb801 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -6,6 +6,11 @@ /** Custom URI configuration loader. Used when a matching uri scheme is found in load.properties */ public interface URIConfigLoader extends ConfigExtension { + /** redact any sensitive information in the URI when displayed by logging */ + default String redact(URI uri) { + return uri.toString(); + } + /** URI Scheme Supported by this loader */ String supportedScheme(); From b173f09b64630e32b4685e4b723d859278978ade Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:01:11 -0400 Subject: [PATCH 16/28] Update InitialLoader.java --- avaje-config/src/main/java/io/avaje/config/InitialLoader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index fd1082b..d35eb1d 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -301,7 +301,8 @@ private boolean loadURI(String fileName) { var loader = uriLoaders.get(scheme); if (loader != null) { - loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, loader.redact(uri))); + final var source = loader.redact(uri); + loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, source)); return true; } return false; From 5655302ef81442e86b9a3dbe37800f73b9d29f8d Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:35:02 -0400 Subject: [PATCH 17/28] add uri context --- .../io/avaje/config/InitialLoadContext.java | 7 ++++ .../java/io/avaje/config/InitialLoader.java | 4 ++- .../java/io/avaje/config/URIConfigLoader.java | 3 +- .../java/io/avaje/config/URILoadContext.java | 36 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 avaje-config/src/main/java/io/avaje/config/URILoadContext.java diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java b/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java index cf9d651..b6e0d9c 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java @@ -107,6 +107,13 @@ private InputStream resourceStream(String resourcePath) { return resourceLoader.getResourceAsStream(resourcePath); } + /** Get a property */ + String get(String key) { + + var entry = map.get(key); + return entry == null ? null : entry.value(); + } + /** * Add a property entry. */ diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index d35eb1d..638d64c 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -43,6 +43,7 @@ enum Source { private final ConfigurationLog log; private final InitialLoadContext loadContext; + private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); private final Map parsers; private final Map uriLoaders; @@ -52,6 +53,7 @@ enum Source { this.uriLoaders = components.uriLoaders(); this.log = components.log(); this.loadContext = new InitialLoadContext(log, resourceLoader); + this.uriContext = new DURILoadContext(parsers, loadContext::get); } Set loadedFrom() { @@ -302,7 +304,7 @@ private boolean loadURI(String fileName) { if (loader != null) { final var source = loader.redact(uri); - loader.load(uri, parsers).forEach((k, v) -> loadContext.put(k, v, source)); + loader.load(uri, uriContext).forEach((k, v) -> loadContext.put(k, v, source)); return true; } return false; diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index addb801..3e35667 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -8,6 +8,7 @@ public interface URIConfigLoader extends ConfigExtension { /** redact any sensitive information in the URI when displayed by logging */ default String redact(URI uri) { + return uri.toString(); } @@ -20,5 +21,5 @@ default String redact(URI uri) { * ConfigParser#supportedExtensions()} * @return key/value map of loaded properties */ - Map load(URI uri, Map parsers); + Map load(URI uri, URILoadContext ctx); } diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java new file mode 100644 index 0000000..37a8c8f --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -0,0 +1,36 @@ +package io.avaje.config; + +import java.util.Map; +import java.util.Optional; +import java.util.function.UnaryOperator; + +public interface URILoadContext { + + Optional parser(String extension); + + Optional getProperty(String key); +} + +class DURILoadContext implements URILoadContext { + + Map parsersMap; + + UnaryOperator getProperty; + + DURILoadContext(Map parsersMap, UnaryOperator getPropertyFunction) { + this.parsersMap = parsersMap; + this.getProperty = getPropertyFunction; + } + + @Override + public Optional parser(String extension) { + + return Optional.ofNullable(parsersMap.get(extension)); + } + + @Override + public Optional getProperty(String key) { + + return Optional.ofNullable(getProperty.apply(key)); + } +} From a85dbb93a2d3a5c6bfd030d45a93bfa1a69a8b3b Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sun, 13 Oct 2024 17:15:36 -0400 Subject: [PATCH 18/28] rename to uriParser --- .../java/io/avaje/config/ConfigServiceLoader.java | 12 ++++++------ .../main/java/io/avaje/config/CoreComponents.java | 6 +++--- .../io/avaje/config/CoreConfigurationBuilder.java | 2 +- .../src/main/java/io/avaje/config/InitialLoader.java | 2 +- .../{URIConfigLoader.java => URIConfigParser.java} | 4 ++-- .../main/java/io/avaje/config/URILoadContext.java | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) rename avaje-config/src/main/java/io/avaje/config/{URIConfigLoader.java => URIConfigParser.java} (79%) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 22d707d..d61a682 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -27,7 +27,7 @@ static ConfigServiceLoader get() { private final ModificationEventRunner eventRunner; private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); - private final Map uriLoaders; + private final Map uriLoaders; private final Map parsers; ConfigServiceLoader() { @@ -35,7 +35,7 @@ static ConfigServiceLoader get() { ConfigurationLog spiLog = null; ResourceLoader spiResourceLoader = null; List otherParsers = new ArrayList<>(); - List loaders = new ArrayList<>(); + List loaders = new ArrayList<>(); for (var spi : ServiceLoader.load(ConfigExtension.class)) { if (spi instanceof ConfigurationSource) { @@ -44,8 +44,8 @@ static ConfigServiceLoader get() { plugins.add((ConfigurationPlugin) spi); } else if (spi instanceof ConfigParser && !Boolean.getBoolean("skipCustomParsing")) { otherParsers.add((ConfigParser) spi); - } else if (spi instanceof URIConfigLoader) { - loaders.add((URIConfigLoader) spi); + } else if (spi instanceof URIConfigParser) { + loaders.add((URIConfigParser) spi); } else if (spi instanceof ConfigurationLog) { spiLog = (ConfigurationLog) spi; } else if (spi instanceof ResourceLoader) { @@ -62,7 +62,7 @@ static ConfigServiceLoader get() { spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; this.parsers = initParsers(otherParsers); - this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigLoader::supportedScheme, Function.identity())); + this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigParser::supportedScheme, Function.identity())); } Map initParsers(List parsers) { @@ -94,7 +94,7 @@ Map parsers() { return parsers; } - public Map uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 59ba397..0eeef28 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -8,7 +8,7 @@ final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; private final Map parsers; - private final Map uriLoaders; + private final Map uriLoaders; private final List sources; private final List plugins; @@ -16,7 +16,7 @@ final class CoreComponents { ModificationEventRunner runner, ConfigurationLog log, Map parsers, - Map uriLoaders, + Map uriLoaders, List sources, List plugins) { this.runner = runner; @@ -41,7 +41,7 @@ Map parsers() { return parsers; } - public Map uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 7b3f123..2e7719f 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -19,7 +19,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); private final Map parsers = serviceLoader.parsers(); - private final Map uriLoaders = serviceLoader.uriLoaders(); + private final Map uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); private ModificationEventRunner eventRunner = serviceLoader.eventRunner(); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 638d64c..1f94ca5 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -46,7 +46,7 @@ enum Source { private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); private final Map parsers; - private final Map uriLoaders; + private final Map uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { this.parsers = components.parsers(); diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigParser.java similarity index 79% rename from avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java rename to avaje-config/src/main/java/io/avaje/config/URIConfigParser.java index 3e35667..0b50201 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigParser.java @@ -3,8 +3,8 @@ import java.net.URI; import java.util.Map; -/** Custom URI configuration loader. Used when a matching uri scheme is found in load.properties */ -public interface URIConfigLoader extends ConfigExtension { +/** Custom URI configuration parser for reading load.properties properties that use a URI. */ +public interface URIConfigParser extends ConfigExtension { /** redact any sensitive information in the URI when displayed by logging */ default String redact(URI uri) { diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index 37a8c8f..ceaaaf5 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -6,7 +6,7 @@ public interface URILoadContext { - Optional parser(String extension); + Optional configParser(String extension); Optional getProperty(String key); } @@ -23,7 +23,7 @@ class DURILoadContext implements URILoadContext { } @Override - public Optional parser(String extension) { + public Optional configParser(String extension) { return Optional.ofNullable(parsersMap.get(extension)); } From 905d233834f9085566c3c3bba1371a3910c5b0fc Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Sun, 13 Oct 2024 17:42:08 -0400 Subject: [PATCH 19/28] add utility for query parsing --- .../java/io/avaje/config/URILoadContext.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index ceaaaf5..f13f372 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -1,5 +1,11 @@ package io.avaje.config; +import java.net.URI; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.UnaryOperator; @@ -9,6 +15,23 @@ public interface URILoadContext { Optional configParser(String extension); Optional getProperty(String key); + + default Map> splitQueryParams(URI uri) { + final Map> queryPairs = new LinkedHashMap<>(); + final String[] pairs = uri.getQuery().split("&"); + for (String pair : pairs) { + final int idx = pair.indexOf("="); + final String key = + idx > 0 ? URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8) : pair; + + final String value = + idx > 0 && pair.length() > idx + 1 + ? URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8) + : null; + queryPairs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } + return queryPairs; + } } class DURILoadContext implements URILoadContext { From 6f995a2c2ee8e0eae4ae5bf6b12f52d454a3768e Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:47:06 -0400 Subject: [PATCH 20/28] rename --- .../java/io/avaje/config/ConfigServiceLoader.java | 12 ++++++------ .../main/java/io/avaje/config/CoreComponents.java | 6 +++--- .../io/avaje/config/CoreConfigurationBuilder.java | 2 +- .../src/main/java/io/avaje/config/InitialLoader.java | 2 +- .../{URIConfigParser.java => URIConfigLoader.java} | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) rename avaje-config/src/main/java/io/avaje/config/{URIConfigParser.java => URIConfigLoader.java} (92%) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index d61a682..22d707d 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -27,7 +27,7 @@ static ConfigServiceLoader get() { private final ModificationEventRunner eventRunner; private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); - private final Map uriLoaders; + private final Map uriLoaders; private final Map parsers; ConfigServiceLoader() { @@ -35,7 +35,7 @@ static ConfigServiceLoader get() { ConfigurationLog spiLog = null; ResourceLoader spiResourceLoader = null; List otherParsers = new ArrayList<>(); - List loaders = new ArrayList<>(); + List loaders = new ArrayList<>(); for (var spi : ServiceLoader.load(ConfigExtension.class)) { if (spi instanceof ConfigurationSource) { @@ -44,8 +44,8 @@ static ConfigServiceLoader get() { plugins.add((ConfigurationPlugin) spi); } else if (spi instanceof ConfigParser && !Boolean.getBoolean("skipCustomParsing")) { otherParsers.add((ConfigParser) spi); - } else if (spi instanceof URIConfigParser) { - loaders.add((URIConfigParser) spi); + } else if (spi instanceof URIConfigLoader) { + loaders.add((URIConfigLoader) spi); } else if (spi instanceof ConfigurationLog) { spiLog = (ConfigurationLog) spi; } else if (spi instanceof ResourceLoader) { @@ -62,7 +62,7 @@ static ConfigServiceLoader get() { spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; this.parsers = initParsers(otherParsers); - this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigParser::supportedScheme, Function.identity())); + this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigLoader::supportedScheme, Function.identity())); } Map initParsers(List parsers) { @@ -94,7 +94,7 @@ Map parsers() { return parsers; } - public Map uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 0eeef28..59ba397 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -8,7 +8,7 @@ final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; private final Map parsers; - private final Map uriLoaders; + private final Map uriLoaders; private final List sources; private final List plugins; @@ -16,7 +16,7 @@ final class CoreComponents { ModificationEventRunner runner, ConfigurationLog log, Map parsers, - Map uriLoaders, + Map uriLoaders, List sources, List plugins) { this.runner = runner; @@ -41,7 +41,7 @@ Map parsers() { return parsers; } - public Map uriLoaders() { + public Map uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 2e7719f..7b3f123 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -19,7 +19,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); private final Map parsers = serviceLoader.parsers(); - private final Map uriLoaders = serviceLoader.uriLoaders(); + private final Map uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); private ModificationEventRunner eventRunner = serviceLoader.eventRunner(); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index fed9881..57afad5 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -46,7 +46,7 @@ enum Source { private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); private final Map parsers; - private final Map uriLoaders; + private final Map uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { this.parsers = components.parsers(); diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigParser.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java similarity index 92% rename from avaje-config/src/main/java/io/avaje/config/URIConfigParser.java rename to avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index 0b50201..911ae27 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigParser.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -4,7 +4,7 @@ import java.util.Map; /** Custom URI configuration parser for reading load.properties properties that use a URI. */ -public interface URIConfigParser extends ConfigExtension { +public interface URIConfigLoader extends ConfigExtension { /** redact any sensitive information in the URI when displayed by logging */ default String redact(URI uri) { From a1927cbc24322cdbdac87e2f58133c43cd798072 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:06:55 -0400 Subject: [PATCH 21/28] Update URILoadContext.java --- .../src/main/java/io/avaje/config/URILoadContext.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index f13f372..e635f5a 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -8,7 +8,9 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.UnaryOperator; +import java.util.function.Function; + +import org.jspecify.annotations.Nullable; public interface URILoadContext { @@ -38,9 +40,11 @@ class DURILoadContext implements URILoadContext { Map parsersMap; - UnaryOperator getProperty; + Function getProperty; - DURILoadContext(Map parsersMap, UnaryOperator getPropertyFunction) { + DURILoadContext( + Map parsersMap, + Function getPropertyFunction) { this.parsersMap = parsersMap; this.getProperty = getPropertyFunction; } From c8182965e2ffe8b71c1a1e8ae0f0d35ed2ed08b4 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:52:01 -0400 Subject: [PATCH 22/28] multiple schemas to a loader --- .../io/avaje/config/ConfigServiceLoader.java | 14 +++++++++++++- .../io/avaje/config/InitialLoadContext.java | 7 ++++--- .../java/io/avaje/config/URIConfigLoader.java | 2 +- .../java/io/avaje/config/URILoadContext.java | 17 +++++++++++------ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 22d707d..0420eb5 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -62,9 +62,10 @@ static ConfigServiceLoader get() { spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; this.parsers = initParsers(otherParsers); - this.uriLoaders = loaders.stream().collect(toMap((Function) URIConfigLoader::supportedScheme, Function.identity())); + this.uriLoaders = initloaders(loaders); } + Map initParsers(List parsers) { var parserMap = new HashMap(); @@ -90,6 +91,17 @@ Map initParsers(List parsers) { return Collections.unmodifiableMap(parserMap); } + Map initloaders(List parsers) { + + var parserMap = new HashMap(); + for (var parser : parsers) { + for (var ext : parser.supportedSchemes()) { + parserMap.put(ext, parser); + } + } + return Collections.unmodifiableMap(parserMap); + } + Map parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java b/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java index 548fdc0..7ee4ebc 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoadContext.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; +import java.util.Optional; import java.util.Set; /** @@ -110,10 +111,10 @@ private InputStream resourceStream(String resourcePath) { } /** Get a property */ - String get(String key) { + Optional get(String key) { - var entry = map.get(key); - return entry == null ? null : entry.value(); + return Optional.ofNullable(map.get(key)) + .map(e -> e.needsEvaluation() ? eval(e.value()) : e.value()); } /** diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index 911ae27..50c7adb 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -13,7 +13,7 @@ default String redact(URI uri) { } /** URI Scheme Supported by this loader */ - String supportedScheme(); + String[] supportedSchemes(); /** * @param uri uri from which to load data diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index e635f5a..c3d446a 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -14,7 +14,7 @@ public interface URILoadContext { - Optional configParser(String extension); + ConfigParser configParser(String extension); Optional getProperty(String key); @@ -40,24 +40,29 @@ class DURILoadContext implements URILoadContext { Map parsersMap; - Function getProperty; + Function> getProperty; DURILoadContext( Map parsersMap, - Function getPropertyFunction) { + Function> getPropertyFunction) { this.parsersMap = parsersMap; this.getProperty = getPropertyFunction; } @Override - public Optional configParser(String extension) { + public ConfigParser configParser(String extension) { + var parser = parsersMap.get(extension); + if (parser == null) { - return Optional.ofNullable(parsersMap.get(extension)); + throw new IllegalArgumentException("No ConfigParser found for file extension" + extension); + } + + return parser; } @Override public Optional getProperty(String key) { - return Optional.ofNullable(getProperty.apply(key)); + return getProperty.apply(key); } } From 4d0198f4fd693b7cbd549fcdf15e800917756167 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Wed, 16 Oct 2024 01:34:57 -0400 Subject: [PATCH 23/28] load test properties before load properties --- avaje-config/src/main/java/io/avaje/config/InitialLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 57afad5..692036f 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -120,12 +120,12 @@ void loadLocalFiles() { loadViaProfiles(RESOURCE); loadViaProfiles(FILE); loadViaSystemProperty(); - loadViaIndirection(); // test configuration (if found) overrides main configuration // we should only find these resources when running tests if (!loadTest()) { loadLocalDev(); } + loadViaIndirection(); loadViaCommandLineArgs(); } From aa6d5e2a3f442218538e2e92fc7f21082712c819 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:05:37 -0400 Subject: [PATCH 24/28] add log --- .../src/main/java/io/avaje/config/InitialLoader.java | 2 +- .../main/java/io/avaje/config/URILoadContext.java | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index 692036f..a559a96 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -53,7 +53,7 @@ enum Source { this.uriLoaders = components.uriLoaders(); this.log = components.log(); this.loadContext = new InitialLoadContext(log, resourceLoader); - this.uriContext = new DURILoadContext(parsers, loadContext::get); + this.uriContext = new DURILoadContext(log, parsers, loadContext::get); } Set loadedFrom() { diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index c3d446a..97b0121 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -10,12 +10,12 @@ import java.util.Optional; import java.util.function.Function; -import org.jspecify.annotations.Nullable; - public interface URILoadContext { ConfigParser configParser(String extension); + ConfigurationLog logger(); + Optional getProperty(String key); default Map> splitQueryParams(URI uri) { @@ -37,18 +37,24 @@ default Map> splitQueryParams(URI uri) { } class DURILoadContext implements URILoadContext { - + ConfigurationLog logger; Map parsersMap; Function> getProperty; DURILoadContext( + ConfigurationLog logger, Map parsersMap, Function> getPropertyFunction) { this.parsersMap = parsersMap; this.getProperty = getPropertyFunction; } + @Override + public ConfigurationLog logger() { + return logger; + } + @Override public ConfigParser configParser(String extension) { var parser = parsersMap.get(extension); From 133fe1896b5571dd5c4da4f215168c41dfcc0d80 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:34:43 -0400 Subject: [PATCH 25/28] supports uri --- .../io/avaje/config/ConfigServiceLoader.java | 17 +++------------ .../java/io/avaje/config/CoreComponents.java | 6 +++--- .../config/CoreConfigurationBuilder.java | 3 ++- .../java/io/avaje/config/InitialLoader.java | 21 +++++++++++++++---- .../java/io/avaje/config/URIConfigLoader.java | 4 ++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 0420eb5..a017e8a 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -27,7 +27,7 @@ static ConfigServiceLoader get() { private final ModificationEventRunner eventRunner; private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); - private final Map uriLoaders; + private final List uriLoaders; private final Map parsers; ConfigServiceLoader() { @@ -62,7 +62,7 @@ static ConfigServiceLoader get() { spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; this.parsers = initParsers(otherParsers); - this.uriLoaders = initloaders(loaders); + this.uriLoaders = loaders; } @@ -91,22 +91,11 @@ Map initParsers(List parsers) { return Collections.unmodifiableMap(parserMap); } - Map initloaders(List parsers) { - - var parserMap = new HashMap(); - for (var parser : parsers) { - for (var ext : parser.supportedSchemes()) { - parserMap.put(ext, parser); - } - } - return Collections.unmodifiableMap(parserMap); - } - Map parsers() { return parsers; } - public Map uriLoaders() { + public List uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 59ba397..134d016 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -8,7 +8,7 @@ final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; private final Map parsers; - private final Map uriLoaders; + private final List uriLoaders; private final List sources; private final List plugins; @@ -16,7 +16,7 @@ final class CoreComponents { ModificationEventRunner runner, ConfigurationLog log, Map parsers, - Map uriLoaders, + List uriLoaders, List sources, List plugins) { this.runner = runner; @@ -41,7 +41,7 @@ Map parsers() { return parsers; } - public Map uriLoaders() { + public List uriLoaders() { return uriLoaders; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 7b3f123..5689c4d 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -8,6 +8,7 @@ import java.io.FileReader; import java.io.IOException; import java.io.UncheckedIOException; +import java.util.List; import java.util.Map; import java.util.Properties; @@ -19,7 +20,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); private final Map parsers = serviceLoader.parsers(); - private final Map uriLoaders = serviceLoader.uriLoaders(); + private final List uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); private ModificationEventRunner eventRunner = serviceLoader.eventRunner(); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index a559a96..a37050d 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -46,7 +46,7 @@ enum Source { private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); private final Map parsers; - private final Map uriLoaders; + private final List uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { this.parsers = components.parsers(); @@ -273,8 +273,8 @@ boolean loadWithExtensionCheck(String fileName) { "Expecting only properties or " + parsers.keySet() + " file extensions or " - + uriLoaders.keySet().stream().map(s -> s + ":/").collect(joining(",")) - + "uri schemes but got [" + + uriLoaders.stream().map(s -> s.getClass().getSimpleName()).collect(joining(",")) + + " compatible uri schemes but got [" + fileName + "]"); } @@ -299,7 +299,7 @@ private boolean loadURI(String fileName) { return false; } - var loader = uriLoaders.get(scheme); + var loader = getLoader(uri); if (loader != null) { final var source = loader.redact(uri); @@ -309,6 +309,19 @@ private boolean loadURI(String fileName) { return false; } + @Nullable + private URIConfigLoader getLoader(URI uri) { + + for (var loader : uriLoaders) { + + if (loader.supports(uri)) { + return loader; + } + } + + return null; + } + /** * Evaluate all the configuration entries and return as properties. */ diff --git a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java index 50c7adb..f72f0a1 100644 --- a/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/URIConfigLoader.java @@ -12,8 +12,8 @@ default String redact(URI uri) { return uri.toString(); } - /** URI Scheme Supported by this loader */ - String[] supportedSchemes(); + /** Whether the URI is supported by this loader */ + boolean supports(URI uri); /** * @param uri uri from which to load data From e1987a935320a3c3eb95c29607d84c1895476309 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:30:25 -0400 Subject: [PATCH 26/28] Update module-info.java --- avaje-config-toml/src/main/java/module-info.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/avaje-config-toml/src/main/java/module-info.java b/avaje-config-toml/src/main/java/module-info.java index 357c7c4..f796a14 100644 --- a/avaje-config-toml/src/main/java/module-info.java +++ b/avaje-config-toml/src/main/java/module-info.java @@ -1,13 +1,12 @@ -import io.avaje.config.ConfigExtension; import io.avaje.config.toml.TomlParser; module io.avaje.config.toml { - requires transitive io.avaje.config; + requires io.avaje.config; requires org.tomlj; exports io.avaje.config.toml; - provides ConfigExtension with TomlParser; + provides io.avaje.config.ConfigExtension with TomlParser; } From c2e623e8f69dafef4bbeda1b8ee817ca3e4d93c8 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:08:27 -0400 Subject: [PATCH 27/28] re-add parsers --- .../java/io/avaje/config/ConfigParsers.java | 78 +++++++++++++++++++ .../io/avaje/config/ConfigServiceLoader.java | 44 ++--------- .../java/io/avaje/config/CoreComponents.java | 7 +- .../io/avaje/config/CoreConfiguration.java | 2 +- .../config/CoreConfigurationBuilder.java | 2 +- .../main/java/io/avaje/config/FileWatch.java | 4 +- .../java/io/avaje/config/InitialLoader.java | 6 +- .../java/io/avaje/config/URILoadContext.java | 8 +- 8 files changed, 97 insertions(+), 54 deletions(-) create mode 100644 avaje-config/src/main/java/io/avaje/config/ConfigParsers.java diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java new file mode 100644 index 0000000..06ef562 --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java @@ -0,0 +1,78 @@ +package io.avaje.config; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +public interface ConfigParsers { + + /** Return the ConfigParser for the given extension. */ + ConfigParser get(String extension); + + /** Return true if the extension has a matching parser. */ + boolean supportsExtension(String extension); + + /** Return the set of supported extensions. */ + Set supportedExtensions(); + + /** Return the extension ConfigParser pairs. */ + Set> entrySet(); +} + +/** Holds the ConfigParsers for various extension types. */ +final class Parsers implements ConfigParsers { + + private final Map parserMap = new HashMap<>(); + + Parsers(List otherParsers) { + parserMap.put("properties", new PropertiesParser()); + if (!"true".equals(System.getProperty("skipYaml"))) { + initYamlParser(); + } + if (!"true".equals(System.getProperty("skipCustomParsing"))) { + initParsers(otherParsers); + } + } + + private void initYamlParser() { + YamlLoader yamlLoader; + try { + Class.forName("org.yaml.snakeyaml.Yaml"); + yamlLoader = new YamlLoaderSnake(); + } catch (ClassNotFoundException e) { + yamlLoader = new YamlLoaderSimple(); + } + parserMap.put("yml", yamlLoader); + parserMap.put("yaml", yamlLoader); + } + + private void initParsers(List otherParsers) { + for (ConfigParser parser : otherParsers) { + for (var ext : parser.supportedExtensions()) { + parserMap.put(ext, parser); + } + } + } + + @Override + public Set> entrySet() { + return parserMap.entrySet(); + } + + @Override + public ConfigParser get(String extension) { + return parserMap.get(extension.toLowerCase()); + } + + @Override + public boolean supportsExtension(String extension) { + return parserMap.containsKey(extension.toLowerCase()); + } + + @Override + public Set supportedExtensions() { + return parserMap.keySet(); + } +} diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index a017e8a..253e30f 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -1,14 +1,8 @@ package io.avaje.config; -import static java.util.stream.Collectors.toMap; - import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.ServiceLoader; -import java.util.function.Function; /** * Load all the avaje-config extensions via ServiceLoader using the single common ConfigExtension @@ -28,7 +22,7 @@ static ConfigServiceLoader get() { private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); private final List uriLoaders; - private final Map parsers; + private final ConfigParsers parsers; ConfigServiceLoader() { ModificationEventRunner spiEventRunner = null; @@ -42,7 +36,7 @@ static ConfigServiceLoader get() { sources.add((ConfigurationSource) spi); } else if (spi instanceof ConfigurationPlugin) { plugins.add((ConfigurationPlugin) spi); - } else if (spi instanceof ConfigParser && !Boolean.getBoolean("skipCustomParsing")) { + } else if (spi instanceof ConfigParser) { otherParsers.add((ConfigParser) spi); } else if (spi instanceof URIConfigLoader) { loaders.add((URIConfigLoader) spi); @@ -56,42 +50,14 @@ static ConfigServiceLoader get() { } this.log = spiLog == null ? new DefaultConfigurationLog() : spiLog; - this.resourceLoader = - spiResourceLoader == null ? new DefaultResourceLoader() : spiResourceLoader; + this.resourceLoader = spiResourceLoader == null ? new DefaultResourceLoader() : spiResourceLoader; this.eventRunner = spiEventRunner == null ? new CoreConfiguration.ForegroundEventRunner() : spiEventRunner; - - this.parsers = initParsers(otherParsers); + this.parsers = new Parsers(otherParsers); this.uriLoaders = loaders; } - - Map initParsers(List parsers) { - - var parserMap = new HashMap(); - parserMap.put("properties", new PropertiesParser()); - if (!Boolean.getBoolean("skipYaml")) { - - YamlLoader yamlLoader; - try { - Class.forName("org.yaml.snakeyaml.Yaml"); - yamlLoader = new YamlLoaderSnake(); - } catch (ClassNotFoundException e) { - yamlLoader = new YamlLoaderSimple(); - } - parserMap.put("yml", yamlLoader); - parserMap.put("yaml", yamlLoader); - } - - for (ConfigParser parser : parsers) { - for (var ext : parser.supportedExtensions()) { - parserMap.put(ext, parser); - } - } - return Collections.unmodifiableMap(parserMap); - } - - Map parsers() { + ConfigParsers parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index 134d016..a486ddf 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -1,13 +1,12 @@ package io.avaje.config; import java.util.List; -import java.util.Map; final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; - private final Map parsers; + private final ConfigParsers parsers; private final List uriLoaders; private final List sources; private final List plugins; @@ -15,7 +14,7 @@ final class CoreComponents { CoreComponents( ModificationEventRunner runner, ConfigurationLog log, - Map parsers, + ConfigParsers parsers, List uriLoaders, List sources, List plugins) { @@ -37,7 +36,7 @@ final class CoreComponents { this.plugins = List.of(); } - Map parsers() { + ConfigParsers parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java index c062839..e8fc571 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java @@ -27,7 +27,7 @@ @NullMarked final class CoreConfiguration implements Configuration { - private final Map parsers; + private final ConfigParsers parsers; private final ConfigurationLog log; private final ModifyAwareProperties properties; private final ReentrantLock lock = new ReentrantLock(); diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index 5689c4d..eaf8589 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -19,7 +19,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); - private final Map parsers = serviceLoader.parsers(); + private final ConfigParsers parsers = serviceLoader.parsers(); private final List uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); diff --git a/avaje-config/src/main/java/io/avaje/config/FileWatch.java b/avaje-config/src/main/java/io/avaje/config/FileWatch.java index 05c1663..9ab7f0e 100644 --- a/avaje-config/src/main/java/io/avaje/config/FileWatch.java +++ b/avaje-config/src/main/java/io/avaje/config/FileWatch.java @@ -11,12 +11,12 @@ final class FileWatch { private final ConfigurationLog log; private final Configuration configuration; - private final Map parsers; + private final ConfigParsers parsers; private final List files; private final long delay; private final long period; - FileWatch(CoreConfiguration configuration, List loadedFiles, Map parsers) { + FileWatch(CoreConfiguration configuration, List loadedFiles, ConfigParsers parsers) { this.log = configuration.log(); this.configuration = configuration; this.delay = configuration.getLong("config.watch.delay", 60); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index a37050d..c22622a 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -45,7 +45,7 @@ enum Source { private final InitialLoadContext loadContext; private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); - private final Map parsers; + private final ConfigParsers parsers; private final List uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { @@ -160,7 +160,7 @@ private void loadCommandLineArg(String arg) { private boolean isValidExtension(String arg) { var extension = arg.substring(arg.lastIndexOf(".") + 1); - return "properties".equals(extension) || parsers.containsKey(extension); + return "properties".equals(extension) || parsers.supportsExtension(extension); } /** @@ -271,7 +271,7 @@ boolean loadWithExtensionCheck(String fileName) { if (parser == null) { throw new IllegalArgumentException( "Expecting only properties or " - + parsers.keySet() + + parsers.supportedExtensions() + " file extensions or " + uriLoaders.stream().map(s -> s.getClass().getSimpleName()).collect(joining(",")) + " compatible uri schemes but got [" diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index 97b0121..2df6af9 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -38,15 +38,15 @@ default Map> splitQueryParams(URI uri) { class DURILoadContext implements URILoadContext { ConfigurationLog logger; - Map parsersMap; + ConfigParsers parsers; Function> getProperty; DURILoadContext( ConfigurationLog logger, - Map parsersMap, + ConfigParsers parsers, Function> getPropertyFunction) { - this.parsersMap = parsersMap; + this.parsers = parsers; this.getProperty = getPropertyFunction; } @@ -57,7 +57,7 @@ public ConfigurationLog logger() { @Override public ConfigParser configParser(String extension) { - var parser = parsersMap.get(extension); + var parser = parsers.get(extension); if (parser == null) { throw new IllegalArgumentException("No ConfigParser found for file extension" + extension); From e18267a09a91c617711ab07ce61d8632871ec7a0 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:03:18 -0400 Subject: [PATCH 28/28] only parsers --- .../io/avaje/config/ConfigServiceLoader.java | 4 ++-- .../java/io/avaje/config/CoreComponents.java | 6 ++--- .../io/avaje/config/CoreConfiguration.java | 2 +- .../config/CoreConfigurationBuilder.java | 2 +- .../main/java/io/avaje/config/FileWatch.java | 4 ++-- .../java/io/avaje/config/InitialLoader.java | 2 +- .../{ConfigParsers.java => Parsers.java} | 23 +------------------ .../java/io/avaje/config/URILoadContext.java | 4 ++-- 8 files changed, 13 insertions(+), 34 deletions(-) rename avaje-config/src/main/java/io/avaje/config/{ConfigParsers.java => Parsers.java} (70%) diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java index 253e30f..0bc2caa 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/ConfigServiceLoader.java @@ -22,7 +22,7 @@ static ConfigServiceLoader get() { private final List sources = new ArrayList<>(); private final List plugins = new ArrayList<>(); private final List uriLoaders; - private final ConfigParsers parsers; + private final Parsers parsers; ConfigServiceLoader() { ModificationEventRunner spiEventRunner = null; @@ -57,7 +57,7 @@ static ConfigServiceLoader get() { this.uriLoaders = loaders; } - ConfigParsers parsers() { + Parsers parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java index a486ddf..8e9532e 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreComponents.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreComponents.java @@ -6,7 +6,7 @@ final class CoreComponents { private final ModificationEventRunner runner; private final ConfigurationLog log; - private final ConfigParsers parsers; + private final Parsers parsers; private final List uriLoaders; private final List sources; private final List plugins; @@ -14,7 +14,7 @@ final class CoreComponents { CoreComponents( ModificationEventRunner runner, ConfigurationLog log, - ConfigParsers parsers, + Parsers parsers, List uriLoaders, List sources, List plugins) { @@ -36,7 +36,7 @@ final class CoreComponents { this.plugins = List.of(); } - ConfigParsers parsers() { + Parsers parsers() { return parsers; } diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java index e8fc571..f5abaf2 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfiguration.java @@ -27,7 +27,7 @@ @NullMarked final class CoreConfiguration implements Configuration { - private final ConfigParsers parsers; + private final Parsers parsers; private final ConfigurationLog log; private final ModifyAwareProperties properties; private final ReentrantLock lock = new ReentrantLock(); diff --git a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java index eaf8589..b0840d6 100644 --- a/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java +++ b/avaje-config/src/main/java/io/avaje/config/CoreConfigurationBuilder.java @@ -19,7 +19,7 @@ final class CoreConfigurationBuilder implements Configuration.Builder { private final CoreEntry.CoreMap sourceMap = CoreEntry.newMap(); private final ConfigServiceLoader serviceLoader = ConfigServiceLoader.get(); - private final ConfigParsers parsers = serviceLoader.parsers(); + private final Parsers parsers = serviceLoader.parsers(); private final List uriLoaders = serviceLoader.uriLoaders(); private ConfigurationLog log = serviceLoader.log(); private ResourceLoader resourceLoader = serviceLoader.resourceLoader(); diff --git a/avaje-config/src/main/java/io/avaje/config/FileWatch.java b/avaje-config/src/main/java/io/avaje/config/FileWatch.java index 9ab7f0e..39a58af 100644 --- a/avaje-config/src/main/java/io/avaje/config/FileWatch.java +++ b/avaje-config/src/main/java/io/avaje/config/FileWatch.java @@ -11,12 +11,12 @@ final class FileWatch { private final ConfigurationLog log; private final Configuration configuration; - private final ConfigParsers parsers; + private final Parsers parsers; private final List files; private final long delay; private final long period; - FileWatch(CoreConfiguration configuration, List loadedFiles, ConfigParsers parsers) { + FileWatch(CoreConfiguration configuration, List loadedFiles, Parsers parsers) { this.log = configuration.log(); this.configuration = configuration; this.delay = configuration.getLong("config.watch.delay", 60); diff --git a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java index c22622a..c5dab27 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -45,7 +45,7 @@ enum Source { private final InitialLoadContext loadContext; private final DURILoadContext uriContext; private final Set profileResourceLoaded = new HashSet<>(); - private final ConfigParsers parsers; + private final Parsers parsers; private final List uriLoaders; InitialLoader(CoreComponents components, ResourceLoader resourceLoader) { diff --git a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java b/avaje-config/src/main/java/io/avaje/config/Parsers.java similarity index 70% rename from avaje-config/src/main/java/io/avaje/config/ConfigParsers.java rename to avaje-config/src/main/java/io/avaje/config/Parsers.java index 06ef562..0b2b50e 100644 --- a/avaje-config/src/main/java/io/avaje/config/ConfigParsers.java +++ b/avaje-config/src/main/java/io/avaje/config/Parsers.java @@ -3,26 +3,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; -public interface ConfigParsers { - - /** Return the ConfigParser for the given extension. */ - ConfigParser get(String extension); - - /** Return true if the extension has a matching parser. */ - boolean supportsExtension(String extension); - - /** Return the set of supported extensions. */ - Set supportedExtensions(); - - /** Return the extension ConfigParser pairs. */ - Set> entrySet(); -} - -/** Holds the ConfigParsers for various extension types. */ -final class Parsers implements ConfigParsers { +final class Parsers { private final Map parserMap = new HashMap<>(); @@ -56,22 +39,18 @@ private void initParsers(List otherParsers) { } } - @Override public Set> entrySet() { return parserMap.entrySet(); } - @Override public ConfigParser get(String extension) { return parserMap.get(extension.toLowerCase()); } - @Override public boolean supportsExtension(String extension) { return parserMap.containsKey(extension.toLowerCase()); } - @Override public Set supportedExtensions() { return parserMap.keySet(); } diff --git a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java index 2df6af9..1af974b 100644 --- a/avaje-config/src/main/java/io/avaje/config/URILoadContext.java +++ b/avaje-config/src/main/java/io/avaje/config/URILoadContext.java @@ -38,13 +38,13 @@ default Map> splitQueryParams(URI uri) { class DURILoadContext implements URILoadContext { ConfigurationLog logger; - ConfigParsers parsers; + Parsers parsers; Function> getProperty; DURILoadContext( ConfigurationLog logger, - ConfigParsers parsers, + Parsers parsers, Function> getPropertyFunction) { this.parsers = parsers; this.getProperty = getPropertyFunction;