adding config loader
This commit is contained in:
parent
3ee81143b0
commit
7fb5d52466
10 changed files with 252 additions and 8 deletions
3
content-config/build.gradle
Normal file
3
content-config/build.gradle
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
dependencies {
|
||||||
|
api project(':content-yaml')
|
||||||
|
}
|
4
content-config/src/main/java/module-info.java
Normal file
4
content-config/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module org.xbib.content.config {
|
||||||
|
exports org.xbib.content.config;
|
||||||
|
requires transitive org.xbib.content.yaml;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
Loading…
Reference in a new issue