Skip to content

Commit

Permalink
[Java] Provide the ability to configure what action is taken when loa…
Browse files Browse the repository at this point in the history
…ding properties files. Issue #226.
  • Loading branch information
mjpt777 committed Nov 9, 2020
1 parent fd6c697 commit e536cff
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 37 deletions.
32 changes: 32 additions & 0 deletions agrona/src/main/java/org/agrona/PropertyAction.java
@@ -0,0 +1,32 @@
/*
* Copyright 2014-2020 Real Logic Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.agrona;

/**
* Action to be taken for each property loaded into system properties.
*/
public enum PropertyAction
{
/**
* Replace existing property value if one exists.
*/
REPLACE,

/**
* Preserve existing property value if one exists.
*/
PRESERVE
}
71 changes: 58 additions & 13 deletions agrona/src/main/java/org/agrona/SystemUtil.java
Expand Up @@ -15,9 +15,7 @@
*/
package org.agrona;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
Expand Down Expand Up @@ -193,7 +191,7 @@ public static String threadDump()
}

/**
* Load system properties from a given filename or url.
* Load system properties from a given filename or url with default to {@link PropertyAction#REPLACE}.
* <p>
* File is first searched for in resources using the system {@link ClassLoader},
* then file system, then URL. All are loaded if multiples found.
Expand All @@ -202,15 +200,26 @@ public static String threadDump()
*/
public static void loadPropertiesFile(final String filenameOrUrl)
{
final Properties properties = new Properties(System.getProperties());
System.getProperties().forEach(properties::put);
loadPropertiesFile(PropertyAction.REPLACE, filenameOrUrl);
}

/**
* Load system properties from a given filename or url.
* <p>
* File is first searched for in resources using the system {@link ClassLoader},
* then file system, then URL. All are loaded if multiples found.
*
* @param propertyAction to take with each loaded property.
* @param filenameOrUrl that holds properties.
*/
public static void loadPropertiesFile(final PropertyAction propertyAction, final String filenameOrUrl)
{
final URL resource = ClassLoader.getSystemClassLoader().getResource(filenameOrUrl);
if (null != resource)
{
try (InputStream in = resource.openStream())
{
properties.load(in);
loadProperties(propertyAction, in);
}
catch (final Exception ignore)
{
Expand All @@ -220,9 +229,9 @@ public static void loadPropertiesFile(final String filenameOrUrl)
final File file = new File(filenameOrUrl);
if (file.exists())
{
try (FileInputStream in = new FileInputStream(file))
try (InputStream in = new FileInputStream(file))
{
properties.load(in);
loadProperties(propertyAction, in);
}
catch (final Exception ignore)
{
Expand All @@ -231,26 +240,36 @@ public static void loadPropertiesFile(final String filenameOrUrl)

try (InputStream in = new URL(filenameOrUrl).openStream())
{
properties.load(in);
loadProperties(propertyAction, in);
}
catch (final Exception ignore)
{
}
}

System.setProperties(properties);
/**
* Load system properties from a given set of filenames or URLs with default to {@link PropertyAction#REPLACE}.
*
* @param filenamesOrUrls that holds properties.
* @see #loadPropertiesFile(String)
*/
public static void loadPropertiesFiles(final String... filenamesOrUrls)
{
loadPropertiesFiles(PropertyAction.REPLACE, filenamesOrUrls);
}

/**
* Load system properties from a given set of filenames or URLs.
*
* @param propertyAction to take with each loaded property.
* @param filenamesOrUrls that holds properties.
* @see #loadPropertiesFile(String)
*/
public static void loadPropertiesFiles(final String... filenamesOrUrls)
public static void loadPropertiesFiles(final PropertyAction propertyAction, final String... filenamesOrUrls)
{
for (final String filenameOrUrl : filenamesOrUrls)
{
loadPropertiesFile(filenameOrUrl);
loadPropertiesFile(propertyAction, filenameOrUrl);
}
}

Expand Down Expand Up @@ -440,4 +459,30 @@ public static long parseDuration(final String propertyName, final String propert
propertyName + ": " + propertyValue + " should end with: s, ms, us, or ns.");
}
}

private static void loadProperties(final PropertyAction propertyAction, final InputStream in) throws IOException
{
final Properties systemProperties = System.getProperties();
final Properties properties = new Properties();

properties.load(in);
properties.forEach(
(k, v) ->
{
switch (propertyAction)
{
case PRESERVE:
if (!systemProperties.containsKey(k))
{
systemProperties.setProperty((String)k, (String)v);
}
break;

default:
case REPLACE:
systemProperties.setProperty((String)k, (String)v);
break;
}
});
}
}
59 changes: 35 additions & 24 deletions agrona/src/test/java/org/agrona/SystemUtilTest.java
Expand Up @@ -21,36 +21,35 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.core.Is.is;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;

public class SystemUtilTest
{
@Test
public void shouldParseSizesWithSuffix()
{
assertThat(parseSize("", "1"), is(1L));
assertThat(parseSize("", "1k"), is(1024L));
assertThat(parseSize("", "1K"), is(1024L));
assertThat(parseSize("", "1m"), is(1024L * 1024));
assertThat(parseSize("", "1M"), is(1024L * 1024));
assertThat(parseSize("", "1g"), is(1024L * 1024 * 1024));
assertThat(parseSize("", "1G"), is(1024L * 1024 * 1024));
assertEquals(1L, parseSize("", "1"));
assertEquals(1024L, parseSize("", "1k"));
assertEquals(1024L, parseSize("", "1K"));
assertEquals(1024L * 1024L, parseSize("", "1m"));
assertEquals(1024L * 1024L, parseSize("", "1M"));
assertEquals(1024L * 1024L * 1024L, parseSize("", "1g"));
assertEquals(1024L * 1024L * 1024L, parseSize("", "1G"));
}

@Test
public void shouldParseTimesWithSuffix()
{
assertThat(parseDuration("", "1"), is(1L));
assertThat(parseDuration("", "1ns"), is(1L));
assertThat(parseDuration("", "1NS"), is(1L));
assertThat(parseDuration("", "1us"), is(1000L));
assertThat(parseDuration("", "1US"), is(1000L));
assertThat(parseDuration("", "1ms"), is(1000L * 1000));
assertThat(parseDuration("", "1MS"), is(1000L * 1000));
assertThat(parseDuration("", "1s"), is(1000L * 1000 * 1000));
assertThat(parseDuration("", "1S"), is(1000L * 1000 * 1000));
assertThat(parseDuration("", "12s"), is(12L * 1000 * 1000 * 1000));
assertEquals(1L, parseDuration("", "1"));
assertEquals(1L, parseDuration("", "1ns"));
assertEquals(1L, parseDuration("", "1NS"));
assertEquals(1000L, parseDuration("", "1us"));
assertEquals(1000L, parseDuration("", "1US"));
assertEquals(1000L * 1000, parseDuration("", "1ms"));
assertEquals(1000L * 1000, parseDuration("", "1MS"));
assertEquals(1000L * 1000 * 1000, parseDuration("", "1s"));
assertEquals(1000L * 1000 * 1000, parseDuration("", "1S"));
assertEquals(12L * 1000 * 1000 * 1000, parseDuration("", "12S"));
}

@Test
Expand Down Expand Up @@ -78,7 +77,7 @@ public void shouldDoNothingToSystemPropsWhenLoadingFileWhichDoesNotExist()

loadPropertiesFile("$unknown-file$");

assertThat(originalSystemPropSize, is(System.getProperties().size()));
assertEquals(originalSystemPropSize, System.getProperties().size());
}

@Test
Expand All @@ -89,19 +88,31 @@ public void shouldMergeMultiplePropFilesTogether()

loadPropertiesFiles("TestFileA.properties", "TestFileB.properties");

assertThat(System.getProperty("TestFileA.foo"), is("AAA"));
assertThat(System.getProperty("TestFileB.foo"), is("BBB"));
assertEquals("AAA", System.getProperty("TestFileA.foo"));
assertEquals("BBB", System.getProperty("TestFileB.foo"));
}

@Test
public void shouldOverrideSystemPropertiesWithConfigFromPropFile()
{
System.setProperty("TestFileA.foo", "ToBeOverridden");
assertThat(System.getProperty("TestFileA.foo"), is("ToBeOverridden"));
assertEquals("ToBeOverridden", System.getProperty("TestFileA.foo"));

loadPropertiesFile("TestFileA.properties");

assertThat(System.getProperty("TestFileA.foo"), is("AAA"));
assertEquals("AAA", System.getProperty("TestFileA.foo"));

System.clearProperty("TestFileA.foo");
}

@Test
public void shouldNotOverrideSystemPropertiesWithConfigFromPropFile()
{
System.setProperty("TestFileA.foo", "ToBeNotOverridden");
assertEquals("ToBeNotOverridden", System.getProperty("TestFileA.foo"));

loadPropertiesFile(PropertyAction.PRESERVE, "TestFileA.properties");
assertEquals("ToBeNotOverridden", System.getProperty("TestFileA.foo"));

System.clearProperty("TestFileA.foo");
}
Expand Down

0 comments on commit e536cff

Please sign in to comment.