Skip to content

Commit dfc4070

Browse files
author
mccabd
committed
Changes after review
1 parent 4bd3679 commit dfc4070

File tree

5 files changed

+194
-81
lines changed

5 files changed

+194
-81
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ already.defined.key+=value2,value3
108108
### Profiles
109109
Profiles allow you to map properties to different profiles - for example, dev, test, prod or mock.
110110
We can activate these profiles in different environments to set(override) the properties we need.
111-
The profile property can be defined as either an OS environment variable or a JVM system property.
111+
The profile property is generally to be defined as either an OS environment variable or a JVM system property.
112+
However, it can be set in a properties file which is useful in unit testing or testing on a local environment.
112113

113114
When a property with the key `bordertech.config.profile` is set, it is used as the suffix for each property lookup:
114115

@@ -241,8 +242,8 @@ If the `bordertech.config.spi.append.default` is true the Default Configuration
241242

242243
### Best Practice
243244

244-
THe Default Configuration allows you to set the profile `bordertech.config.profile` but you would normally set the profile through a
245-
JVM System Property or an OS environment variable.
245+
When using java-config in a container and setting specific properties for that container instance,
246+
this can be achieved by property file(s) placed in the container that can be referred to and included within the application at runtime.
246247

247248
## Contributing
248249

src/main/java/com/github/bordertech/config/DefaultConfiguration.java

Lines changed: 98 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.Iterator;
3838
import java.util.List;
3939
import java.util.Map;
40+
import java.util.Objects;
4041
import java.util.Properties;
4142
import java.util.Set;
4243
import java.util.TreeSet;
@@ -100,7 +101,9 @@ public class DefaultConfiguration implements Configuration {
100101
public static final String DUMP_FILE = "bordertech.config.parameters.dump.file";
101102
/**
102103
* If this parameter is set, it will be used as the environment suffix for each property lookup.
104+
* @deprecated Use {@link #PROFILE_PROPERTY} to define the profile property
103105
*/
106+
@Deprecated
104107
public static final String ENVIRONMENT_PROPERTY = "bordertech.config.environment";
105108
/**
106109
* If this parameter is set, it will be used as the environment suffix for each property lookup.
@@ -166,14 +169,9 @@ public class DefaultConfiguration implements Configuration {
166169
private final String[] resourceLoadOrder;
167170

168171
/**
169-
* Holds the current environment suffix (if set).
170-
*
171-
* @deprecated - Replaced by current Profile
172+
* Hold the current profile (if set).
172173
*/
173-
@Deprecated
174-
private String currentEnvironment = null;
175-
176-
private String environmentProfile = null;
174+
private String currentProfile = null;
177175

178176
/**
179177
* Our backing store is a Map object.
@@ -196,6 +194,11 @@ public class DefaultConfiguration implements Configuration {
196194
*/
197195
private Map<String, Properties> subcontextCache;
198196

197+
/**
198+
* Properties added at runtime.
199+
*/
200+
private IncludeProperties runtimeProperties;
201+
199202
/**
200203
* Creates a Default Configuration.
201204
*/
@@ -264,7 +267,8 @@ private void initialiseInstanceVariables() {
264267

265268
// subContextCache is updated on the fly so ensure no concurrent modification.
266269
subcontextCache = Collections.synchronizedMap(new HashMap<>());
267-
currentEnvironment = null;
270+
runtimeProperties = new IncludeProperties("Runtime: property added at runtime");
271+
currentProfile = null;
268272
}
269273

270274
/**
@@ -297,10 +301,7 @@ private void load() {
297301
loadEnvironmentProperties();
298302
}
299303

300-
setEnvironmentProfile();
301-
302-
// Check if environment set
303-
checkEnvironmentProperty();
304+
checkProfileProperty();
304305

305306
// Now perform variable substitution.
306307
for (String key : backing.keySet()) {
@@ -699,7 +700,7 @@ private ClassLoader getParamsClassLoader() {
699700
*/
700701
private void loadSystemProperties() {
701702
boolean overWriteOnly = getBoolean(USE_SYSTEM_OVERWRITEONLY, false);
702-
List<Object> allowedPrefixes = getList(USE_SYSTEM_PREFIXES);
703+
List<String> allowedPrefixes = Arrays.asList(getStringArray(USE_SYSTEM_PREFIXES));
703704
System
704705
.getProperties()
705706
.forEach((key, value) -> mergeExternalProperty("System Properties",
@@ -713,27 +714,12 @@ private void loadSystemProperties() {
713714
* Load the OS Environment Properties into Config.
714715
*/
715716
private void loadEnvironmentProperties() {
716-
List<Object> allowedPrefixes = getList(USE_OSENV_PREFIXES);
717+
List<String> allowedPrefixes = Arrays.asList(getStringArray(USE_OSENV_PREFIXES));
717718
System
718719
.getenv()
719720
.forEach((key, value) -> mergeExternalProperty("Environment Properties", key, value, false, allowedPrefixes));
720721
}
721722

722-
/**
723-
* Set the Environment Profile if it has been set as a system or environment property.
724-
* If both are defined, system property overrides and environment property
725-
*/
726-
private void setEnvironmentProfile() {
727-
728-
environmentProfile = ObjectUtils.firstNonNull(backing.get(PROFILE_PROPERTY), System.getProperty(PROFILE_PROPERTY), System.getenv().get(PROFILE_PROPERTY));
729-
730-
if (StringUtils.isBlank(environmentProfile)) {
731-
recordMessage("Environment Profile Property <" + PROFILE_PROPERTY + "> has not been defined.");
732-
} else {
733-
recordMessage("Environment Profile Property <" + PROFILE_PROPERTY + "> has been defined as " + environmentProfile);
734-
}
735-
}
736-
737723
/**
738724
* Merge the external property.
739725
*
@@ -748,7 +734,7 @@ private void mergeExternalProperty(
748734
final String key,
749735
final String value,
750736
final boolean overWriteOnly,
751-
final List<Object> allowedPrefixes) {
737+
final List<String> allowedPrefixes) {
752738

753739
// Check for "include" keys (should not come from System or Environment Properties)
754740
if (INCLUDE.equals(key) || INCLUDE_AFTER.equals(key)) {
@@ -776,16 +762,16 @@ private void mergeExternalProperty(
776762
* @param key the key to check
777763
* @return true if the key is an allowed prefix
778764
*/
779-
private boolean isAllowedKeyPrefix(final List<Object> allowedPrefixes, final String key) {
765+
private boolean isAllowedKeyPrefix(final List<String> allowedPrefixes, final String key) {
780766

781767
// If no prefixes defined, then ALL keys are allowed
782768
if (allowedPrefixes == null || allowedPrefixes.isEmpty()) {
783769
return true;
784770
}
785771

786772
// Check allowed prefixes
787-
for (Object prefix : allowedPrefixes) {
788-
if (key.startsWith(prefix.toString())) {
773+
for (String prefix : allowedPrefixes) {
774+
if (key.startsWith(prefix)) {
789775
return true;
790776
}
791777
}
@@ -963,7 +949,10 @@ public void clearProperty(final String key) {
963949

964950
@Override
965951
public boolean containsKey(final String key) {
966-
return backing.containsKey(getKey(key));
952+
if (useProfileKey(key) && backing.containsKey(getProfileKey(key))) {
953+
return true;
954+
}
955+
return backing.containsKey(key);
967956
}
968957

969958
@Override
@@ -1008,7 +997,10 @@ public BigInteger getBigInteger(final String key, final BigInteger defaultValue)
1008997

1009998
@Override
1010999
public boolean getBoolean(final String key) {
1011-
return booleanBacking.contains(getKey(key));
1000+
if (useProfileKey(key) && booleanBacking.contains(getProfileKey(key))) {
1001+
return true;
1002+
}
1003+
return booleanBacking.contains(key);
10121004
}
10131005

10141006
@Override
@@ -1318,18 +1310,20 @@ protected String get(final String key, final String defolt) {
13181310
}
13191311

13201312
/**
1313+
*
13211314
* @param key the property key
13221315
* @return the property value or null
13231316
*/
13241317
protected String get(final String key) {
1325-
String result = backing.get(getKey(key));
1326-
1327-
if (StringUtils.isNotBlank(result)) {
1328-
//Final substitution check
1329-
result = StringSubstitutor.replace(result, backing);
1318+
// Check environment property
1319+
if (useProfileKey(key)) {
1320+
String result = backing.get(getProfileKey(key));
1321+
if (result != null) {
1322+
return StringSubstitutor.replace(result, backing);
1323+
}
13301324
}
1331-
1332-
return result;
1325+
//Final substitution check
1326+
return StringSubstitutor.replace(backing.get(key), backing);
13331327
}
13341328

13351329
/**
@@ -1353,7 +1347,7 @@ protected void addOrModifyProperty(final String name, final String value) {
13531347

13541348
recordMessage("modifyProperties() - Adding property '" + name + "' with the value '" + value + "'.");
13551349

1356-
new IncludeProperties("Runtime: added at runtime").put(name, value);
1350+
runtimeProperties.put(name, value);
13571351

13581352
handlePropertiesChanged();
13591353
}
@@ -1364,20 +1358,60 @@ protected void addOrModifyProperty(final String name, final String value) {
13641358
protected void handlePropertiesChanged() {
13651359
// clear the subContext cache, it's now invalid
13661360
subcontextCache.clear();
1367-
// Check if environment changed
1368-
checkEnvironmentProperty();
1369-
setEnvironmentProfile();
1361+
// Check if profile changed
1362+
checkProfileProperty();
1363+
}
1364+
1365+
/**
1366+
* Set the current Profile if it has been set as property. An application defined property overrides,
1367+
* a JVM System property which overrides a OS environment variable
1368+
*/
1369+
protected void checkProfileProperty() {
1370+
1371+
currentProfile = ObjectUtils.firstNonNull(backing.get(PROFILE_PROPERTY), System.getProperty(PROFILE_PROPERTY), System.getenv().get(PROFILE_PROPERTY));
1372+
1373+
//Temporarily exists until deprecated Environment Property is removed
1374+
if (StringUtils.isBlank(currentProfile)) {
1375+
//Might not be using profile property, try the environment property for backwards compatibility
1376+
currentProfile = ObjectUtils.firstNonNull(backing.get(ENVIRONMENT_PROPERTY), System.getProperty(ENVIRONMENT_PROPERTY), System.getenv().get(ENVIRONMENT_PROPERTY));
1377+
}
1378+
1379+
if (StringUtils.isBlank(currentProfile)) {
1380+
recordMessage("Profile Property <" + PROFILE_PROPERTY + "> has not been defined.");
1381+
} else {
1382+
recordMessage("Profile Property <" + PROFILE_PROPERTY + "> has been defined as " + currentProfile);
1383+
}
1384+
}
1385+
1386+
/**
1387+
* @param key the property key
1388+
* @return true if check suffix
1389+
*/
1390+
protected boolean useProfileKey(final String key) {
1391+
// Has environment and is not the environment property
1392+
return currentProfile != null && !ENVIRONMENT_PROPERTY.equals(key) && !PROFILE_PROPERTY.equals(key);
1393+
}
1394+
1395+
/**
1396+
* @param key the property key
1397+
* @return the property key with the environment suffix
1398+
*/
1399+
protected String getProfileKey(final String key) {
1400+
if (useProfileKey(key)) {
1401+
return key + "." + currentProfile;
1402+
} else {
1403+
return key;
1404+
}
13701405
}
13711406

13721407
/**
13731408
* Check if the environment property has been set.
13741409
*
1375-
* @deprecated - Replaced by Environment Profile
1410+
* @deprecated - Replaced by see checkProfileProperty
13761411
*/
13771412
@Deprecated
13781413
protected void checkEnvironmentProperty() {
1379-
String env = backing.get(ENVIRONMENT_PROPERTY);
1380-
currentEnvironment = (env == null || env.isEmpty()) ? null : env;
1414+
checkProfileProperty();
13811415
}
13821416

13831417
/**
@@ -1387,8 +1421,7 @@ protected void checkEnvironmentProperty() {
13871421
*/
13881422
@Deprecated
13891423
protected boolean useEnvironmentKey(final String key) {
1390-
// Has environment and is not the environment property
1391-
return currentEnvironment != null && !ENVIRONMENT_PROPERTY.equals(key);
1424+
return useProfileKey(key);
13921425
}
13931426

13941427
/**
@@ -1398,25 +1431,7 @@ protected boolean useEnvironmentKey(final String key) {
13981431
*/
13991432
@Deprecated
14001433
protected String getEnvironmentKey(final String key) {
1401-
if (useEnvironmentKey(key)) {
1402-
return key + "." + currentEnvironment;
1403-
} else {
1404-
return key;
1405-
}
1406-
}
1407-
1408-
private String getKey(final String key) {
1409-
1410-
final String profileKey = key + "." + environmentProfile;
1411-
final String currentEnvKey = key + "." + currentEnvironment;
1412-
1413-
if (StringUtils.isNotBlank(environmentProfile) && backing.containsKey(profileKey)) {
1414-
return profileKey;
1415-
} else if (StringUtils.isNotBlank(currentEnvironment) && backing.containsKey(currentEnvKey)) {
1416-
return currentEnvKey;
1417-
} else {
1418-
return key;
1419-
}
1434+
return getProfileKey(key);
14201435
}
14211436

14221437
/**
@@ -1425,7 +1440,7 @@ private String getKey(final String key) {
14251440
* <p>This is used to ensure on the call of put(key, value) is immediately loaded into the
14261441
* {@link DefaultConfiguration} to respect the order hierarchy for the configuration.</p>
14271442
*/
1428-
class IncludeProperties extends Properties {
1443+
private class IncludeProperties extends Properties {
14291444

14301445
/**
14311446
* The properties file location (if applicable).
@@ -1486,5 +1501,17 @@ public synchronized Object put(final Object aKey, final Object aValue) {
14861501
return super.put(key, value);
14871502
}
14881503
}
1504+
1505+
@Override
1506+
public synchronized int hashCode() {
1507+
int hash = 5;
1508+
hash = 97 * hash + Objects.hashCode(this.location);
1509+
return hash;
1510+
}
1511+
1512+
@Override
1513+
public synchronized boolean equals(final Object obj) {
1514+
return obj instanceof IncludeProperties && Objects.equals(this.location, ((IncludeProperties) obj).location);
1515+
}
14891516
}
14901517
}

src/test/java/com/github/bordertech/config/DefaultConfigurationEnvSuffixTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.junit.Test;
55

66
import static com.github.bordertech.config.DefaultConfiguration.ENVIRONMENT_PROPERTY;
7+
import static com.github.bordertech.config.DefaultConfiguration.PROFILE_PROPERTY;
78

89
/**
910
* DefaultConfiguration_EnvironmentSuffix_Test - JUnit tests for {@link DefaultConfiguration}.
@@ -41,6 +42,40 @@ public void testEnvSuffixProperties() {
4142

4243
//Test for the suffix 2 is set
4344
assertPropertyEquals(config, SUFFIX2_PROPERTY_VALUE);
45+
46+
System.clearProperty(ENVIRONMENT_PROPERTY);
47+
config.refresh();
48+
}
49+
50+
@Test
51+
public void testProfileSuffixProperties() {
52+
DefaultConfiguration config = new DefaultConfiguration(
53+
"com/github/bordertech/config/DefaultConfigurationEnvSuffixTest.properties");
54+
55+
System.clearProperty(PROFILE_PROPERTY);
56+
config.refresh();
57+
58+
Assert.assertNull(System.getProperty(PROFILE_PROPERTY));
59+
60+
//Test the default value
61+
assertPropertyEquals(config, DEFAULT_PROPERTY_VALUE);
62+
63+
//Set the environment suffix 1 and reload
64+
System.setProperty(PROFILE_PROPERTY, "suffix1");
65+
config.refresh();
66+
67+
//Test for the suffix 1 is set
68+
assertPropertyEquals(config, SUFFIX1_PROPERTY_VALUE);
69+
70+
//Set the environment suffix 2 and reload
71+
System.setProperty(PROFILE_PROPERTY, "suffix2");
72+
config.refresh();
73+
74+
//Test for the suffix 2 is set
75+
assertPropertyEquals(config, SUFFIX2_PROPERTY_VALUE);
76+
77+
System.clearProperty(PROFILE_PROPERTY);
78+
config.refresh();
4479
}
4580

4681
/**

0 commit comments

Comments
 (0)