keycloak-aplcache

KEYCLOAK-4148 StringUtils property replacer optimization StringUtils.getSystemPropertyAsString

1/4/2017 12:21:19 PM

Details

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")
+        );
+    }
+
+}