io.dropwizard.configuration.BaseConfigurationFactory Maven / Gradle / Ivy
package io.dropwizard.configuration;
import static java.util.Objects.requireNonNull;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.TreeTraversingParser;
/**
* A generic factory class for loading configuration files, binding them to configuration objects, and
* validating their constraints. Allows for overriding configuration parameters from system properties.
*
* @param the type of the configuration objects to produce
*/
public abstract class BaseConfigurationFactory implements ConfigurationFactory {
private static final Pattern ESCAPED_COMMA_PATTERN = Pattern.compile("\\\\,");
private static final Pattern ESCAPED_DOT_PATTERN = Pattern.compile("\\\\\\.");
private final Class klass;
private final String propertyPrefix;
protected final ObjectMapper mapper;
private final Validator validator;
private final String formatName;
private final JsonFactory parserFactory;
/**
* Creates a new configuration factory for the given class.
*
* @param parserFactory the factory that creates the parser used
* @param formatName the name of the format parsed by this factory (used in exceptions)
* @param klass the configuration class
* @param validator the validator to use
* @param propertyPrefix the system property name prefix used by overrides
*/
public BaseConfigurationFactory(JsonFactory parserFactory,
String formatName,
Class klass,
Validator validator,
ObjectMapper objectMapper,
String propertyPrefix) {
this.klass = klass;
this.formatName = formatName;
this.propertyPrefix = (propertyPrefix == null || propertyPrefix.endsWith("."))
? propertyPrefix : (propertyPrefix + '.');
// Sub-classes may choose to omit data-binding; if so, null ObjectMapper passed:
if (objectMapper == null) { // sub-class has no need for mapper
this.mapper = null;
this.parserFactory = null;
} else {
this.mapper = objectMapper;
this.parserFactory = parserFactory;
}
this.validator = validator;
}
@Override
public T build(ConfigurationSourceProvider provider, String path) throws IOException, ConfigurationException {
try (InputStream input = provider.open(requireNonNull(path))) {
final JsonNode node = mapper.readTree(createParser(input));
if (node == null) {
throw ConfigurationParsingException
.builder("Configuration at " + path + " must not be empty")
.build(path);
}
return build(node, path);
} catch (JsonParseException e) {
throw ConfigurationParsingException
.builder("Malformed " + formatName)
.setCause(e)
.setLocation(e.getLocation())
.setDetail(e.getMessage())
.build(path);
}
}
protected JsonParser createParser(InputStream input) throws IOException {
return parserFactory.createParser(input);
}
@Override
public T build() throws IOException, ConfigurationException {
try {
final JsonNode node = mapper.valueToTree(klass.newInstance());
return build(node, "default configuration");
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | SecurityException e) {
throw new IllegalArgumentException("Unable create an instance " +
"of the configuration class: '" + klass.getCanonicalName() + "'", e);
}
}
protected T build(JsonNode node, String path) throws IOException, ConfigurationException {
for (Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy