You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/02/22 20:43:23 UTC

svn commit: r379859 - in /jakarta/commons/proper/configuration/trunk: src/java/org/apache/commons/configuration/ src/test/org/apache/commons/configuration/ xdocs/

Author: oheger
Date: Wed Feb 22 11:43:20 2006
New Revision: 379859

URL: http://svn.apache.org/viewcvs?rev=379859&view=rev
Log:
Moved implementation of interpolation features from AbstractConfiguration to PropertiesConverter, so that it can be accessed from other objects, too (namely bean declaration classes)

Modified:
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java
    jakarta/commons/proper/configuration/trunk/xdocs/changes.xml

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java?rev=379859&r1=379858&r2=379859&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java Wed Feb 22 11:43:20 2006
@@ -219,7 +219,8 @@
      */
     protected String interpolate(String base)
     {
-        return interpolateHelper(base, null);
+        Object result = interpolate((Object) base);
+        return (result == null) ? null : result.toString();
     }
 
     /**
@@ -231,14 +232,7 @@
      */
     protected Object interpolate(Object value)
     {
-        if (value instanceof String)
-        {
-            return interpolate((String) value);
-        }
-        else
-        {
-            return value;
-        }
+        return PropertyConverter.interpolate(value, this);
     }
 
     /**
@@ -253,82 +247,13 @@
      * subsequent interpolated variables are added afterward.
      *
      * @return the string with the interpolation taken care of
+     * @deprecated Interpolation is now handled by
+     * <code>{@link PropertyConverter}</code>; this method will no longer be
+     * called
      */
     protected String interpolateHelper(String base, List priorVariables)
     {
-        if (base == null)
-        {
-            return null;
-        }
-
-        // on the first call initialize priorVariables
-        // and add base as the first element
-        if (priorVariables == null)
-        {
-            priorVariables = new ArrayList();
-            priorVariables.add(base);
-        }
-
-        int begin = -1;
-        int end = -1;
-        int prec = 0 - END_TOKEN.length();
-        StringBuffer result = new StringBuffer();
-
-        // FIXME: we should probably allow the escaping of the start token
-        while (((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length())) > -1)
-                && ((end = base.indexOf(END_TOKEN, begin)) > -1))
-        {
-            result.append(base.substring(prec + END_TOKEN.length(), begin));
-            String variable = base.substring(begin + START_TOKEN.length(), end);
-
-            // if we've got a loop, create a useful exception message and throw
-            if (priorVariables.contains(variable))
-            {
-                String initialBase = priorVariables.remove(0).toString();
-                priorVariables.add(variable);
-                StringBuffer priorVariableSb = new StringBuffer();
-
-                // create a nice trace of interpolated variables like so:
-                // var1->var2->var3
-                for (Iterator it = priorVariables.iterator(); it.hasNext();)
-                {
-                    priorVariableSb.append(it.next());
-                    if (it.hasNext())
-                    {
-                        priorVariableSb.append("->");
-                    }
-                }
-
-                throw new IllegalStateException("infinite loop in property interpolation of " + initialBase + ": "
-                        + priorVariableSb.toString());
-            }
-            // otherwise, add this variable to the interpolation list.
-            else
-            {
-                priorVariables.add(variable);
-            }
-
-            Object value = resolveContainerStore(variable);
-            if (value != null)
-            {
-                result.append(interpolateHelper(value.toString(), priorVariables));
-
-                // pop the interpolated variable off the stack
-                // this maintains priorVariables correctness for
-                // properties with multiple interpolations, e.g.
-                // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}
-                priorVariables.remove(priorVariables.size() - 1);
-            }
-            else
-            {
-                //variable not defined - so put it back in the value
-                result.append(START_TOKEN).append(variable).append(END_TOKEN);
-            }
-
-            prec = end;
-        }
-        result.append(base.substring(prec + END_TOKEN.length(), base.length()));
-        return result.toString();
+        return base; // just a dummy implementation
     }
 
     /**

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java?rev=379859&r1=379858&r2=379859&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java Wed Feb 22 11:43:20 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2005 The Apache Software Foundation.
+ * Copyright 2004-2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License")
  * you may not use this file except in compliance with the License.
@@ -714,5 +714,127 @@
         {
             return new SingletonIterator(value);
         }
+    }
+
+    /**
+     * Performs interpolation of the specified value. This method checks if the
+     * given value contains variables of the form <code>${...}</code>. If
+     * this is the case, all occurrances will be substituted by their current
+     * values.
+     *
+     * @param value the value to be interpolated
+     * @param config the current configuration object
+     * @return the interpolated value
+     */
+    public static Object interpolate(Object value, AbstractConfiguration config)
+    {
+        if (value instanceof String)
+        {
+            return interpolateHelper((String) value, null, config);
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    /**
+     * Recursive handler for multple levels of interpolation. This will be
+     * replaced when Commons Lang provides an interpolation feature. When called
+     * the first time, priorVariables should be null.
+     *
+     * @param base string with the ${key} variables
+     * @param priorVariables serves two purposes: to allow checking for loops,
+     * and creating a meaningful exception message should a loop occur. It's
+     * 0'th element will be set to the value of base from the first call. All
+     * subsequent interpolated variables are added afterward.
+     * @param config the current configuration
+     * @return the string with the interpolation taken care of
+     */
+    private static String interpolateHelper(String base, List priorVariables,
+            AbstractConfiguration config)
+    {
+        if (base == null)
+        {
+            return null;
+        }
+
+        // on the first call initialize priorVariables
+        // and add base as the first element
+        if (priorVariables == null)
+        {
+            priorVariables = new ArrayList();
+            priorVariables.add(base);
+        }
+
+        int begin = -1;
+        int end = -1;
+        int prec = 0 - AbstractConfiguration.END_TOKEN.length();
+        StringBuffer result = new StringBuffer();
+
+        // FIXME: we should probably allow the escaping of the start token
+        while (((begin = base.indexOf(AbstractConfiguration.START_TOKEN, prec
+                + AbstractConfiguration.END_TOKEN.length())) > -1)
+                && ((end = base.indexOf(AbstractConfiguration.END_TOKEN, begin)) > -1))
+        {
+            result.append(base.substring(prec
+                    + AbstractConfiguration.END_TOKEN.length(), begin));
+            String variable = base.substring(begin
+                    + AbstractConfiguration.START_TOKEN.length(), end);
+
+            // if we've got a loop, create a useful exception message and throw
+            if (priorVariables.contains(variable))
+            {
+                String initialBase = priorVariables.remove(0).toString();
+                priorVariables.add(variable);
+                StringBuffer priorVariableSb = new StringBuffer();
+
+                // create a nice trace of interpolated variables like so:
+                // var1->var2->var3
+                for (Iterator it = priorVariables.iterator(); it.hasNext();)
+                {
+                    priorVariableSb.append(it.next());
+                    if (it.hasNext())
+                    {
+                        priorVariableSb.append("->");
+                    }
+                }
+
+                throw new IllegalStateException(
+                        "infinite loop in property interpolation of "
+                                + initialBase + ": "
+                                + priorVariableSb.toString());
+            }
+            // otherwise, add this variable to the interpolation list.
+            else
+            {
+                priorVariables.add(variable);
+            }
+
+            Object value = config.resolveContainerStore(variable);
+            if (value != null)
+            {
+                result.append(interpolateHelper(value.toString(),
+                        priorVariables, config));
+
+                // pop the interpolated variable off the stack
+                // this maintains priorVariables correctness for
+                // properties with multiple interpolations, e.g.
+                // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}
+                priorVariables.remove(priorVariables.size() - 1);
+            }
+            else
+            {
+                // variable not defined - so put it back in the value
+                result.append(AbstractConfiguration.START_TOKEN);
+                result.append(variable);
+                result.append(AbstractConfiguration.END_TOKEN);
+            }
+
+            prec = end;
+        }
+        result.append(base.substring(prec
+                + AbstractConfiguration.END_TOKEN.length(), base.length()));
+        return result.toString();
     }
 }

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java?rev=379859&r1=379858&r2=379859&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java Wed Feb 22 11:43:20 2006
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ *
+ * 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
+ *
+ *     http://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.apache.commons.configuration;
 
 import java.util.List;
@@ -6,6 +21,8 @@
 import junit.framework.TestCase;
 
 /**
+ * Test class for PropertyConverter.
+ *
  * @author Emmanuel Bourg
  * @version $Revision$, $Date$
  */
@@ -71,4 +88,79 @@
         assertEquals("3rd element", new Integer(3), it.next());
     }
 
+    /**
+     * Tests the interpolation features.
+     */
+    public void testInterpolateString()
+    {
+        PropertiesConfiguration config = new PropertiesConfiguration();
+        config.addProperty("animal", "quick brown fox");
+        config.addProperty("target", "lazy dog");
+        assertEquals("Wrong interpolation",
+                "The quick brown fox jumps over the lazy dog.",
+                PropertyConverter.interpolate(
+                        "The ${animal} jumps over the ${target}.", config));
+    }
+
+    /**
+     * Tests interpolation of an object. Here nothing should be substituted.
+     */
+    public void testInterpolateObject()
+    {
+        assertEquals("Object was not correctly interpolated", new Integer(42),
+                PropertyConverter.interpolate(new Integer(42),
+                        new PropertiesConfiguration()));
+    }
+
+    /**
+     * Tests complex interpolation where the variables' values contain in turn
+     * other variables.
+     */
+    public void testInterpolateRecursive()
+    {
+        PropertiesConfiguration config = new PropertiesConfiguration();
+        config.addProperty("animal", "${animal_attr} fox");
+        config.addProperty("target", "${target_attr} dog");
+        config.addProperty("animal_attr", "quick brown");
+        config.addProperty("target_attr", "lazy");
+        assertEquals("Wrong complex interpolation",
+                "The quick brown fox jumps over the lazy dog.",
+                PropertyConverter.interpolate(
+                        "The ${animal} jumps over the ${target}.", config));
+    }
+
+    /**
+     * Tests an interpolation that leads to a cycle. This should throw an
+     * exception.
+     */
+    public void testCyclicInterpolation()
+    {
+        PropertiesConfiguration config = new PropertiesConfiguration();
+        config.addProperty("animal", "${animal_attr} ${species}");
+        config.addProperty("animal_attr", "quick brown");
+        config.addProperty("species", "${animal}");
+        try
+        {
+            PropertyConverter.interpolate("This is a ${animal}", config);
+            fail("Cyclic interpolation was not detected!");
+        }
+        catch (IllegalStateException iex)
+        {
+            // ok
+        }
+    }
+
+    /**
+     * Tests interpolation if a variable is unknown. Then the variable won't be
+     * substituted.
+     */
+    public void testInterpolationUnknownVariable()
+    {
+        PropertiesConfiguration config = new PropertiesConfiguration();
+        config.addProperty("animal", "quick brown fox");
+        assertEquals("Wrong interpolation",
+                "The quick brown fox jumps over ${target}.", PropertyConverter
+                        .interpolate("The ${animal} jumps over ${target}.",
+                                config));
+    }
 }

Modified: jakarta/commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/xdocs/changes.xml?rev=379859&r1=379858&r2=379859&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Wed Feb 22 11:43:20 2006
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!--
-   Copyright 2004-2005 The Apache Software Foundation
+   Copyright 2004-2006 The Apache Software Foundation
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -23,6 +23,12 @@
   <body>
 
     <release version="1.3-SNAPSHOT" date="in SVN">
+      <action dev="oheger" type="update">
+        The implementation of the interpolation features have been extracted out
+        off AbstractConfiguration and moved to PropertyConverter. The
+        interpolateHelper() method of AbstractConfiguration is now deprectated
+        and will not be called any more during interpolation.
+      </action>
       <action dev="oheger" type="add" issue="38075">
         A new method configurationsAdd() was added to HierarchicalConfiguration
         that provides a convenient way of iterating over complex list-like



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org