diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
index f582ae0..23fb45f 100755
--- a/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
@@ -59,6 +59,9 @@ public class StringUtil {
return str == null || str.isEmpty();
}
+ private static final Pattern PROPERTY_REPLACEMENT = Pattern.compile("(.*?)" + "\\$\\{(.*?)" + "(?:::(.*?))?\\}");
+ // 1: PREFIX | START 2: NAME | 3: OPTIONAL DEFAULT VALUE
+
/**
* <p>
* Get the system property value if the string is of the format ${sysproperty}
@@ -84,37 +87,25 @@ public class StringUtil {
public static String getSystemPropertyAsString(String str) {
if (str == null)
throw logger.nullArgumentError("str");
- if (str.contains("${")) {
- Pattern pattern = Pattern.compile("\\$\\{([^}]+)}");
- Matcher matcher = pattern.matcher(str);
-
- StringBuffer buffer = new StringBuffer();
- String sysPropertyValue = null;
-
- while (matcher.find()) {
- String subString = matcher.group(1);
- String defaultValue = "";
-
- // Look for default value
- if (subString.contains("::")) {
- int index = subString.indexOf("::");
- defaultValue = subString.substring(index + 2);
- subString = subString.substring(0, index);
- }
- sysPropertyValue = SecurityActions.getSystemProperty(subString, defaultValue);
- if (sysPropertyValue.isEmpty()) {
- throw logger.systemPropertyMissingError(matcher.group(1));
- }else{
- // sanitize the value before we use append-and-replace
- sysPropertyValue = Matcher.quoteReplacement(sysPropertyValue);
- }
- matcher.appendReplacement(buffer, sysPropertyValue);
+
+ Matcher m = PROPERTY_REPLACEMENT.matcher(str);
+ StringBuilder sb = new StringBuilder();
+ int lastPosition = 0;
+ while (m.find()) {
+ String propertyName = m.group(2);
+ String defaultValue = m.group(3);
+
+ String sysPropertyValue = SecurityActions.getSystemProperty(propertyName, defaultValue);
+ if (sysPropertyValue.isEmpty()) {
+ throw logger.systemPropertyMissingError(propertyName);
}
- matcher.appendTail(buffer);
- str = buffer.toString();
+ sb.append(m.group(1)).append(sysPropertyValue);
+
+ lastPosition = m.end();
}
- return str;
+
+ return sb.append(str.substring(lastPosition)).toString();
}
/**
diff --git a/saml-core/src/test/java/org/keycloak/saml/common/util/StringUtilTest.java b/saml-core/src/test/java/org/keycloak/saml/common/util/StringUtilTest.java
new file mode 100644
index 0000000..dff97b7
--- /dev/null
+++ b/saml-core/src/test/java/org/keycloak/saml/common/util/StringUtilTest.java
@@ -0,0 +1,47 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.keycloak.saml.common.util;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public class StringUtilTest {
+
+ public StringUtilTest() {
+ }
+
+ @Test
+ public void testGetSystemPropertyAsString() {
+ System.setProperty("StringUtilTest.prop1", "value1");
+ System.setProperty("StringUtilTest.prop2", "value2");
+
+ assertThat(StringUtil.getSystemPropertyAsString("a"), is("a"));
+ assertThat(StringUtil.getSystemPropertyAsString("a ${StringUtilTest.prop1}"), is("a value1"));
+ assertThat(
+ StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1"),
+ is("a" + "value1" + "StringUtilTest.prop1")
+ );
+ assertThat(
+ StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}"),
+ is("a" + "value1" + "StringUtilTest.prop1" + "value2")
+ );
+ assertThat(
+ StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}" + "${StringUtilTest.prop3::abc}"),
+ is("a" + "value1" + "StringUtilTest.prop1" + "value2" + "abc")
+ );
+ assertThat(
+ StringUtil.getSystemPropertyAsString("a" + "${StringUtilTest.prop1}" + "StringUtilTest.prop1" + "${StringUtilTest.prop2}" + "${StringUtilTest.prop3::abc}" + "end"),
+ is("a" + "value1" + "StringUtilTest.prop1" + "value2" + "abc" + "end")
+ );
+ }
+
+}