move settings and datastructure projects from content to here
This commit is contained in:
parent
afec455270
commit
5f06b39eb0
61 changed files with 2535 additions and 6 deletions
|
@ -1,9 +1,9 @@
|
|||
plugins {
|
||||
id "io.morethan.jmhreport" version "0.9.0"
|
||||
id "org.cyclonedx.bom" version "1.7.2"
|
||||
id "com.github.spotbugs" version "5.0.13"
|
||||
id "checkstyle"
|
||||
id "pmd"
|
||||
id "io.morethan.jmhreport" version "0.9.0"
|
||||
id "org.cyclonedx.bom" version "1.7.4"
|
||||
id "com.github.spotbugs" version "6.0.0-beta.3"
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/test/jmh.gradle')
|
||||
|
|
|
@ -31,7 +31,7 @@ ext {
|
|||
}
|
||||
|
||||
subprojects {
|
||||
apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||
//apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||
|
|
5
config/build.gradle
Normal file
5
config/build.gradle
Normal file
|
@ -0,0 +1,5 @@
|
|||
dependencies {
|
||||
api project(':settings-datastructures')
|
||||
testImplementation project(':settings-datastructures-json')
|
||||
testImplementation project(':settings-datastructures-yaml')
|
||||
}
|
1
config/gradle.properties
Normal file
1
config/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
|||
version = 5.0.5
|
13
config/src/main/java/module-info.java
Normal file
13
config/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
import org.xbib.config.ConfigLogger;
|
||||
import org.xbib.config.NullConfigLogger;
|
||||
import org.xbib.config.SystemConfigLogger;
|
||||
import org.xbib.settings.SettingsLoader;
|
||||
|
||||
module org.xbib.config {
|
||||
exports org.xbib.config;
|
||||
uses ConfigLogger;
|
||||
uses SettingsLoader;
|
||||
provides ConfigLogger with NullConfigLogger, SystemConfigLogger;
|
||||
requires org.xbib.settings.api;
|
||||
requires transitive org.xbib.settings.datastructures;
|
||||
}
|
17
config/src/main/java/org/xbib/config/ConfigException.java
Normal file
17
config/src/main/java/org/xbib/config/ConfigException.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package org.xbib.config;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ConfigException extends RuntimeException {
|
||||
|
||||
public ConfigException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public ConfigException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ConfigException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
168
config/src/main/java/org/xbib/config/ConfigFinder.java
Normal file
168
config/src/main/java/org/xbib/config/ConfigFinder.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
package org.xbib.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ConfigFinder {
|
||||
|
||||
private final FileSystem fileSystem;
|
||||
|
||||
private final EnumSet<FileVisitOption> opts;
|
||||
|
||||
private final List<Path> result;
|
||||
|
||||
private Comparator<Path> comparator;
|
||||
|
||||
public ConfigFinder() {
|
||||
this(FileSystems.getDefault(), EnumSet.of(FileVisitOption.FOLLOW_LINKS));
|
||||
}
|
||||
|
||||
public ConfigFinder(FileSystem fileSystem, EnumSet<FileVisitOption> opts) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.opts = opts;
|
||||
this.result = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ConfigFinder find(String path, String pathPattern) throws IOException {
|
||||
return find(null, null, fileSystem.getPath(path), pathPattern);
|
||||
}
|
||||
|
||||
public ConfigFinder find(String base, String basePattern, String path, String pathPattern) throws IOException {
|
||||
return find(base == null || base.isEmpty() ? null : fileSystem.getPath(base), basePattern,
|
||||
path == null || path.isEmpty() ? null : fileSystem.getPath(path), pathPattern);
|
||||
}
|
||||
|
||||
public ConfigFinder find(Path base, String basePattern, Path path, String pathPattern) throws IOException {
|
||||
return find(base, basePattern, path, pathPattern, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the most recent version of a file.
|
||||
*
|
||||
* @param base the path of the base directory
|
||||
* @param basePattern a pattern to match directory entries in the base directory or null to match '*'
|
||||
* @param path the path of the file if no recent path can be found in the base directory or null
|
||||
* @param pathPattern the file name pattern to match
|
||||
* @param modifiedSince time stamp for file or null
|
||||
* @return this Finder
|
||||
* @throws IOException if find fails
|
||||
*/
|
||||
public ConfigFinder find(Path base,
|
||||
String basePattern,
|
||||
Path path,
|
||||
String pathPattern,
|
||||
FileTime modifiedSince) throws IOException {
|
||||
if (base != null && path == null) {
|
||||
// find input in base
|
||||
final PathMatcher baseMatcher = base.getFileSystem()
|
||||
.getPathMatcher("glob:" + (basePattern != null ? basePattern : "*"));
|
||||
final PathMatcher pathMatcher = base.getFileSystem()
|
||||
.getPathMatcher("glob:" + (pathPattern != null ? pathPattern : "*"));
|
||||
List<Path> directories = new ArrayList<>();
|
||||
List<Path> list = Files.find(base, 1,
|
||||
(p, a) -> {
|
||||
if (Files.isDirectory(p) && baseMatcher.matches(p.getFileName())) {
|
||||
directories.add(p);
|
||||
return false;
|
||||
}
|
||||
return Files.isRegularFile(p) && pathMatcher.matches(p.getFileName());
|
||||
}, FileVisitOption.FOLLOW_LINKS)
|
||||
.collect(Collectors.toList());
|
||||
if (directories.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
list.sort(LAST_MODIFIED_COMPARATOR.reversed());
|
||||
result.addAll(list);
|
||||
path = list.iterator().next();
|
||||
}
|
||||
if (path == null) {
|
||||
return this;
|
||||
}
|
||||
final PathMatcher pathMatcher = path.getFileSystem()
|
||||
.getPathMatcher("glob:" + (pathPattern != null ? pathPattern : "*"));
|
||||
Files.walkFileTree(path, opts, Integer.MAX_VALUE, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path p, BasicFileAttributes a) {
|
||||
if ((Files.isRegularFile(p) && pathMatcher.matches(p.getFileName())) &&
|
||||
(modifiedSince == null || a.lastModifiedTime().toMillis() > modifiedSince.toMillis())) {
|
||||
result.add(p);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigFinder sortBy(String mode) {
|
||||
if ("lastmodified".equals(mode)) {
|
||||
this.comparator = LAST_MODIFIED_COMPARATOR;
|
||||
} else if ("name".equals(mode)) {
|
||||
this.comparator = PATH_NAME_COMPARATOR;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigFinder order(String mode) {
|
||||
if ("desc".equals(mode)) {
|
||||
this.comparator = Collections.reverseOrder(comparator);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Stream<Path> getPathFiles() {
|
||||
return getPathFiles(-1);
|
||||
}
|
||||
|
||||
public Stream<Path> getPathFiles(long max) {
|
||||
if (comparator != null) {
|
||||
result.sort(comparator);
|
||||
}
|
||||
return result.stream().limit(max < 0 ? result.size() : max);
|
||||
}
|
||||
|
||||
public Stream<Path> skipPathFiles(long skip) {
|
||||
if (comparator != null) {
|
||||
result.sort(comparator);
|
||||
}
|
||||
return result.stream().skip(skip < 0 ? 0 : skip);
|
||||
}
|
||||
|
||||
public Stream<String> getPaths() {
|
||||
return getPaths(-1);
|
||||
}
|
||||
|
||||
public Stream<String> getPaths(long max) {
|
||||
if (comparator != null) {
|
||||
result.sort(comparator);
|
||||
}
|
||||
return result.stream()
|
||||
.map(p -> p.toAbsolutePath().toString())
|
||||
.limit(max < 0 ? result.size() : max);
|
||||
}
|
||||
|
||||
private static final Comparator<Path> LAST_MODIFIED_COMPARATOR = Comparator.comparing(p -> {
|
||||
try {
|
||||
return Files.getLastModifiedTime(p);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
private static final Comparator<Path> PATH_NAME_COMPARATOR = Comparator.comparing(Path::toString);
|
||||
}
|
311
config/src/main/java/org/xbib/config/ConfigLoader.java
Normal file
311
config/src/main/java/org/xbib/config/ConfigLoader.java
Normal file
|
@ -0,0 +1,311 @@
|
|||
package org.xbib.config;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
import org.xbib.settings.Settings;
|
||||
import org.xbib.settings.SettingsBuilder;
|
||||
import org.xbib.settings.SettingsLoader;
|
||||
import org.xbib.settings.SettingsLoaderService;
|
||||
|
||||
/**
|
||||
* A configuration loader for configuration files.
|
||||
*/
|
||||
public class ConfigLoader {
|
||||
|
||||
private static final Map<ConfigParams, Settings> map = new HashMap<>();
|
||||
|
||||
private ConfigLogger logger;
|
||||
|
||||
private ConfigLoader() {
|
||||
}
|
||||
|
||||
private static class Holder {
|
||||
private static ConfigLogger createConfigLogger() {
|
||||
ServiceLoader<ConfigLogger> serviceLoader = ServiceLoader.load(ConfigLogger.class);
|
||||
Optional<ConfigLogger> optionalConfigLogger = serviceLoader.findFirst();
|
||||
return optionalConfigLogger.orElse(new NullConfigLogger());
|
||||
}
|
||||
|
||||
private static final ConfigLoader configLoader = new ConfigLoader().withLogger(createConfigLogger());
|
||||
}
|
||||
|
||||
public static ConfigLoader getInstance() {
|
||||
return Holder.configLoader;
|
||||
}
|
||||
|
||||
public ConfigLoader withLogger(ConfigLogger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public synchronized Settings load(ConfigParams configParams) throws ConfigException {
|
||||
map.computeIfAbsent(configParams, p -> internalLoad(p)
|
||||
.replacePropertyPlaceholders()
|
||||
.build());
|
||||
return map.get(configParams);
|
||||
}
|
||||
|
||||
private SettingsBuilder internalLoad(ConfigParams params) throws ConfigException {
|
||||
SettingsBuilder settings = Settings.settingsBuilder();
|
||||
if (params.withSystemEnvironment) {
|
||||
settings.loadFromSystemEnvironment();
|
||||
}
|
||||
if (params.withSystemProperties) {
|
||||
settings.loadFromSystemProperties();
|
||||
}
|
||||
if (!params.settings.isEmpty()) {
|
||||
for (Settings s : params.settings) {
|
||||
settings.put(s);
|
||||
}
|
||||
}
|
||||
if (!params.reader.isEmpty()) {
|
||||
for (ConfigParams.SuffixedReader reader : params.reader) {
|
||||
SettingsBuilder readerSettings = createSettingsFromReader(reader.reader, reader.suffix);
|
||||
if (readerSettings != null) {
|
||||
settings.put(readerSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (params.args != null) {
|
||||
SettingsBuilder argsSettings = createSettingsFromArgs(params);
|
||||
if (argsSettings != null) {
|
||||
settings.put(argsSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (params.withStdin) {
|
||||
SettingsBuilder stdinSettings = createSettingsFromStdin();
|
||||
if (stdinSettings != null) {
|
||||
settings.put(stdinSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!params.fileLocations.isEmpty()) {
|
||||
SettingsBuilder fileSettings = createSettingsFromFile(params.fileLocations);
|
||||
if (fileSettings != null) {
|
||||
settings.put(fileSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!params.fileNamesWithoutSuffix.isEmpty()) {
|
||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
||||
SettingsBuilder fileSettings = createSettingsFromFile(createListOfLocations(params, fileNameWithoutSuffix));
|
||||
if (fileSettings != null) {
|
||||
settings.put(fileSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
||||
if (params.classLoaders != null) {
|
||||
for (ClassLoader cl : params.classLoaders) {
|
||||
if (cl != null) {
|
||||
SettingsBuilder classpathSettings = createClasspathSettings(params, cl, fileNameWithoutSuffix);
|
||||
if (classpathSettings != null) {
|
||||
settings.put(classpathSettings.build());
|
||||
if (!params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!params.jdbcLookups.isEmpty()) {
|
||||
for (ConfigParams.JdbcLookup jdbcLookup : params.jdbcLookups) {
|
||||
try {
|
||||
settings.fromJdbc(jdbcLookup.connection, jdbcLookup.statement, jdbcLookup.params);
|
||||
} catch (SQLException sqlException) {
|
||||
throw new ConfigException(sqlException);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (params.includeAll) {
|
||||
return overrideFromProperties(params, settings);
|
||||
}
|
||||
if (params.failIfEmpty) {
|
||||
throw new ConfigException("no config found");
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
private SettingsBuilder createSettingsFromArgs(ConfigParams params) throws ConfigException {
|
||||
if (!params.fileNamesWithoutSuffix.isEmpty() && params.args != null) {
|
||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
||||
for (int i = 0; i < params.args.size() - 1; i++) {
|
||||
String arg = params.args.get(i);
|
||||
String s = params.directoryName != null ?
|
||||
"--" + params.directoryName + "-" + fileNameWithoutSuffix + "." + suffix :
|
||||
"--" + fileNameWithoutSuffix + "." + suffix;
|
||||
if (arg.equals(s)) {
|
||||
return createSettingsFromReader(new StringReader(params.args.get(i + 1)), suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SettingsBuilder createSettingsFromStdin() throws ConfigException {
|
||||
if (System.in != null) {
|
||||
try {
|
||||
int numBytesWaiting = System.in.available();
|
||||
if (numBytesWaiting > 0) {
|
||||
String suffix = System.getProperty("config.format", "yaml");
|
||||
return createSettingsFromStream(System.in, "." + suffix);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ConfigException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SettingsBuilder createSettingsFromFile(List<String> settingsFileNames) throws ConfigException {
|
||||
SettingsBuilder settings = Settings.settingsBuilder();
|
||||
for (String settingsFileName: settingsFileNames) {
|
||||
int pos = settingsFileName.lastIndexOf('.');
|
||||
String suffix = (pos > 0 ? settingsFileName.substring(pos + 1) : "").toLowerCase(Locale.ROOT);
|
||||
Path path = Paths.get(settingsFileName);
|
||||
if (logger != null) {
|
||||
logger.info("trying " + path);
|
||||
}
|
||||
if (Files.exists(path)) {
|
||||
if (logger != null) {
|
||||
logger.info("found path: " + path);
|
||||
}
|
||||
System.setProperty("config.path", path.getParent().toString());
|
||||
try {
|
||||
InputStream inputStream = Files.newInputStream(path);
|
||||
SettingsBuilder fileSettings = createSettingsFromStream(inputStream, suffix);
|
||||
if (fileSettings != null) {
|
||||
settings.put(fileSettings.build());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ConfigException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings.isEmpty() ? null : settings;
|
||||
}
|
||||
|
||||
private SettingsBuilder createClasspathSettings(ConfigParams params,
|
||||
ClassLoader classLoader,
|
||||
String fileNameWithoutSuffix) throws ConfigException {
|
||||
SettingsBuilder settings = Settings.settingsBuilder();
|
||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
||||
String path = params.directoryName != null ?
|
||||
params.directoryName + '-' + fileNameWithoutSuffix + suffix : fileNameWithoutSuffix + suffix;
|
||||
InputStream inputStream = classLoader.getResourceAsStream(path);
|
||||
if (inputStream != null) {
|
||||
if (logger != null) {
|
||||
logger.info("found resource: " + path);
|
||||
}
|
||||
SettingsBuilder streamSettings = createSettingsFromStream(inputStream, suffix);
|
||||
if (streamSettings != null) {
|
||||
settings.put(streamSettings.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings.isEmpty() ? null : settings;
|
||||
}
|
||||
|
||||
private SettingsBuilder createSettingsFromStream(InputStream inputStream,
|
||||
String suffix) throws ConfigException {
|
||||
if (inputStream == null) {
|
||||
if (logger != null) {
|
||||
logger.error("unable to open input stream");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return createSettingsFromReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), suffix);
|
||||
}
|
||||
|
||||
private SettingsBuilder createSettingsFromReader(Reader reader,
|
||||
String suffix) throws ConfigException {
|
||||
if (reader == null) {
|
||||
if (logger != null) {
|
||||
logger.error("unable to open reader");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
SettingsLoader settingsLoader = SettingsLoaderService.getInstance().loaderFromResource(suffix);
|
||||
if (settingsLoader != null) {
|
||||
SettingsBuilder settings;
|
||||
try (BufferedReader bufferedReader = new BufferedReader(reader)) {
|
||||
String content = bufferedReader.lines().collect(Collectors.joining("\n"));
|
||||
settings = Settings.settingsBuilder().put(settingsLoader.load(content));
|
||||
} catch (IOException e) {
|
||||
throw new ConfigException(e);
|
||||
}
|
||||
return settings;
|
||||
} else {
|
||||
if (logger != null) {
|
||||
logger.error("suffix is invalid: " + suffix);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SettingsBuilder overrideFromProperties(ConfigParams params, SettingsBuilder settingsBuilder) {
|
||||
if (params.withSystemPropertiesOverride) {
|
||||
settingsBuilder.map(e -> {
|
||||
String key = e.getKey();
|
||||
String value = System.getProperty(params.directoryName != null ? params.directoryName + '.' + key : key);
|
||||
return value != null ? Map.entry(key, value) : Map.entry(key, e.getValue());
|
||||
});
|
||||
}
|
||||
return settingsBuilder;
|
||||
}
|
||||
|
||||
private List<String> createListOfLocations(ConfigParams params,
|
||||
String fileNameWithoutSuffix) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
||||
String xdgConfigHome = System.getenv("XDG_CONFIG_HOME");
|
||||
if (xdgConfigHome == null) {
|
||||
xdgConfigHome = System.getProperty("user.home") + "/.config";
|
||||
}
|
||||
if (params.directoryName != null) {
|
||||
list.add(params.directoryName + '-' + fileNameWithoutSuffix + "." + suffix);
|
||||
list.add(xdgConfigHome + '/' + params.directoryName + '/' + fileNameWithoutSuffix + "." + suffix);
|
||||
list.add("/etc/" + params.directoryName + '/' + fileNameWithoutSuffix + "." + suffix);
|
||||
} else {
|
||||
list.add(fileNameWithoutSuffix + "." + suffix);
|
||||
list.add(xdgConfigHome + '/' + fileNameWithoutSuffix + "." + suffix);
|
||||
list.add("/etc/" + fileNameWithoutSuffix + "." + suffix);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
10
config/src/main/java/org/xbib/config/ConfigLogger.java
Normal file
10
config/src/main/java/org/xbib/config/ConfigLogger.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package org.xbib.config;
|
||||
|
||||
public interface ConfigLogger {
|
||||
|
||||
void info(String string);
|
||||
|
||||
void warn(String string);
|
||||
|
||||
void error(String message);
|
||||
}
|
192
config/src/main/java/org/xbib/config/ConfigParams.java
Normal file
192
config/src/main/java/org/xbib/config/ConfigParams.java
Normal file
|
@ -0,0 +1,192 @@
|
|||
package org.xbib.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.xbib.settings.Settings;
|
||||
import org.xbib.settings.datastructures.DatastructureSettings;
|
||||
|
||||
public class ConfigParams implements Comparable<ConfigParams> {
|
||||
|
||||
private static final Comparator<ConfigParams> COMPARATOR =
|
||||
Comparator.comparing(ConfigParams::toString);
|
||||
|
||||
boolean withSystemEnvironment = false;
|
||||
|
||||
boolean withSystemProperties = false;
|
||||
|
||||
boolean failIfEmpty = false;
|
||||
|
||||
boolean includeAll = false;
|
||||
|
||||
boolean withStdin = false;
|
||||
|
||||
boolean withSystemPropertiesOverride = false;
|
||||
|
||||
List<ClassLoader> classLoaders = null;
|
||||
|
||||
final List<SuffixedReader> reader = new ArrayList<>();
|
||||
|
||||
final List<JdbcLookup> jdbcLookups = new ArrayList<>();
|
||||
|
||||
final List<DatastructureSettings> settings = new ArrayList<>();
|
||||
|
||||
List<String> args = null;
|
||||
|
||||
String directoryName = null;
|
||||
|
||||
final List<String> fileNamesWithoutSuffix = new ArrayList<>();
|
||||
|
||||
final List<String> fileLocations = new ArrayList<>();
|
||||
|
||||
public ConfigParams() {
|
||||
}
|
||||
|
||||
public ConfigParams withSystemEnvironment() {
|
||||
this.withSystemEnvironment = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withSystemProperties() {
|
||||
this.withSystemProperties = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withSystemPropertiesOverride() {
|
||||
this.withSystemPropertiesOverride = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams includeAll() {
|
||||
this.includeAll = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams failIfEmpty() {
|
||||
this.failIfEmpty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withStdin(boolean withStdin) {
|
||||
this.withStdin = withStdin;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withArgs(String[] args) {
|
||||
this.args = Arrays.asList(args);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withClassLoaders(ClassLoader... classLoaders) {
|
||||
this.classLoaders = Arrays.asList(classLoaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withReader(Reader reader, String suffix) {
|
||||
SuffixedReader suffixedReader = new SuffixedReader();
|
||||
suffixedReader.reader = reader;
|
||||
suffixedReader.suffix = suffix;
|
||||
this.reader.add(suffixedReader);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withSettings(Settings settings) {
|
||||
this.settings.add(DatastructureSettings.builder().put(settings.getAsMap()).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withDirectoryName(String directoryName) {
|
||||
this.directoryName = directoryName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withFileNamesWithoutSuffix(String... fileNamesWithoutSuffix) {
|
||||
this.fileNamesWithoutSuffix.addAll(Arrays.asList(fileNamesWithoutSuffix));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withLocation(String location) {
|
||||
this.fileLocations.add(location);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withPath(String basePath, String basePattern, String path, String pathPattern) throws IOException {
|
||||
ConfigFinder configFinder = new ConfigFinder();
|
||||
configFinder.find(basePath, basePattern, path, pathPattern).getPaths().forEach(this::withLocation);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigParams withJdbc(Connection connection, String statement, String[] params) {
|
||||
JdbcLookup jdbcLookup = new JdbcLookup();
|
||||
jdbcLookup.connection = connection;
|
||||
jdbcLookup.statement = statement;
|
||||
jdbcLookup.params = params;
|
||||
jdbcLookups.add(jdbcLookup);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ConfigParams that = (ConfigParams) o;
|
||||
return withSystemEnvironment == that.withSystemEnvironment &&
|
||||
withSystemProperties == that.withSystemProperties &&
|
||||
failIfEmpty == that.failIfEmpty &&
|
||||
includeAll == that.includeAll &&
|
||||
withStdin == that.withStdin &&
|
||||
withSystemPropertiesOverride == that.withSystemPropertiesOverride &&
|
||||
Objects.equals(classLoaders, that.classLoaders) &&
|
||||
Objects.equals(reader, that.reader) &&
|
||||
Objects.equals(jdbcLookups, that.jdbcLookups) &&
|
||||
Objects.equals(settings, that.settings) &&
|
||||
Objects.equals(args, that.args) &&
|
||||
Objects.equals(directoryName, that.directoryName) &&
|
||||
Objects.equals(fileNamesWithoutSuffix, that.fileNamesWithoutSuffix) &&
|
||||
Objects.equals(fileLocations, that.fileLocations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ConfigParams o) {
|
||||
return COMPARATOR.compare(this, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" +
|
||||
withSystemEnvironment +
|
||||
withSystemProperties +
|
||||
withStdin +
|
||||
classLoaders +
|
||||
reader +
|
||||
args +
|
||||
directoryName +
|
||||
fileNamesWithoutSuffix +
|
||||
fileLocations;
|
||||
}
|
||||
|
||||
static class SuffixedReader {
|
||||
Reader reader;
|
||||
String suffix;
|
||||
}
|
||||
|
||||
static class JdbcLookup {
|
||||
Connection connection;
|
||||
String statement;
|
||||
String[] params;
|
||||
}
|
||||
}
|
19
config/src/main/java/org/xbib/config/NullConfigLogger.java
Normal file
19
config/src/main/java/org/xbib/config/NullConfigLogger.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package org.xbib.config;
|
||||
|
||||
public class NullConfigLogger implements ConfigLogger {
|
||||
|
||||
public NullConfigLogger() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String string) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
}
|
||||
}
|
22
config/src/main/java/org/xbib/config/SystemConfigLogger.java
Normal file
22
config/src/main/java/org/xbib/config/SystemConfigLogger.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
package org.xbib.config;
|
||||
|
||||
public class SystemConfigLogger implements ConfigLogger {
|
||||
|
||||
public SystemConfigLogger() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String string) {
|
||||
System.err.println("info: " + string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String message) {
|
||||
System.err.println("warning: " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
System.err.println("error: " + message);
|
||||
}
|
||||
}
|
4
config/src/main/java/org/xbib/config/package-info.java
Normal file
4
config/src/main/java/org/xbib/config/package-info.java
Normal file
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Classes for configuration setup.
|
||||
*/
|
||||
package org.xbib.config;
|
|
@ -0,0 +1,76 @@
|
|||
package org.xbib.config.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.config.ConfigLoader;
|
||||
import org.xbib.config.ConfigParams;
|
||||
import org.xbib.settings.Settings;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ConfigLoaderTest {
|
||||
|
||||
@Test
|
||||
public void configEmptyTest() {
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams());
|
||||
assertTrue(settings.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configSettingsTest() {
|
||||
Settings configSettings = Settings.settingsBuilder()
|
||||
.put("hello", "world")
|
||||
.build();
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams().withSettings(configSettings));
|
||||
assertEquals("world", settings.get("hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configArgsTest() {
|
||||
String[] args = new String[] {
|
||||
"--config.yaml",
|
||||
"hello: world"
|
||||
};
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams()
|
||||
.withArgs(args)
|
||||
.withFileNamesWithoutSuffix("config"));
|
||||
assertEquals("world", settings.get("hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configPropertiesTest() {
|
||||
Reader reader = new StringReader("a=b");
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams()
|
||||
.withReader(reader, "properties"));
|
||||
assertEquals("b", settings.get("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configFileTest() throws IOException {
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams()
|
||||
.withPath(null, null, "src/test/resources", "config.*"));
|
||||
assertEquals("world", settings.get("hello"));
|
||||
assertEquals("world2", settings.get("hello2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemPropertiesOverride() throws IOException {
|
||||
System.setProperty("hello", "override");
|
||||
Settings settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams()
|
||||
.withPath(null, null, "src/test/resources", "config.*"));
|
||||
assertEquals("world", settings.get("hello"));
|
||||
settings = ConfigLoader.getInstance()
|
||||
.load(new ConfigParams()
|
||||
.withSystemPropertiesOverride()
|
||||
.withPath(null, null, "src/test/resources", "config.*"));
|
||||
assertEquals("override", settings.get("hello"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Test classes for config.
|
||||
*/
|
||||
package org.xbib.config.test;
|
|
@ -0,0 +1,2 @@
|
|||
org.xbib.config.NullConfigLogger
|
||||
org.xbib.config.SystemConfigLogger
|
|
@ -0,0 +1,3 @@
|
|||
org.xbib.settings.datastructures.PropertiesSettingsLoader
|
||||
org.xbib.settings.datastructures.json.JsonSettingsLoader
|
||||
org.xbib.settings.datastructures.yaml.YamlSettingsLoader
|
3
config/src/test/resources/config.json
Normal file
3
config/src/test/resources/config.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"hello2": "world2"
|
||||
}
|
1
config/src/test/resources/config.yaml
Normal file
1
config/src/test/resources/config.yaml
Normal file
|
@ -0,0 +1 @@
|
|||
hello: world
|
|
@ -7,8 +7,8 @@ sourceSets {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
jmhImplementation 'org.openjdk.jmh:jmh-core:1.32'
|
||||
jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.32'
|
||||
jmhImplementation 'org.openjdk.jmh:jmh-core:1.37'
|
||||
jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
|
||||
}
|
||||
|
||||
task jmh(type: JavaExec, group: 'jmh', dependsOn: jmhClasses) {
|
||||
|
|
3
settings-api/build.gradle
Normal file
3
settings-api/build.gradle
Normal file
|
@ -0,0 +1,3 @@
|
|||
dependencies {
|
||||
api project(':datastructures-api')
|
||||
}
|
1
settings-api/gradle.properties
Normal file
1
settings-api/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
|||
version = 5.0.5
|
10
settings-api/src/main/java/module-info.java
Normal file
10
settings-api/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
import org.xbib.settings.SettingsBuilder;
|
||||
import org.xbib.settings.SettingsLoader;
|
||||
|
||||
module org.xbib.settings.api {
|
||||
exports org.xbib.settings;
|
||||
uses SettingsBuilder;
|
||||
uses SettingsLoader;
|
||||
requires transitive org.xbib.datastructures.api;
|
||||
requires transitive java.sql;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.xbib.settings;
|
||||
|
||||
/**
|
||||
* Strategy interface used to resolve replacement values for placeholders contained in Strings.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface PlaceholderResolver {
|
||||
|
||||
/**
|
||||
* Resolves the supplied placeholder name into the replacement value.
|
||||
*
|
||||
* @param placeholderName the name of the placeholder to resolve.
|
||||
* @return the replacement value or <code>null</code> if no replacement is to be made.
|
||||
*/
|
||||
String resolvePlaceholder(String placeholderName);
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package org.xbib.settings;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class PropertyPlaceholder {
|
||||
|
||||
private final String placeholderPrefix;
|
||||
|
||||
private final String placeholderSuffix;
|
||||
|
||||
private final boolean ignoreUnresolvablePlaceholders;
|
||||
|
||||
/**
|
||||
* Creates a new <code>PropertyPlaceholderHelper</code> that uses the supplied prefix and suffix.
|
||||
*
|
||||
* @param placeholderPrefix the prefix that denotes the start of a placeholder.
|
||||
* @param placeholderSuffix the suffix that denotes the end of a placeholder.
|
||||
* @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored
|
||||
* (<code>true</code>) or cause an exception (<code>false</code>).
|
||||
*/
|
||||
public PropertyPlaceholder(String placeholderPrefix,
|
||||
String placeholderSuffix,
|
||||
boolean ignoreUnresolvablePlaceholders) {
|
||||
this.placeholderPrefix = placeholderPrefix;
|
||||
this.placeholderSuffix = placeholderSuffix;
|
||||
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all placeholders of format <code>${name}</code> with the value returned from the supplied {@link
|
||||
* PlaceholderResolver}.
|
||||
*
|
||||
* @param value the value containing the placeholders to be replaced.
|
||||
* @param placeholderResolver the <code>PlaceholderResolver</code> to use for replacement.
|
||||
* @return the supplied value with placeholders replaced inline.
|
||||
*/
|
||||
public String replacePlaceholders(String value,
|
||||
PlaceholderResolver placeholderResolver) {
|
||||
return parseStringValue(value, placeholderResolver, new HashSet<>());
|
||||
}
|
||||
|
||||
protected String parseStringValue(String value,
|
||||
PlaceholderResolver placeholderResolver,
|
||||
Set<String> visitedPlaceholders) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(value);
|
||||
int startIndex = value.indexOf(this.placeholderPrefix);
|
||||
while (startIndex != -1) {
|
||||
int endIndex = findPlaceholderEndIndex(sb, startIndex);
|
||||
if (endIndex != -1) {
|
||||
String placeholder = sb.substring(startIndex + this.placeholderPrefix.length(), endIndex);
|
||||
if (!visitedPlaceholders.add(placeholder)) {
|
||||
throw new IllegalArgumentException("Circular placeholder reference '" + placeholder + "' in property definitions");
|
||||
}
|
||||
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
|
||||
int defaultValueIdx = placeholder.indexOf(':');
|
||||
String defaultValue = null;
|
||||
if (defaultValueIdx != -1) {
|
||||
defaultValue = placeholder.substring(defaultValueIdx + 1);
|
||||
placeholder = placeholder.substring(0, defaultValueIdx);
|
||||
}
|
||||
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
|
||||
if (propVal == null) {
|
||||
propVal = defaultValue;
|
||||
}
|
||||
if (propVal != null) {
|
||||
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
|
||||
sb.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
|
||||
startIndex = sb.indexOf(this.placeholderPrefix, startIndex + propVal.length());
|
||||
} else if (this.ignoreUnresolvablePlaceholders) {
|
||||
// Proceed with unprocessed value.
|
||||
startIndex = sb.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
|
||||
} else {
|
||||
throw new IllegalArgumentException("could not resolve placeholder '" + placeholder + "'");
|
||||
}
|
||||
visitedPlaceholders.remove(placeholder);
|
||||
} else {
|
||||
startIndex = -1;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private int findPlaceholderEndIndex(CharSequence charSequence, int startIndex) {
|
||||
int index = startIndex + this.placeholderPrefix.length();
|
||||
int withinNestedPlaceholder = 0;
|
||||
while (index < charSequence.length()) {
|
||||
if (substringMatch(charSequence, index, this.placeholderSuffix)) {
|
||||
if (withinNestedPlaceholder > 0) {
|
||||
withinNestedPlaceholder--;
|
||||
index = index + this.placeholderPrefix.length() - 1;
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
} else if (substringMatch(charSequence, index, this.placeholderPrefix)) {
|
||||
withinNestedPlaceholder++;
|
||||
index = index + this.placeholderPrefix.length();
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private boolean substringMatch(CharSequence charSequence, int index, CharSequence substring) {
|
||||
for (int j = 0; j < substring.length(); j++) {
|
||||
int i = index + j;
|
||||
if (i >= charSequence.length() || charSequence.charAt(i) != substring.charAt(j)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
71
settings-api/src/main/java/org/xbib/settings/Settings.java
Normal file
71
settings-api/src/main/java/org/xbib/settings/Settings.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
package org.xbib.settings;
|
||||
|
||||
import org.xbib.datastructures.api.ByteSizeValue;
|
||||
import org.xbib.datastructures.api.TimeValue;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public interface Settings extends AutoCloseable {
|
||||
|
||||
class Holder {
|
||||
|
||||
private Holder() {
|
||||
}
|
||||
|
||||
private static SettingsBuilder createBuilder() {
|
||||
ServiceLoader<SettingsBuilder> serviceLoader = ServiceLoader.load(SettingsBuilder.class);
|
||||
Optional<SettingsBuilder> optionalSettingsBuilder = serviceLoader.findFirst();
|
||||
return optionalSettingsBuilder.orElse(null);
|
||||
}
|
||||
|
||||
private static final Settings emptySettings = createBuilder().build();
|
||||
}
|
||||
|
||||
static SettingsBuilder settingsBuilder() {
|
||||
return Holder.createBuilder();
|
||||
}
|
||||
|
||||
static Settings emptySettings() {
|
||||
return Holder.emptySettings;
|
||||
}
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
String get(String setting);
|
||||
|
||||
String get(String setting, String defaultValue);
|
||||
|
||||
float getAsFloat(String setting, float defaultValue);
|
||||
|
||||
double getAsDouble(String setting, double defaultValue);
|
||||
|
||||
int getAsInt(String setting, int defaultValue);
|
||||
|
||||
long getAsLong(String setting, long defaultValue);
|
||||
|
||||
boolean getAsBoolean(String setting, boolean defaultValue);
|
||||
|
||||
TimeValue getAsTime(String setting, TimeValue defaultValue);
|
||||
|
||||
ByteSizeValue getAsBytesSize(String setting, ByteSizeValue defaultValue);
|
||||
|
||||
String[] getAsArray(String settingPrefix);
|
||||
|
||||
String[] getAsArray(String settingPrefix, String[] defaultArray);
|
||||
|
||||
Map<String, String> getAsMap();
|
||||
|
||||
Map<String, Object> getAsStructuredMap();
|
||||
|
||||
Map<String, Settings> getGroups(String prefix);
|
||||
|
||||
Settings getAsSettings(String setting);
|
||||
|
||||
Settings getByPrefix(String prefix);
|
||||
|
||||
boolean containsSetting(String setting);
|
||||
|
||||
void close() throws IOException;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.xbib.settings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface SettingsBuilder {
|
||||
|
||||
SettingsBuilder put(String setting, String value);
|
||||
|
||||
SettingsBuilder put(String setting, boolean value);
|
||||
|
||||
SettingsBuilder put(String setting, int value);
|
||||
|
||||
SettingsBuilder put(String setting, long value);
|
||||
|
||||
SettingsBuilder put(String setting, float value);
|
||||
|
||||
SettingsBuilder put(String setting, double value);
|
||||
|
||||
SettingsBuilder putArray(String setting, String... values);
|
||||
|
||||
SettingsBuilder putArray(String setting, List<String> values);
|
||||
|
||||
SettingsBuilder put(String settingPrefix, String groupName, String[] settings, String[] values)
|
||||
throws SettingsException;
|
||||
|
||||
SettingsBuilder put(Settings settings);
|
||||
|
||||
SettingsBuilder put(Map<String, String> settings);
|
||||
|
||||
SettingsBuilder loadFromString(String resourceName, String content);
|
||||
|
||||
SettingsBuilder loadFromResource(String resourceName, InputStream inputStream);
|
||||
|
||||
default SettingsBuilder fromJdbc(Connection connection, String statement, String[] params) throws SQLException {
|
||||
try (PreparedStatement preparedStatement = connection.prepareStatement(statement, params);
|
||||
ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
String key = resultSet.getString("key");
|
||||
String value = resultSet.getString("value");
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
SettingsBuilder loadFromSystemProperties();
|
||||
|
||||
SettingsBuilder loadFromSystemEnvironment();
|
||||
|
||||
/**
|
||||
* Runs across all the settings set on this builder and replaces {@code ${...}} elements in the
|
||||
* each setting value according to the following logic:
|
||||
* First, tries to resolve it against a System property ({@link System#getProperty(String)}), next,
|
||||
* tries and resolve it against an environment variable ({@link System#getenv(String)}), next,
|
||||
* tries and resolve it against a date pattern to resolve the current date,
|
||||
* and last, tries and replace it with another setting already set on this builder.
|
||||
* @param propertyPlaceholder the property place holder
|
||||
* @param placeholderResolver the place holder resolver
|
||||
* @return this builder
|
||||
*/
|
||||
SettingsBuilder replacePropertyPlaceholders(PropertyPlaceholder propertyPlaceholder,
|
||||
PlaceholderResolver placeholderResolver);
|
||||
|
||||
/**
|
||||
* A default method to replace property placeholders.
|
||||
* @return this builder
|
||||
*/
|
||||
SettingsBuilder replacePropertyPlaceholders();
|
||||
|
||||
/**
|
||||
* Optional settings refresh mechanism, using reloading from a path after a give time period.
|
||||
* May not be implemented at all.
|
||||
*/
|
||||
SettingsBuilder setRefresh(Path path, long initialDelay, long period, TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Map all settings keys and values to other keys and values.
|
||||
* Example usage is to override settings from another priority source.
|
||||
* @return this builder
|
||||
*/
|
||||
SettingsBuilder map(Function<Map.Entry<String, String>, Map.Entry<String, String>> function);
|
||||
|
||||
/**
|
||||
* Return the Settings from this SettingsBuilder.
|
||||
* @return the settings
|
||||
*/
|
||||
Settings build();
|
||||
|
||||
/**
|
||||
* Returns true if the settings builder is empty.
|
||||
* @return true if empty
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.xbib.settings;
|
||||
|
||||
/**
|
||||
* A generic failure to handle settings.
|
||||