com.bluetrainsoftware.common.config.BatheTimeWatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stickycode-extended-config Show documentation
Show all versions of stickycode-extended-config Show documentation
Extends the functionality of Spring Boot and Sticky Code and provides extra support for Kubernetes style mounted volumes.
package com.bluetrainsoftware.common.config;
import bathe.BatheInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.StringUtils;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.parser.ParserException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author Richard Vowles - https://plus.google.com/+RichardVowles
*/
public class BatheTimeWatcher extends BaseConfigurationFileWatcher implements BatheInitializer {
private static final Logger log = LoggerFactory.getLogger(BatheTimeWatcher.class);
private static final String MINUS_D = "-D";
private static final String MINUS_P = "-P";
@PreStart
public void start() {
startWatching();
}
@Override
public int getOrder() {
return -1;
}
@Override
public String getName() {
return "bathe-system-property";
}
@Override
public String[] initialize(String[] args, String jumpClass) {
List appArguments = new ArrayList<>();
for (String arg : args) {
if (arg.startsWith(MINUS_D)) {
String property = arg.substring(MINUS_D.length());
int equals = property.indexOf('=');
if (equals >= 0)
System.setProperty(property.substring(0, equals), property.substring(equals + 1));
else
System.setProperty(property, Boolean.TRUE.toString());
} else if (arg.startsWith(MINUS_P)) {
try {
loadProperties(arg.substring(MINUS_P.length()));
} catch (IOException e) {
e.printStackTrace();
}
} else
appArguments.add(arg);
}
return appArguments.toArray(new String[0]);
}
private boolean isWindows() {
return ";".equals(File.pathSeparator);
}
private void loadProperties(String originalUrl) throws IOException {
Properties loadingProperties = new DuplicateProperties();
String url = decodeUrl(originalUrl);
if (url.startsWith("classpath:")) {
singleLoadClasspath(url, loadingProperties);
} else if (url.contains(":") && (!isWindows() || url.indexOf(':') > 1)) { // deal with c: d: garbage
singleLoadUrl(url, loadingProperties);
} else {
File properties = new File(url);
if (properties.exists()) {
if (isYaml(properties) || isProperties(properties)) {
watchedFiles.add(properties);
}
}
}
System.getProperties().putAll(loadingProperties);
}
/*
* Allow for ${user.home}, ${jdk.home} and similar.
*/
protected String decodeUrl(String url) {
int idx = url.indexOf("${");
while (idx > -1) {
String part1 = url.substring(0, idx);
String part2 = url.substring(idx+2);
int idx2 = part2.indexOf("}");
if (idx2 == -1) {
url = part1 + "\\$\\{" + part2;
} else {
String part3 = part2.substring(idx2+1);
url = part1 + System.getProperty(part2.substring(0, idx2), "") + part3;
}
idx = url.indexOf("${");
}
return url.replace("\\$\\{", "${");
}
private void singleLoadUrl(String url, Properties loadingProperties) throws IOException {
URL source = new URL(url);
InputStream is = source.openStream();
loadingProperties.load(is);
is.close();
}
private void singleLoadClasspath(String url, Properties loadingProperties) throws IOException {
InputStream is = getClass().getResourceAsStream(url.substring(10));
if (is == null) {
System.err.println("Failed to load ${url} (${url.substring(10)})");
} else {
loadingProperties.load(is);
is.close();
}
}
@Override
protected MapPropertySource loadPropertyFile(File propertyFile) {
if (isYaml(propertyFile)) {
return loadYamlFile(propertyFile);
} else {
return loadPropertyFileContents(propertyFile);
}
}
@SuppressWarnings("unchecked")
protected MapPropertySource loadYamlFile(File yamlFile) {
Yaml parser = new Yaml(new StrictMapAppenderConstructor());
try {
Map yamlProperties = (Map) parser.load(new FileReader(yamlFile));
Map result = new LinkedHashMap();
buildFlattenedMap(result, yamlProperties, null);
return new MapPropertySource(yamlFile.getAbsolutePath(), result);
} catch (FileNotFoundException e) {
System.out.println("Unable to find file " + yamlFile.getAbsolutePath());
return null;
}
}
/*
* From Spring Boot's YamlPropertySourceLoader with List modifications
*/
private void buildFlattenedMap(Map result, Map source, String path) {
for (Map.Entry entry : source.entrySet()) {
String key = entry.getKey();
if (StringUtils.hasText(path)) {
if (key.startsWith("[")) {
key = path + key;
}
else {
key = path + "." + key;
}
}
Object value = entry.getValue();
if (value instanceof String) {
result.put(key, value);
}
else if (value instanceof Map) {
// Need a compound key
@SuppressWarnings("unchecked")
Map map = (Map) value;
buildFlattenedMap(result, map, key);
}
else if (value instanceof Collection) {
// Need a compound key
@SuppressWarnings("unchecked")
Collection