From eabb4bc7e67399b5564cac0c31e4b20abe3dee20 Mon Sep 17 00:00:00 2001 From: Yusuf Koer Date: Mon, 31 Jul 2017 10:53:19 +0200 Subject: [PATCH] Added SystemEnvironmentAwareProperties to support system environment placeholders in the lightblue client configuration --- core/pom.xml | 15 +++- ...ropertiesLightblueClientConfiguration.java | 2 +- .../SystemEnvironmentAwareProperties.java | 68 +++++++++++++++++++ ...ropertiesLightblueClientSystemEnvTest.java | 38 +++++++++++ .../lightblue-client-systemenv.properties | 7 ++ 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/com/redhat/lightblue/client/SystemEnvironmentAwareProperties.java create mode 100644 core/src/test/java/com/redhat/lightblue/client/PropertiesLightblueClientSystemEnvTest.java create mode 100644 core/src/test/resources/lightblue-client-systemenv.properties diff --git a/core/pom.xml b/core/pom.xml index f4f9118..566d668 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -7,4 +7,17 @@ 5.12.0-SNAPSHOTlightblue-client-core lightblue-client: ${project.groupId}|${project.artifactId} - \ No newline at end of file + + + + org.powermock + powermock-module-junit4 + 1.7.0 + + + org.powermock + powermock-api-mockito + 1.7.0 + + + diff --git a/core/src/main/java/com/redhat/lightblue/client/PropertiesLightblueClientConfiguration.java b/core/src/main/java/com/redhat/lightblue/client/PropertiesLightblueClientConfiguration.java index 179b11c..72864d1 100644 --- a/core/src/main/java/com/redhat/lightblue/client/PropertiesLightblueClientConfiguration.java +++ b/core/src/main/java/com/redhat/lightblue/client/PropertiesLightblueClientConfiguration.java @@ -153,7 +153,7 @@ public static LightblueClientConfiguration fromPath(Path pathToProperties) { */ public static LightblueClientConfiguration fromInputStream(InputStream propertiesStream) { try { - Properties properties = new Properties(); + Properties properties = new SystemEnvironmentAwareProperties(); properties.load(loadInputStream(propertiesStream)); return fromObject(properties); diff --git a/core/src/main/java/com/redhat/lightblue/client/SystemEnvironmentAwareProperties.java b/core/src/main/java/com/redhat/lightblue/client/SystemEnvironmentAwareProperties.java new file mode 100644 index 0000000..7b85237 --- /dev/null +++ b/core/src/main/java/com/redhat/lightblue/client/SystemEnvironmentAwareProperties.java @@ -0,0 +1,68 @@ +package com.redhat.lightblue.client; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Enumeration; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Extended Properties class for working with Strings that have placeholders for system environment variables in them. + * A placeholder takes the form ${env.NAME}. + * + *

+ * Example: dataServiceURI=${env.LIGHTBLUE_DATA_SERVICE_URL} + *

+ */ +public class SystemEnvironmentAwareProperties extends Properties { + + private static final Pattern PROPERTY_PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{env\\.(.*?)\\}"); + + @Override + public synchronized void load(Reader reader) throws IOException { + super.load(reader); + replacePlaceholders(); + } + + @Override + public synchronized void load(InputStream inStream) throws IOException { + super.load(inStream); + replacePlaceholders(); + } + + /** + * Loop through all properties and replace the placeholders of format ${env.NAME} + * with the corresponding property value from the system environment. + */ + private synchronized void replacePlaceholders() { + for (Enumeration e = super.propertyNames() ; e.hasMoreElements() ;) { + String name = (String)e.nextElement() ; + super.setProperty(name, findAndReplacePlaceholders(super.getProperty(name))); + } + } + + + /** + * Replace placeholders in the provided value by the appropriate system environment variable, otherwise return the original value. + * Placeholder referencing non-existing system environment variables are replaced by an empty string. + * + * @param value The property value with or without property placeholders. + * @return the supplied value with placeholders replaced inline + */ + private String findAndReplacePlaceholders(String value) { + if (value==null) { + return value; + } + + Matcher matchPattern = PROPERTY_PLACEHOLDER_PATTERN.matcher(value); + StringBuffer sb = new StringBuffer(); + while(matchPattern.find()) { + String environmentVariable = System.getenv(matchPattern.group(1)); + matchPattern.appendReplacement(sb, environmentVariable!=null?Matcher.quoteReplacement(environmentVariable):""); + } + matchPattern.appendTail(sb); + return sb.toString(); + } +} diff --git a/core/src/test/java/com/redhat/lightblue/client/PropertiesLightblueClientSystemEnvTest.java b/core/src/test/java/com/redhat/lightblue/client/PropertiesLightblueClientSystemEnvTest.java new file mode 100644 index 0000000..230b03b --- /dev/null +++ b/core/src/test/java/com/redhat/lightblue/client/PropertiesLightblueClientSystemEnvTest.java @@ -0,0 +1,38 @@ +package com.redhat.lightblue.client; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Created by ykoer on 7/31/17. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({System.class, SystemEnvironmentAwareProperties.class}) +public class PropertiesLightblueClientSystemEnvTest { + + @Test + public void shouldReplaceSystemEnvironmentPropertyPlaceholders() { + + PowerMockito.mockStatic(System.class); + when(System.getenv("LB_DATA_SERVICE_URL")).thenReturn("http://this.is.a/test/data"); + when(System.getenv("LB_METADATA_SERVICE_URL")).thenReturn("http://this.is.a/test/metadata"); + + Path resourceWithSystemEnvPlaceholders = Paths.get("lightblue-client-systemenv.properties"); + LightblueClientConfiguration config = PropertiesLightblueClientConfiguration.fromPath(resourceWithSystemEnvPlaceholders); + + assertEquals("http://this.is.a/test/data", config.getDataServiceURI()); + assertEquals("http://this.is.a/test/metadata", config.getMetadataServiceURI()); + + // properties without placeholders should still work + assertEquals("certFile", config.getCertAlias()); + } +} diff --git a/core/src/test/resources/lightblue-client-systemenv.properties b/core/src/test/resources/lightblue-client-systemenv.properties new file mode 100644 index 0000000..4b9d5e3 --- /dev/null +++ b/core/src/test/resources/lightblue-client-systemenv.properties @@ -0,0 +1,7 @@ +metadataServiceURI=${env.LB_METADATA_SERVICE_URL} +dataServiceURI=${env.LB_DATA_SERVICE_URL} +useCertAuth=true +caFilePath=${env.LB_CACERT_FILE} +certFilePath=${env.LB_CERT_FILE} +certPassword=${env.LB_CERT_PASSWORD} +certAlias=certFile