Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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,11 @@

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
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 +71,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 +93,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 +105,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 +145,47 @@ 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);

// Returning a shallow copy to satisfy SpotBugs (EI_EXPOSE_REP).
return new HashMap<>(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 +194,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 +256,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 +298,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 +374,30 @@ 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());
}

final Path fileName = Paths.get(path).getFileName();
if (fileName == null) {
return "unknown.properties";
}

return fileName.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();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ private static void deleteDirectory(final File path, final boolean deleteParent)
if (f.isDirectory()) {
deleteDirectory(f, true);
}
Assert.assertTrue(f.delete(), "Unable to delete file " + f.getAbsolutePath());

final boolean deleted = f.delete();
Assert.assertTrue(deleted || !f.exists(), "Unable to delete file " + f.getAbsolutePath());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a safe check to gracefully handle scenarios where a temp file has been deleted by another part of the code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since CI is green and PR is approved, merging the PR

}
}
if (deleteParent) {
Expand Down Expand Up @@ -177,6 +179,7 @@ private PluginJavaConfig extractJavaBundleTestResource() {
return createPluginJavaConfig(resourceUrl.getPath());
}
}

return null;
}

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>org.kill-bill.billing</groupId>
<artifactId>killbill-oss-parent</artifactId>
<version>0.146.51</version>
<version>0.146.56</version>
</parent>
<artifactId>killbill-platform</artifactId>
<version>0.41.16-SNAPSHOT</version>
Expand Down