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 7b2e5c5..314d8fe 100644 --- a/avaje-config/src/main/java/io/avaje/config/FileWatch.java +++ b/avaje-config/src/main/java/io/avaje/config/FileWatch.java @@ -11,17 +11,17 @@ final class FileWatch { private final ConfigurationLog log; private final Configuration configuration; - private final Map parserMap; + private final Parsers parsers; private final List files; private final long delay; private final long period; - FileWatch(CoreConfiguration configuration, List loadedFiles, Map parserMap) { + FileWatch(CoreConfiguration configuration, List loadedFiles, Parsers parsers) { this.log = configuration.log(); this.configuration = configuration; this.delay = configuration.getLong("config.watch.delay", 60); this.period = configuration.getInt("config.watch.period", 10); - this.parserMap = parserMap; + this.parsers = parsers; this.files = initFiles(loadedFiles); if (files.isEmpty()) { log.log(Level.ERROR, "No files to watch?"); @@ -84,7 +84,7 @@ private void reloadProps(Entry file, Map keyValues) { } private void reloadYaml(Entry file, Map keyValues) { - var parser = parserMap.get(file.extension); + var parser = parsers.get(file.extension); if (parser == null) { log.log(Level.ERROR, "Unexpected - no parser to reload config file " + file); } else { 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 7d21e36..ab36e35 100644 --- a/avaje-config/src/main/java/io/avaje/config/InitialLoader.java +++ b/avaje-config/src/main/java/io/avaje/config/InitialLoader.java @@ -39,13 +39,12 @@ enum Source { private final ConfigurationLog log; private final InitialLoadContext loadContext; private final Set profileResourceLoaded = new HashSet<>(); - private final Map parserMap = new HashMap<>(); + private final Parsers parsers; InitialLoader(ConfigurationLog log, ResourceLoader resourceLoader) { this.log = log; this.loadContext = new InitialLoadContext(log, resourceLoader); - - initCustomLoaders(); + this.parsers = new Parsers(); } Set loadedFrom() { @@ -92,29 +91,7 @@ CoreMap load() { void initWatcher(CoreConfiguration configuration) { if (configuration.getBool("config.watch.enabled", false)) { - configuration.setWatcher(new FileWatch(configuration, loadContext.loadedFiles(), parserMap)); - } - } - - private void initCustomLoaders() { - 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); - } - - if (!"true".equals(System.getProperty("skipCustomParsing"))) { - ServiceLoader.load(ConfigParser.class).forEach(p -> { - for (var ext : p.supportedExtensions()) { - parserMap.put(ext, p); - } - }); + configuration.setWatcher(new FileWatch(configuration, loadContext.loadedFiles(), parsers)); } } @@ -174,7 +151,7 @@ private void loadCommandLineArg(String arg) { private boolean isValidExtension(String arg) { var extension = arg.substring(arg.lastIndexOf(".") + 1); - return "properties".equals(extension) || parserMap.containsKey(extension); + return "properties".equals(extension) || parsers.supportsExtension(extension); } /** @@ -278,11 +255,11 @@ boolean loadWithExtensionCheck(String fileName) { if ("properties".equals(extension)) { return loadProperties(fileName, RESOURCE) | loadProperties(fileName, FILE); } else { - var parser = parserMap.get(extension); + var parser = parsers.get(extension); if (parser == null) { throw new IllegalArgumentException( "Expecting only properties or " - + parserMap.keySet() + + parsers.supportedExtensions() + " file extensions but got [" + fileName + "]"); @@ -308,7 +285,7 @@ boolean load(String resourcePath, Source source) { } private boolean loadCustom(String resourcePath, Source source) { - for (var entry : parserMap.entrySet()) { + for (var entry : parsers.entrySet()) { var extension = entry.getKey(); if (loadCustomExtension(resourcePath + "." + extension, entry.getValue(), source)) { return true; diff --git a/avaje-config/src/main/java/io/avaje/config/Parsers.java b/avaje-config/src/main/java/io/avaje/config/Parsers.java new file mode 100644 index 0000000..4eb0037 --- /dev/null +++ b/avaje-config/src/main/java/io/avaje/config/Parsers.java @@ -0,0 +1,71 @@ +package io.avaje.config; + +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.Set; + +/** + * Holds the non-properties ConfigParsers. + */ +final class Parsers { + + private final Map parserMap = new HashMap<>(); + + Parsers() { + if (!"true".equals(System.getProperty("skipYaml"))) { + initYamlParser(); + } + if (!"true".equals(System.getProperty("skipCustomParsing"))) { + initParsers(); + } + } + + 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() { + ServiceLoader.load(ConfigParser.class).forEach(p -> { + for (var ext : p.supportedExtensions()) { + parserMap.put(ext, p); + } + }); + } + + /** + * Return the extension ConfigParser pairs. + */ + Set> entrySet() { + return parserMap.entrySet(); + } + + /** + * Return the ConfigParser for the given extension. + */ + ConfigParser get(String extension) { + return parserMap.get(extension); + } + + /** + * Return true if the extension has a matching parser. + */ + boolean supportsExtension(String extension) { + return parserMap.containsKey(extension); + } + + /** + * Return the set of supported extensions. + */ + Set supportedExtensions() { + 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 ede568c..81dab68 100644 --- a/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java +++ b/avaje-config/src/test/java/io/avaje/config/FileWatchTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Properties; import static org.assertj.core.api.Assertions.assertThat; @@ -25,8 +24,7 @@ void test_when_notChanged() { CoreConfiguration config = newConfig(); List files = files(); - YamlLoader yamlLoader = new YamlLoaderSnake(); - final FileWatch watch = new FileWatch(config, files, Map.of("yml", yamlLoader, "yaml", yamlLoader)); + final FileWatch watch = new FileWatch(config, files, new Parsers()); assertThat(config.size()).isEqualTo(2); // not touched @@ -40,8 +38,7 @@ void test_check_whenTouched_expect_loaded() { CoreConfiguration config = newConfig(); List files = files(); - YamlLoader yamlLoader = new YamlLoaderSnake(); - final FileWatch watch = new FileWatch(config, files, Map.of("yml", yamlLoader, "yaml", yamlLoader)); + final FileWatch watch = new FileWatch(config, files, new Parsers()); assertThat(config.size()).isEqualTo(2); assertThat(config.getOptional("one")).isEmpty(); @@ -69,8 +66,7 @@ void test_check_whenTouchedScheduled_expect_loaded() { fail("File " + file.getAbsolutePath() + " does not exist?"); } } - YamlLoader yamlLoader = new YamlLoaderSnake(); - final FileWatch watch = new FileWatch(config, files, Map.of("yml", yamlLoader, "yaml", yamlLoader)); + final FileWatch watch = new FileWatch(config, files, new Parsers()); System.out.println(watch); // assert not loaded @@ -97,8 +93,7 @@ void test_check_whenFileWritten() throws Exception { CoreConfiguration config = newConfig(); List files = files(); - YamlLoader yamlLoader = new YamlLoaderSnake(); - final FileWatch watch = new FileWatch(config, files, Map.of("yml", yamlLoader, "yaml", yamlLoader)); + final FileWatch watch = new FileWatch(config, files, new Parsers()); if (isGithubActions()) { File aFile = files.get(0);