adding config loader

This commit is contained in:
Jörg Prante 2020-08-05 10:46:20 +02:00
parent 3ee81143b0
commit 7fb5d52466
10 changed files with 252 additions and 8 deletions

View file

@ -0,0 +1,3 @@
dependencies {
api project(':content-yaml')
}

View file

@ -0,0 +1,4 @@
module org.xbib.content.config {
exports org.xbib.content.config;
requires transitive org.xbib.content.yaml;
}

View file

@ -0,0 +1,130 @@
package org.xbib.content.config;
import org.xbib.content.json.JsonSettingsLoader;
import org.xbib.content.settings.Settings;
import org.xbib.content.settings.SettingsLoader;
import org.xbib.content.yaml.YamlSettingsLoader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* A configuration file loader for JSON/YAML configuration files.
*/
public class ConfigLoader {
private static final String JSON = ".json";
private static final String YML = ".yml";
private static final String YAML = ".yaml";
private final ConfigLogger logger;
public ConfigLoader(ConfigLogger logger) {
this.logger = logger;
}
public Settings.Builder loadSettings(ClassLoader classLoader,
String applicationName,
String... fileNamesWithoutSuffix) throws IOException {
for (String fileNameWithoutSuffix : fileNamesWithoutSuffix) {
Settings.Builder settings = createSettingsFromFile(createListOfLocations(applicationName, fileNameWithoutSuffix));
if (settings != null) {
return settings;
}
settings = createClasspathSettings(classLoader, applicationName, fileNameWithoutSuffix);
if (settings != null) {
return settings;
}
settings = createClasspathSettings(ConfigLoader.class.getClassLoader(), applicationName, fileNameWithoutSuffix);
if (settings != null) {
return settings;
}
settings = createClasspathSettings(ClassLoader.getSystemClassLoader(), applicationName, fileNameWithoutSuffix);
if (settings != null) {
return settings;
}
}
throw new IllegalArgumentException("no config found for " + applicationName + " "+ Arrays.asList(fileNamesWithoutSuffix));
}
private Settings.Builder createClasspathSettings(ClassLoader classLoader, String applicationName, String fileNameWithoutSuffix)
throws IOException {
for (String suffix : List.of(YML, YAML, JSON)) {
InputStream inputStream = classLoader.getResourceAsStream(applicationName + '-' + fileNameWithoutSuffix + suffix);
if (inputStream != null) {
logger.info("found resource: " + applicationName + '-' + fileNameWithoutSuffix + suffix);
Settings.Builder settings = createSettingsFromStream(inputStream, suffix);
if (settings != null) {
return settings;
}
}
}
return null;
}
private Settings.Builder createSettingsFromFile(List<String> settingsFileNames) throws IOException {
for (String settingsFileName: settingsFileNames) {
int pos = settingsFileName.lastIndexOf('.');
String suffix = (pos > 0 ? settingsFileName.substring(pos) : "").toLowerCase(Locale.ROOT);
Path path = Paths.get(settingsFileName);
logger.info("trying " + path.toString());
if (Files.exists(path)) {
logger.info("found path: " + path);
return createSettingsFromStream(Files.newInputStream(path), suffix);
}
}
return null;
}
private Settings.Builder createSettingsFromStream(InputStream inputStream, String suffix) throws IOException {
if (inputStream == null) {
logger.error("unable to open input stream");
return null;
}
SettingsLoader settingsLoader = isYaml(suffix) ? new YamlSettingsLoader() :
isJson(suffix) ? new JsonSettingsLoader() : null;
if (settingsLoader != null) {
Settings.Builder settings;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
String content = reader.lines().collect(Collectors.joining("\n"));
settings = Settings.settingsBuilder().put(settingsLoader.load(content));
}
return settings;
} else {
logger.error("suffix is invalid: " + suffix);
}
return null;
}
private static List<String> createListOfLocations(String applicationName, String fileNameWithoutSuffix) {
return List.of(
applicationName + '-' + fileNameWithoutSuffix + YML,
applicationName + '-' + fileNameWithoutSuffix + YAML,
applicationName + '-' + fileNameWithoutSuffix + JSON,
System.getProperty("user.home") + "/." + applicationName + '/' + fileNameWithoutSuffix + YML,
System.getProperty("user.home") + "/." + applicationName + '/' + fileNameWithoutSuffix + YAML,
System.getProperty("user.home") + "/." + applicationName + '/' + fileNameWithoutSuffix + JSON,
"/etc/" + applicationName + '/' + fileNameWithoutSuffix + YML,
"/etc/" + applicationName + '/' + fileNameWithoutSuffix + YAML,
"/etc/" + applicationName + '/' + fileNameWithoutSuffix + JSON);
}
private static boolean isYaml(String suffix) {
return YAML.equals(suffix) || YML.equals(suffix);
}
private static boolean isJson(String suffix) {
return JSON.equals(suffix);
}
}

View file

@ -0,0 +1,18 @@
package org.xbib.content.config;
import java.io.OutputStream;
public interface ConfigLogger {
void setLevel(String level);
void info(String string);
void error(String message);
void error(String message, Throwable throwable);
OutputStream getStderrOutputStream();
OutputStream getStdoutOutputStream();
}

View file

@ -0,0 +1,56 @@
package org.xbib.content.config;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* Format java exception messages and stack traces.
*/
public final class ExceptionFormatter {
private ExceptionFormatter() {
}
/**
* Format exception with stack trace.
*
* @param t the thrown object
* @return the formatted exception
*/
public static String format(Throwable t) {
StringBuilder sb = new StringBuilder();
append(sb, t, 0, true);
return sb.toString();
}
/**
* Append Exception to string builder.
*/
private static void append(StringBuilder sb, Throwable t, int level, boolean details) {
if (((t != null) && (t.getMessage() != null)) && (!t.getMessage().isEmpty())) {
if (details && (level > 0)) {
sb.append("\n\nCaused by\n");
}
sb.append(t.getMessage());
}
if (details) {
if (t != null) {
if ((t.getMessage() != null) && (t.getMessage().isEmpty())) {
sb.append("\n\nCaused by ");
} else {
sb.append("\n\n");
}
}
StringWriter sw = new StringWriter();
if (t != null) {
t.printStackTrace(new PrintWriter(sw));
}
sb.append(sw.toString());
}
if (t != null) {
if (t.getCause() != null) {
append(sb, t.getCause(), level + 1, details);
}
}
}
}

View file

@ -0,0 +1,37 @@
package org.xbib.content.config;
import java.io.OutputStream;
public class SystemConfigLogger implements ConfigLogger {
@Override
public void setLevel(String level) {
// d nothing
}
@Override
public void info(String string) {
System.out.println(string);
}
@Override
public void error(String message) {
System.err.println(message);
}
@Override
public void error(String message, Throwable throwable) {
System.err.println(message);
System.err.println(ExceptionFormatter.format(throwable));
}
@Override
public OutputStream getStderrOutputStream() {
return System.err;
}
@Override
public OutputStream getStdoutOutputStream() {
return System.out;
}
}

View file

@ -2,9 +2,6 @@ package org.xbib.content.json;
import org.xbib.content.XContent; import org.xbib.content.XContent;
import org.xbib.content.settings.AbstractSettingsLoader; import org.xbib.content.settings.AbstractSettingsLoader;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
@ -13,7 +10,7 @@ import java.util.Set;
*/ */
public class JsonSettingsLoader extends AbstractSettingsLoader { public class JsonSettingsLoader extends AbstractSettingsLoader {
private static final Set<String> JSON_SUFFIXES = new HashSet<>(Collections.singletonList("json")); private static final Set<String> JSON_SUFFIXES = Set.of("json");
@Override @Override
public XContent content() { public XContent content() {

View file

@ -3,8 +3,6 @@ package org.xbib.content.yaml;
import org.xbib.content.XContent; import org.xbib.content.XContent;
import org.xbib.content.settings.AbstractSettingsLoader; import org.xbib.content.settings.AbstractSettingsLoader;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -14,7 +12,7 @@ import java.util.Set;
*/ */
public class YamlSettingsLoader extends AbstractSettingsLoader { public class YamlSettingsLoader extends AbstractSettingsLoader {
private static final Set<String> YAML_SUFFIXES = new HashSet<>(Arrays.asList("yml", "yaml")); private static final Set<String> YAML_SUFFIXES = Set.of("yml", "yaml");
@Override @Override
public XContent content() { public XContent content() {

View file

@ -1,6 +1,6 @@
group = org.xbib group = org.xbib
name = content name = content
version = 2.3.2 version = 2.4.0
gradle.wrapper.version = 6.4.1 gradle.wrapper.version = 6.4.1
xbib.net.version = 2.1.0 xbib.net.version = 2.1.0

View file

@ -1,3 +1,4 @@
include 'content-config'
include 'content-core' include 'content-core'
include 'content-resource' include 'content-resource'
include 'content-language' include 'content-language'