fix unspecified string settings load

This commit is contained in:
Jörg Prante 2022-01-06 14:12:24 +01:00
parent 7b220eac39
commit 54b000429d
16 changed files with 65 additions and 107 deletions

View file

@ -13,8 +13,8 @@ public interface Settings extends AutoCloseable {
private static SettingsBuilder createBuilder() { private static SettingsBuilder createBuilder() {
ServiceLoader<SettingsBuilder> serviceLoader = ServiceLoader.load(SettingsBuilder.class); ServiceLoader<SettingsBuilder> serviceLoader = ServiceLoader.load(SettingsBuilder.class);
Optional<SettingsBuilder> optionalConfigLogger = serviceLoader.findFirst(); Optional<SettingsBuilder> optionalSettingsBuilder = serviceLoader.findFirst();
return optionalConfigLogger.orElse(null); return optionalSettingsBuilder.orElse(null);
} }
private static final Settings emptySettings = createBuilder().build(); private static final Settings emptySettings = createBuilder().build();

View file

@ -1,5 +1,6 @@
package org.xbib.settings; package org.xbib.settings;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.sql.Connection; import java.sql.Connection;
@ -36,9 +37,9 @@ public interface SettingsBuilder {
SettingsBuilder put(Map<String, String> settings); SettingsBuilder put(Map<String, String> settings);
SettingsBuilder loadFromString(String source); SettingsBuilder loadFromString(String resourceName, String content);
SettingsBuilder loadFromResource(String resourceName, InputStream inputStream) throws SettingsException; SettingsBuilder loadFromResource(String resourceName, InputStream inputStream);
default SettingsBuilder fromJdbc(Connection connection, String statement, String[] params) throws SQLException { default SettingsBuilder fromJdbc(Connection connection, String statement, String[] params) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(statement, params); try (PreparedStatement preparedStatement = connection.prepareStatement(statement, params);

View file

@ -20,11 +20,14 @@ public interface SettingsLoader {
* Loads the settings from a source string. * Loads the settings from a source string.
* @param source the source * @param source the source
* @return a Map * @return a Map
* @throws IOException if load fails
*/ */
Map<String, String> load(String source) throws IOException; Map<String, String> load(String source) throws IOException;
/**
* Loads the settings from a map.
* @param source the map with the source
* @return a Map
*/
Map<String, String> load(Map<String, Object> source) throws IOException; Map<String, String> load(Map<String, Object> source) throws IOException;
boolean canLoad(String source);
} }

View file

@ -44,20 +44,6 @@ public final class SettingsLoaderService {
throw new IllegalArgumentException("no settings loader for " + resourceName + " in " + settingsLoaderMap.keySet()); throw new IllegalArgumentException("no settings loader for " + resourceName + " in " + settingsLoaderMap.keySet());
} }
/**
* Returns a {@link SettingsLoader} based on the actual source.
* @param source the source
* @return the settings loader
*/
public SettingsLoader loaderFromString(String source) {
for (SettingsLoader loader : settingsLoaderMap.values()) {
if (loader.canLoad(source)) {
return loader;
}
}
throw new IllegalArgumentException("no settings loader");
}
public Set<String> getSuffixes() { public Set<String> getSuffixes() {
Set<String> suffixes = new HashSet<>(); Set<String> suffixes = new HashSet<>();
for (Set<String> set : settingsLoaderMap.keySet()) { for (Set<String> set : settingsLoaderMap.keySet()) {

View file

@ -21,8 +21,4 @@ public class JsonSettingsLoader extends AbstractSettingsLoader {
return Set.of("json"); return Set.of("json");
} }
@Override
public boolean canLoad(String source) {
return source.indexOf('{') != -1 && source.indexOf('}') != -1;
}
} }

View file

@ -47,9 +47,9 @@ public class JsonSettingsTest {
} }
@Test @Test
public void testLoadSettingsFromString() { public void testLoadSettingsFromString() throws IOException {
String json = "{\"Hello\":\"World\"}"; String json = "{\"Hello\":\"World\"}";
Settings settings = Settings.settingsBuilder().loadFromString(json).build(); Settings settings = Settings.settingsBuilder().loadFromString("json", json).build();
assertEquals("{Hello=World}", settings.getAsMap().toString()); assertEquals("{Hello=World}", settings.getAsMap().toString());
} }

View file

@ -30,9 +30,4 @@ public class YamlSettingsLoader extends AbstractSettingsLoader {
// replace tabs with whitespace (yaml does not accept tabs, but many users might use it still...) // replace tabs with whitespace (yaml does not accept tabs, but many users might use it still...)
return super.load(source.replace("\t", " ")); return super.load(source.replace("\t", " "));
} }
@Override
public boolean canLoad(String source) {
return source.indexOf(':') != -1;
}
} }

View file

@ -28,7 +28,7 @@ import java.util.function.Function;
*/ */
public class ContentSettingsBuilder implements SettingsBuilder { public class ContentSettingsBuilder implements SettingsBuilder {
private final SettingsLoaderService settingsLoaderService = SettingsLoaderService.getInstance(); private final SettingsLoaderService settingsLoaderService;
private final Map<String, String> map; private final Map<String, String> map;
@ -41,7 +41,8 @@ public class ContentSettingsBuilder implements SettingsBuilder {
private TimeUnit timeUnit; private TimeUnit timeUnit;
public ContentSettingsBuilder() { public ContentSettingsBuilder() {
map = TinyMap.builder(); this.settingsLoaderService = SettingsLoaderService.getInstance();
this.map = TinyMap.builder();
} }
public String remove(String key) { public String remove(String key) {
@ -227,24 +228,6 @@ public class ContentSettingsBuilder implements SettingsBuilder {
return this; return this;
} }
/**
* Loads settings from the actual string content that represents them using the
* {@link SettingsLoaderService#loaderFromString(String)}.
*
* @param source source
* @return builder
*/
public ContentSettingsBuilder loadFromString(String source) {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromString(source);
try {
Map<String, String> loadedSettings = settingsLoader.load(source);
put(loadedSettings);
} catch (Exception e) {
throw new SettingsException("Failed to load settings from [" + source + "]", e);
}
return this;
}
/** /**
* Loads settings from an URL. * Loads settings from an URL.
* *
@ -267,16 +250,31 @@ public class ContentSettingsBuilder implements SettingsBuilder {
* @return builder * @return builder
*/ */
@Override @Override
public ContentSettingsBuilder loadFromResource(String resourceName, InputStream inputStream) throws SettingsException { public ContentSettingsBuilder loadFromResource(String resourceName, InputStream inputStream) {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
try { try {
Map<String, String> loadedSettings = settingsLoader return loadFromString(resourceName, ContentSettings.copyToString(new InputStreamReader(inputStream, StandardCharsets.UTF_8)));
.load(ContentSettings.copyToString(new InputStreamReader(inputStream, StandardCharsets.UTF_8)));
put(loadedSettings);
} catch (Exception e) { } catch (Exception e) {
throw new SettingsException("Failed to load settings from [" + resourceName + "]", e); throw new SettingsException("failed to load settings from [" + resourceName + "]", e);
}
}
/**
* Loads settings from the actual string content that represents them using the
* {@link SettingsLoaderService#loaderFromResource(String)} (String)}.
*
* @param resourceName the resource name ("json", "yaml")
* @param content the content
* @return builder
*/
@Override
public ContentSettingsBuilder loadFromString(String resourceName, String content) {
try {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
put(settingsLoader.load(content));
return this;
} catch (Exception e) {
throw new SettingsException("failed to load settings from [" + resourceName + "]", e);
} }
return this;
} }
/** /**

View file

@ -41,7 +41,7 @@ public class PropertiesSettingsLoader implements SettingsLoader {
@Override @Override
public Map<String, String> load(Map<String, Object> source) throws IOException { public Map<String, String> load(Map<String, Object> source) {
Properties props = new Properties(); Properties props = new Properties();
props.putAll(source); props.putAll(source);
Map<String, String> result = new HashMap<>(); Map<String, String> result = new HashMap<>();
@ -51,11 +51,6 @@ public class PropertiesSettingsLoader implements SettingsLoader {
return result; return result;
} }
@Override
public boolean canLoad(String source) {
return source != null && source.charAt(0) == '#';
}
public Map<String, String> load(BytesReference ref) throws IOException { public Map<String, String> load(BytesReference ref) throws IOException {
Properties props = new Properties(); Properties props = new Properties();
try (Reader reader = new InputStreamReader(ref.streamInput(), StandardCharsets.UTF_8)) { try (Reader reader = new InputStreamReader(ref.streamInput(), StandardCharsets.UTF_8)) {

View file

@ -153,7 +153,7 @@ public class SettingsTest {
@Test @Test
public void testPropertiesLoaderFromString() { public void testPropertiesLoaderFromString() {
Settings settings = Settings.settingsBuilder() Settings settings = Settings.settingsBuilder()
.loadFromString("#\na.b=c") .loadFromString("properties", "#\na.b=c")
.build(); .build();
assertEquals("{a.b=c}", settings.getAsMap().toString()); assertEquals("{a.b=c}", settings.getAsMap().toString());
} }

View file

@ -16,9 +16,4 @@ public class JsonSettingsLoader extends AbstractSettingsLoader {
public Set<String> suffixes() { public Set<String> suffixes() {
return Set.of("json"); return Set.of("json");
} }
@Override
public boolean canLoad(String source) {
return source.indexOf('{') != -1 && source.indexOf('}') != -1;
}
} }

View file

@ -1,10 +1,6 @@
package org.xbib.settings.datastructures.json.test; package org.xbib.settings.datastructures.json.test;
import java.io.FileOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.datastructures.json.tiny.JsonBuilder;
import org.xbib.settings.Settings; import org.xbib.settings.Settings;
import org.xbib.settings.SettingsLoader; import org.xbib.settings.SettingsLoader;
import org.xbib.settings.datastructures.json.JsonSettingsLoader; import org.xbib.settings.datastructures.json.JsonSettingsLoader;
@ -53,7 +49,7 @@ public class JsonSettingsTest {
@Test @Test
public void testLoadSettingsFromString() { public void testLoadSettingsFromString() {
String json = "{\"Hello\":\"World\"}"; String json = "{\"Hello\":\"World\"}";
Settings settings = Settings.settingsBuilder().loadFromString(json).build(); Settings settings = Settings.settingsBuilder().loadFromString("json", json).build();
assertEquals("{Hello=World}", settings.getAsMap().toString()); assertEquals("{Hello=World}", settings.getAsMap().toString());
} }

View file

@ -20,11 +20,6 @@ public class YamlSettingsLoader extends AbstractSettingsLoader {
return Set.of("yml", "yaml"); return Set.of("yml", "yaml");
} }
@Override
public boolean canLoad(String source) {
return source.indexOf(':') != -1;
}
@Override @Override
public Map<String, String> load(String source) throws IOException { public Map<String, String> load(String source) throws IOException {
// replace tabs with whitespace (yaml does not accept tabs, but many users might use it still...) // replace tabs with whitespace (yaml does not accept tabs, but many users might use it still...)

View file

@ -28,12 +28,13 @@ import java.util.stream.Collectors;
*/ */
public class DatastructureSettingsBuilder implements SettingsBuilder { public class DatastructureSettingsBuilder implements SettingsBuilder {
private final SettingsLoaderService settingsLoaderService = SettingsLoaderService.getInstance(); private final SettingsLoaderService settingsLoaderService;
private final TinyMap.Builder<String, String> map; private final TinyMap.Builder<String, String> map;
public DatastructureSettingsBuilder() { public DatastructureSettingsBuilder() {
map = TinyMap.builder(); this.settingsLoaderService = SettingsLoaderService.getInstance();
this.map = TinyMap.builder();
} }
public String remove(String key) { public String remove(String key) {
@ -218,24 +219,6 @@ public class DatastructureSettingsBuilder implements SettingsBuilder {
return this; return this;
} }
/**
* Loads settings from the actual string content that represents them using the
* {@link SettingsLoaderService#loaderFromString(String)}.
*
* @param source source
* @return builder
*/
@Override
public DatastructureSettingsBuilder loadFromString(String source) {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromString(source);
try {
put(settingsLoader.load(source));
} catch (Exception e) {
throw new SettingsException("failed to load settings from [" + source + "]", e);
}
return this;
}
/** /**
* Loads settings from a resource. * Loads settings from a resource.
* *
@ -244,7 +227,7 @@ public class DatastructureSettingsBuilder implements SettingsBuilder {
* @return builder * @return builder
*/ */
@Override @Override
public DatastructureSettingsBuilder loadFromResource(String resourceName, InputStream inputStream) throws SettingsException { public DatastructureSettingsBuilder loadFromResource(String resourceName, InputStream inputStream) {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName); SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
Map<String, String> loadedSettings = settingsLoader.load(bufferedReader.lines().collect(Collectors.joining())); Map<String, String> loadedSettings = settingsLoader.load(bufferedReader.lines().collect(Collectors.joining()));
@ -255,6 +238,25 @@ public class DatastructureSettingsBuilder implements SettingsBuilder {
return this; return this;
} }
/**
* Loads settings from the actual string content that represents them using the
* {@link SettingsLoaderService#loaderFromResource(String)} (String)}.
*
* @param resourceName the resource name
* @param source the source
* @return builder
*/
@Override
public DatastructureSettingsBuilder loadFromString(String resourceName, String source) {
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
try {
put(settingsLoader.load(source));
} catch (Exception e) {
throw new SettingsException("failed to load settings from [" + source + "]", e);
}
return this;
}
/** /**
* Load system properties to this settings. * Load system properties to this settings.
* *

View file

@ -41,9 +41,4 @@ public class PropertiesSettingsLoader implements SettingsLoader {
} }
return result.build(); return result.build();
} }
@Override
public boolean canLoad(String source) {
return source != null && source.charAt(0) == '#';
}
} }

View file

@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test;
import org.xbib.settings.Settings; import org.xbib.settings.Settings;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
@ -126,7 +127,7 @@ public class SettingsTest {
@Test @Test
public void testPropertiesLoaderFromString() { public void testPropertiesLoaderFromString() {
Settings settings = Settings.settingsBuilder() Settings settings = Settings.settingsBuilder()
.loadFromString("#\na.b=c") .loadFromString("properties", "#\na.b=c")
.build(); .build();
assertEquals("{a.b=c}", settings.getAsMap().toString()); assertEquals("{a.b=c}", settings.getAsMap().toString());
} }