This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new cdfea5d  Support for default values in property value expressions
cdfea5d is described below

commit cdfea5d3df5c3c4d65d9922e78f05fa967ab0a97
Author: bohmber <bom...@apache.org>
AuthorDate: Mon Mar 2 20:25:30 2020 +0100

    Support for default values in property value expressions
---
 .../org/apache/tomcat/util/IntrospectionUtils.java | 60 ++++++++++++++++------
 .../apache/tomcat/util/TestIntrospectionUtils.java | 37 ++++++++++++-
 webapps/docs/changelog.xml                         |  5 ++
 webapps/docs/config/systemprops.xml                |  5 +-
 4 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/java/org/apache/tomcat/util/IntrospectionUtils.java 
b/java/org/apache/tomcat/util/IntrospectionUtils.java
index 0c2eb6e..9987533 100644
--- a/java/org/apache/tomcat/util/IntrospectionUtils.java
+++ b/java/org/apache/tomcat/util/IntrospectionUtils.java
@@ -219,7 +219,15 @@ public final class IntrospectionUtils {
     }
 
     /**
-     * Replace ${NAME} with the property value.
+     * Replaces ${NAME} in the value with the value of the property 'NAME'.
+     * Replaces ${NAME:DEFAULT} with the value of the property 'NAME:DEFAULT',
+     * if the property 'NAME:DEFAULT' is not set,
+     * the expression is replaced with the value of the property 'NAME',
+     * if the property 'NAME' is not set,
+     * the expression is replaced with 'DEFAULT'.
+     * If the property is not set and there is no default the value will be
+     * returned unmodified.
+     *
      * @param value The value
      * @param staticProp Replacement properties
      * @param dynamicProp Replacement properties
@@ -239,6 +247,7 @@ public final class IntrospectionUtils {
      * @param dynamicProp Replacement properties
      * @param classLoader Class loader associated with the code requesting the
      *                    property
+     *
      * @return the replacement value
      */
     public static String replaceProperties(String value,
@@ -270,25 +279,21 @@ public final class IntrospectionUtils {
                     continue;
                 }
                 String n = value.substring(pos + 2, endName);
-                String v = null;
-                if (staticProp != null) {
-                    v = (String) staticProp.get(n);
-                }
-                if (v == null && dynamicProp != null) {
-                    for (PropertySource propertySource : dynamicProp) {
-                        if (propertySource instanceof SecurePropertySource) {
-                            v = ((SecurePropertySource) 
propertySource).getProperty(n, classLoader);
-                        } else {
-                            v = propertySource.getProperty(n);
-                        }
-                        if (v != null) {
-                            break;
+                String v = getProperty(n, staticProp, dynamicProp, 
classLoader);
+                if (v == null) {
+                    // {name:default}
+                    int col = n.indexOf(':');
+                    if (col != -1) {
+                        String dV = n.substring(col+1);
+                        n = n.substring(0, col);
+                        v = getProperty(n, staticProp, dynamicProp, 
classLoader);
+                        if (v == null) {
+                            v = dV;
                         }
+                    } else {
+                        v = "${" + n + "}";
                     }
                 }
-                if (v == null)
-                    v = "${" + n + "}";
-
                 sb.append(v);
                 prev = endName + 1;
             }
@@ -298,6 +303,27 @@ public final class IntrospectionUtils {
         return sb.toString();
     }
 
+    private static String getProperty(String name, Hashtable<Object, Object> 
staticProp,
+            PropertySource[] dynamicProp, ClassLoader classLoader) {
+        String v = null;
+        if (staticProp != null) {
+            v = (String) staticProp.get(name);
+        }
+        if (v == null && dynamicProp != null) {
+            for (PropertySource propertySource : dynamicProp) {
+                if (propertySource instanceof SecurePropertySource) {
+                    v = ((SecurePropertySource) 
propertySource).getProperty(name, classLoader);
+                } else {
+                    v = propertySource.getProperty(name);
+                }
+                if (v != null) {
+                    break;
+                }
+            }
+        }
+        return v;
+    }
+
     /**
      * Reverse of Introspector.decapitalize.
      * @param name The name
diff --git a/test/org/apache/tomcat/util/TestIntrospectionUtils.java 
b/test/org/apache/tomcat/util/TestIntrospectionUtils.java
index 64864f6..ef27174 100644
--- a/test/org/apache/tomcat/util/TestIntrospectionUtils.java
+++ b/test/org/apache/tomcat/util/TestIntrospectionUtils.java
@@ -16,6 +16,8 @@
  */
 package org.apache.tomcat.util;
 
+import java.util.Properties;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -101,12 +103,45 @@ public class TestIntrospectionUtils {
                 StandardContext.class, 
"javax.management.NotificationBroadcaster"));
     }
 
-    // And one to check that non-matches return false
 
+    // And one to check that non-matches return false
 
     @Test
     public void testIsInstanceStandardContext12() {
         Assert.assertFalse(IntrospectionUtils.isInstance(
                 StandardContext.class, "com.example.Other"));
     }
+
+
+    @Test
+    public void testReplaceProperties() {
+        Properties properties = new Properties();
+
+        Assert.assertEquals("no-expression", 
IntrospectionUtils.replaceProperties(
+                "no-expression", properties, null, null));
+
+        Assert.assertEquals("${normal}", IntrospectionUtils.replaceProperties(
+                "${normal}", properties, null, null));
+
+        properties.setProperty("normal", "value1");
+        Assert.assertEquals("value1", IntrospectionUtils.replaceProperties(
+                "${normal}", properties, null, null));
+
+        Assert.assertEquals("abcvalue1xyz", 
IntrospectionUtils.replaceProperties(
+                "abc${normal}xyz", properties, null, null));
+
+        properties.setProperty("prop_with:colon", "value2");
+        Assert.assertEquals("value2", IntrospectionUtils.replaceProperties(
+                "${prop_with:colon}", properties, null, null));
+
+        Assert.assertEquals("value1", IntrospectionUtils.replaceProperties(
+                "${normal:default}", properties, null, null));
+
+        properties.remove("normal");
+        Assert.assertEquals("default", IntrospectionUtils.replaceProperties(
+                "${normal:default}", properties, null, null));
+
+        Assert.assertEquals("abc${normal}xyz", 
IntrospectionUtils.replaceProperties(
+                "abc${normal}xyz", properties, null, null));
+    }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index e0a6bfe..b50f759 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -74,6 +74,11 @@
         <bug>64265</bug>: Fix ETag comparison performed by the default servlet.
         The default servley always uses weak comparison. (markt)
       </fix>
+      <fix>
+        Add support for default values when using <code>${...}</code> property
+        replacement in configuration files. Based on a pull request provided by
+        Bernd Bohmann. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">
diff --git a/webapps/docs/config/systemprops.xml 
b/webapps/docs/config/systemprops.xml
index 1cff7e8..b472daf 100644
--- a/webapps/docs/config/systemprops.xml
+++ b/webapps/docs/config/systemprops.xml
@@ -45,8 +45,9 @@
          <code>org.apache.tomcat.util.IntrospectionUtils.PropertySource</code>.
          Required to have a public constructor with no arguments.</p>
       <p>Use this to add a property source, that will be invoked when
-         <code>${parameter}</code> denoted parameters are found in the XML 
files
-         that Tomcat parses.</p>
+         <code>${parameter:default-value}</code> denoted parameters (with
+         optional default values) are found in the XML files that Tomcat
+         parses.</p>
       <p>Property replacement from the specified property source on the JVM
          system properties can also be done using the
          <code>REPLACE_SYSTEM_PROPERTIES</code> system property.</p>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to