Skip to content

Commit

Permalink
Merge pull request #15 from epam/main
Browse files Browse the repository at this point in the history
Improve substitutions
  • Loading branch information
artsiomkorzun committed Jul 3, 2024
2 parents 7f313b9 + 587d12d commit cd83203
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 43 deletions.
6 changes: 6 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## 3.0.6

- Support default values in substitutions: ${some.property:-default.value}
- Support system properties and environment variables in substitutions: ${sys:some.property} and ${env:some.property}
- Support nested substitutions for default values: ${env:some.property:-${sys:some.property:-default.value}}

## 3.0.5

- Support SLF4J 2.0.+.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ Highly efficient garbage-free logging framework for Java 8+.
Add the following dependencies to your project:

```gradle
implementation 'com.epam.deltix:gflog-api:3.0.5'
runtimeOnly 'com.epam.deltix:gflog-core:3.0.5'
implementation 'com.epam.deltix:gflog-api:3.0.6'
runtimeOnly 'com.epam.deltix:gflog-core:3.0.6'
```

Use the following sample to log a message:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@

public final class PropertyUtil {

private static final String SUBSTITUTION_START = "${";
private static final char SUBSTITUTION_END = '}';

private PropertyUtil() {
}

Expand Down Expand Up @@ -161,43 +158,6 @@ public static Duration toDuration(final String value) {
}

public static String substitute(final String value, final Properties properties) {
if (value.contains(SUBSTITUTION_START)) {
final StringBuilder builder = new StringBuilder();

final int length = value.length();
int i = 0;

while (true) {
final int j = value.indexOf(SUBSTITUTION_START, i);
if (j == -1) {
break;
}

final int k = j + SUBSTITUTION_START.length();
final int m = value.indexOf(SUBSTITUTION_END, k);
if (m == -1) {
break;
}

if (i < j) {
builder.append(value, i, j);
}

final String name = value.substring(k, m);
final String substitution = properties.getProperty(name, "");

builder.append(substitution);
i = m + 1;
}

if (i < length) {
builder.append(value, i, length);
}

return builder.toString();
}

return value;
return new StringSubstitution(properties, System.getProperties(), System.getenv()).substitute(value);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.epam.deltix.gflog.core.util;

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


public final class StringSubstitution {

private static final String SYSTEM_PROPERTY_PREFIX = "sys:";
private static final String ENVIRONMENT_VARIABLE_PREFIX = "env:";

private final Properties defaultProperties;
private final Properties systemProperties;
private final Map<String, String> environmentVariables;

public StringSubstitution(final Properties defaultProperties,
final Properties systemProperties,
final Map<String, String> environmentVariables) {
this.defaultProperties = defaultProperties;
this.systemProperties = systemProperties;
this.environmentVariables = environmentVariables;
}

public String substitute(final String text) {
final StringBuilder builder = new StringBuilder();

for (int index = 0; index < text.length(); ) {
final int position = text.indexOf("${", index);

if (position < 0) {
builder.append(text, index, text.length());
break;
}

builder.append(text, index, position);
index = substitute(text, position, builder);
}

return builder.toString();
}

private int substitute(final String source, int index, final StringBuilder target) {
final int end = source.length();
final int start = index;

index += 2;

while (index < end) {
char c = source.charAt(index);

if (c == '}') {
final String key = source.substring(start + 2, index);
final String value = lookup(key);

if (value == null) {
target.append("${").append(key).append(":#UNRESOLVED#").append("}");
} else {
target.append(value);
}

return index + 1;
}

if (c == ':' && index + 1 < end && source.charAt(index + 1) == '-') {
final String key = source.substring(start + 2, index);
final String value = lookup(key);

final int length = target.length();
final int mid = index + 2;

index = mid;

while (index < end) {
c = source.charAt(index);

if (c == '}') {
if (value != null) {
target.setLength(length);
target.append(value);
}

return index + 1;
}

if (c == '$' && index + 1 < end && source.charAt(index + 1) == '{') {
index = substitute(source, index, target);
continue;
}

target.append(c);
index++;
}

target.insert(length, source, start, mid);
return end;
}

index++;
}

target.append(source, start, end);
return index;
}

private String lookup(final String key) {
if (key.startsWith(SYSTEM_PROPERTY_PREFIX)) {
final String propertyKey = key.substring(SYSTEM_PROPERTY_PREFIX.length());
return systemProperties.getProperty(propertyKey);
}

if (key.startsWith(ENVIRONMENT_VARIABLE_PREFIX)) {
final String environmentKey = key.substring(ENVIRONMENT_VARIABLE_PREFIX.length());
return environmentVariables.get(environmentKey);
}

return defaultProperties.getProperty(key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.epam.deltix.gflog.core.util;

import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

public class StringSubstitutionTest {

@Test
public void testDefaults() {
final Properties defaults = new Properties();
defaults.put("a", "A");
defaults.put("b", "B");
defaults.put("c", "C");

final Properties systems = new Properties();
final Map<String, String> environments = new HashMap<>();
final StringSubstitution substitution = new StringSubstitution(defaults, systems, environments);
final Map<String, String> mapping = new LinkedHashMap<>();

mapping.put("12345", "12345");
mapping.put("${a} ${b} ${c}", "A B C");
mapping.put("${a:-10} ${b:-${c:-100500}}", "A B");
mapping.put("${missing:-5} + ${missing:-10}", "5 + 10");
mapping.put("${missing:-${a}}", "A");
mapping.put("${missing:-${missing2:-${b}}}", "B");
mapping.put("${missing:-${missing2:-${missing3:-${c}}}}", "C");
mapping.put("${a:-5", "${a:-5");
mapping.put(" ${a:-${b} ", " ${a:-B ");
mapping.put(" ${a:-${b:-${c ", " ${a:-${b:-${c ");
mapping.put(" ${a:-${b:-${c} ", " ${a:-${b:-C ");
mapping.put(" ${a:-${b:-${c}} ", " ${a:-B ");
mapping.put("${missing}", "${missing:#UNRESOLVED#}");
mapping.put("${missing:-1 ${a} 2 ${missing2} 3}", "1 A 2 ${missing2:#UNRESOLVED#} 3");
mapping.put("${missing:-}", "");

for (final Map.Entry<String, String> entry : mapping.entrySet()) {
final String text = entry.getKey();
final String expected = entry.getValue();
final String actual = substitution.substitute(text);

Assert.assertEquals(expected, actual);
}
}

@Test
public void testEnvironmentAndSystemSubstitution() {
final Properties defaults = new Properties();
defaults.put("a", "1");
defaults.put("b", "2");
defaults.put("c", "3");

final Properties systems = new Properties();
systems.put("a", "4");
systems.put("b", "5");
systems.put("c", "6");

final Map<String, String> environments = new HashMap<>();
environments.put("a", "7");
environments.put("b", "8");
environments.put("c", "9");

final StringSubstitution substitution = new StringSubstitution(defaults, systems, environments);
final Map<String, String> mapping = new LinkedHashMap<>();

mapping.put("${a} ${sys:a} ${env:a}", "1 4 7");
mapping.put("${missing:-${b}} ${missing:-${sys:b}} ${missing:-${env:b}}", "2 5 8");
mapping.put("${sys:missing:-${b}} ${sys:missing:-${sys:b}} ${sys:missing:-${env:b}}", "2 5 8");
mapping.put("${env:missing:-${b}} ${env:missing:-${sys:b}} ${env:missing:-${env:b}}", "2 5 8");

for (final Map.Entry<String, String> entry : mapping.entrySet()) {
final String text = entry.getKey();
final String expected = entry.getValue();
final String actual = substitution.substitute(text);

Assert.assertEquals(expected, actual);
}
}
}

0 comments on commit cd83203

Please sign in to comment.