Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
Expand Down Expand Up @@ -68,6 +70,8 @@ public class DefaultKillbillConfigSource implements KillbillConfigSource, OSGICo
private static volatile int GMT_WARNING = NOT_SHOWN;
private static volatile int ENTROPY_WARNING = NOT_SHOWN;

private final Map<String, Map<String, String>> runtimeConfigBySource = new HashMap<>();

private final Properties properties;

public DefaultKillbillConfigSource() throws IOException, URISyntaxException {
Expand All @@ -88,6 +92,10 @@ public DefaultKillbillConfigSource(@Nullable final String file, final Map<String
} else {
this.properties = new Properties();
this.properties.load(UriAccessor.accessUri(Objects.requireNonNull(this.getClass().getResource(file)).toURI()));

final String category = extractFileNameFromPath(file);

runtimeConfigBySource.put(category, propertiesToMap(this.properties));
}

for (final Entry<String, String> entry : extraDefaultProperties.entrySet()) {
Expand All @@ -96,6 +104,8 @@ public DefaultKillbillConfigSource(@Nullable final String file, final Map<String
}
}

runtimeConfigBySource.put("ExtraDefaultProperties", extraDefaultProperties);

populateDefaultProperties();

if (Boolean.parseBoolean(getString(LOOKUP_ENVIRONMENT_VARIABLES))) {
Expand Down Expand Up @@ -134,15 +144,46 @@ public Properties getProperties() {
return result;
}

@Override
public Map<String, Map<String, String>> getPropertiesBySource() {
final Map<String, String> systemProps = new HashMap<>();

properties.stringPropertyNames().forEach(key -> systemProps.put(key, properties.getProperty(key)));

final Map<String, Map<String, String>> runtimeBySource = RuntimeConfigRegistry.getAllBySource();
runtimeBySource.forEach((source, props) -> {
final Map<String, String> filteredProps = new HashMap<>();
props.forEach((key, value) -> {
if (!systemProps.containsKey(key)) {
filteredProps.put(key, value);
}
});

if (!filteredProps.isEmpty()) {
runtimeConfigBySource.put(source, filteredProps);
}
});

runtimeConfigBySource.putAll(runtimeBySource);

return runtimeConfigBySource;
}

private Properties loadPropertiesFromFileOrSystemProperties() {
// Chicken-egg problem. It would be nice to have the property in e.g. KillbillServerConfig,
// but we need to build the ConfigSource first...
final String propertiesFileLocation = System.getProperty(PROPERTIES_FILE);

if (propertiesFileLocation != null) {
try {
// Ignore System Properties if we're loading from a file
final Properties properties = new Properties();
properties.load(UriAccessor.accessUri(propertiesFileLocation));

final String category = extractFileNameFromPath(propertiesFileLocation);

runtimeConfigBySource.put(category, propertiesToMap(properties));

return properties;
} catch (final IOException e) {
logger.warn("Unable to access properties file, defaulting to system properties", e);
Expand All @@ -151,7 +192,11 @@ private Properties loadPropertiesFromFileOrSystemProperties() {
}
}

return new Properties(System.getProperties());
final Properties systemProperties = System.getProperties();

runtimeConfigBySource.put("SystemProperties", propertiesToMap(systemProperties));

return systemProperties;
}

@VisibleForTesting
Expand Down Expand Up @@ -209,6 +254,13 @@ protected void populateDefaultProperties() {
}
}
}

final Map<String, String> defaultProps = propertiesToMap(defaultProperties);
final Map<String, String> defaultSystemProps = propertiesToMap(defaultSystemProperties);

defaultSystemProps.putAll(defaultProps);

runtimeConfigBySource.put("DefaultSystemProperties", defaultSystemProps);
}

@VisibleForTesting
Expand Down Expand Up @@ -244,15 +296,22 @@ protected Properties getDefaultSystemProperties() {
private void overrideWithEnvironmentVariables() {
// Find all Kill Bill properties in the environment variables
final Map<String, String> env = System.getenv();

final Map<String, String> kbEnvVariables = new HashMap<>();

for (final Entry<String, String> entry : env.entrySet()) {
if (!entry.getKey().startsWith(ENVIRONMENT_VARIABLE_PREFIX)) {
continue;
}

final String propertyName = fromEnvVariableName(entry.getKey());
final String value = entry.getValue();

kbEnvVariables.put(propertyName, value);
properties.setProperty(propertyName, value);
}

runtimeConfigBySource.put("EnvironmentVariables", kbEnvVariables);
}

@VisibleForTesting
Expand Down Expand Up @@ -313,4 +372,25 @@ private Optional<String> decryptableValue(final String value) {
}
return Optional.empty();
}

private String extractFileNameFromPath(String path) {
if (path == null || path.isEmpty()) {
return "unknown.properties";
}

if (path.startsWith("file://")) {
path = path.substring("file://".length());
}

return Paths.get(path).getFileName().toString();
}

private Map<String, String> propertiesToMap(final Properties props) {
final Map<String, String> propertiesMap = new HashMap<>();
for (final Map.Entry<Object, Object> entry : props.entrySet()) {
propertiesMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}

return propertiesMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.killbill.billing.osgi.api.OSGIConfigProperties;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.testng.Assert;

import static org.killbill.billing.platform.config.DefaultKillbillConfigSource.ENVIRONMENT_VARIABLE_PREFIX;

Expand Down Expand Up @@ -68,6 +68,25 @@ public void testGetProperties() throws URISyntaxException, IOException {
Assert.assertEquals(configSource.getProperties().getProperty("1"), "A");
}

@Test(groups = "fast")
public void testGetPropertiesBySource() throws URISyntaxException, IOException {
final Map<String, String> configuration = new HashMap<>();
configuration.put("org.killbill.dao.user", "root");
configuration.put("org.killbill.dao.password", "password");

final OSGIConfigProperties configSource = new DefaultKillbillConfigSource(null, configuration);

final Map<String, Map<String, String>> propsBySource = configSource.getPropertiesBySource();

Assert.assertNotNull(propsBySource);
Assert.assertFalse(propsBySource.isEmpty());

final Map<String, String> defaultProps = propsBySource.get("ExtraDefaultProperties");
Assert.assertNotNull(defaultProps);
Assert.assertEquals(defaultProps.get("org.killbill.dao.user"), "root");
Assert.assertEquals(defaultProps.get("org.killbill.dao.password"), "password");
}

@Test(groups = "fast")
public void testFromEnvVariableName() throws IOException, URISyntaxException {
final DefaultKillbillConfigSource configSource = new DefaultKillbillConfigSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.killbill.billing.osgi.api;

import java.util.Map;
import java.util.Properties;

/**
Expand All @@ -28,13 +29,26 @@
public interface OSGIConfigProperties {

/**
* Retrieves the value of the given property.
*
* @param propertyName the system property name
* @return the value of the property
*/
public String getString(final String propertyName);

/**
* @return all knows system properties (for the JVM)
* Returns all runtime resolved properties as a flat {@link Properties} object.
*
* @return all known configuration properties
*/
public Properties getProperties();

/**
* Returns all runtime resolved properties grouped by their respective source.
* Each key in the outer map represents the source name (e.g., "SystemProperties", "KillbillServerConfig", "CatalogConfig"),
* and the corresponding value is a map of property names to values loaded from that source.
*
* @return a map of configuration sources to their respective key-value property sets.
*/
public Map<String, Map<String, String>> getPropertiesBySource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.killbill.billing.osgi.libs.killbill;

import java.util.Map;
import java.util.Properties;

import org.killbill.billing.osgi.api.OSGIConfigProperties;
Expand Down Expand Up @@ -59,4 +60,14 @@ public Properties executeWithService(final OSGIConfigProperties service) {
}
});
}

@Override
public Map<String, Map<String, String>> getPropertiesBySource() {
return withServiceTracker(killbillTracker, new APICallback<>(OSGIConfigProperties.class.getName()) {
@Override
public Map<String, Map<String, String>> executeWithService(final OSGIConfigProperties service) {
return service.getPropertiesBySource();
}
});
}
}
Loading