ratpack.config.internal.source.EnvironmentConfigSource Maven / Gradle / Ivy
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ratpack.config.internal.source;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.google.common.base.CaseFormat;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import ratpack.config.ConfigDataBuilder;
import ratpack.config.ConfigSource;
import ratpack.config.EnvironmentParser;
import ratpack.file.FileSystemBinding;
import ratpack.func.Function;
import ratpack.func.Pair;
import ratpack.func.Predicate;
import ratpack.server.internal.ServerEnvironment;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class EnvironmentConfigSource implements ConfigSource {
public static final String DEFAULT_OBJECT_DELIMITER = "__";
public static final Function DEFAULT_MAP_FUNC = camelCase();
private final ServerEnvironment serverEnvironment;
private final EnvironmentParser parser;
public EnvironmentConfigSource(ServerEnvironment serverEnvironment) {
this(serverEnvironment, ConfigDataBuilder.DEFAULT_ENV_PREFIX);
}
public EnvironmentConfigSource(ServerEnvironment serverEnvironment, String prefix) {
this(serverEnvironment, prefix, DEFAULT_MAP_FUNC);
}
public EnvironmentConfigSource(ServerEnvironment serverEnvironment, String prefix, Function mapFunc) {
this(serverEnvironment, new DefaultEnvironmentParser(
filterAndRemoveKeyPrefix(Preconditions.checkNotNull(prefix)),
splitObjects(DEFAULT_OBJECT_DELIMITER),
mapFunc));
}
public EnvironmentConfigSource(ServerEnvironment serverEnvironment, EnvironmentParser parser) {
this.serverEnvironment = serverEnvironment;
this.parser = parser;
}
@Override
public ObjectNode loadConfigData(ObjectMapper objectMapper, FileSystemBinding fileSystemBinding) throws Exception {
ObjectNode rootNode = objectMapper.createObjectNode();
serverEnvironment.getenv().entrySet().stream().map(toPair()).flatMap(getFilterFunc()).map(getPairTokenizerFunc()).forEach(entry -> {
populate(rootNode, mapPathSegments(entry), 0, entry.getRight());
}
);
return rootNode;
}
private List mapPathSegments(Pair, String> entry) {
return entry.getLeft().stream().map(getMapFunc()).collect(Collectors.toList());
}
private void populate(ObjectNode node, List path, int pathIndex, String value) {
String segment = path.get(pathIndex);
if (pathIndex == path.size() - 1) {
node.set(segment, TextNode.valueOf(value));
} else {
// For environment variables, we don't support array indexing.
// Thus, if there are remaining segments, it must mean that the parent is an object.
ObjectNode childNode = (ObjectNode) node.get(segment);
if (childNode == null) {
childNode = node.putObject(segment);
}
populate(childNode, path, pathIndex + 1, value);
}
}
private java.util.function.Function, Stream>> getFilterFunc() {
return ((Function, Stream>>) parser::filter).toFunction();
}
private java.util.function.Function, Pair, String>> getPairTokenizerFunc() {
return ((Function, Pair, String>>) e -> e.mapLeft(parser::tokenize)).toFunction();
}
private java.util.function.Function getMapFunc() {
return ((Function) parser::map).toFunction();
}
public static Function camelCase() {
return Function.fromGuava(CaseFormat.UPPER_UNDERSCORE.converterTo(CaseFormat.LOWER_CAMEL));
}
public static Function, Stream>> filterAndRemoveKeyPrefix(String prefix) {
if (Strings.isNullOrEmpty(prefix)) {
return Stream::of;
}
return entry -> Stream.of(entry).filter(keyStartsWith(prefix).toPredicate()).map(removeKeyPrefix(prefix).toFunction());
}
public static Function> splitObjects(String objectDelimiter) {
return Splitter.on(objectDelimiter)::splitToList;
}
private static Predicate> keyStartsWith(String prefix) {
return entry -> entry.getLeft().startsWith(prefix);
}
private static Function, Pair> removeKeyPrefix(String prefix) {
return entry -> entry.mapLeft(key -> key.substring(prefix.length(), key.length()));
}
private static java.util.function.Function, Pair> toPair() {
return e -> Pair.of(e.getKey(), e.getValue());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy