You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2011/05/09 22:35:24 UTC

svn commit: r1101212 - in /commons/proper/configuration/trunk/src: changes/changes.xml java/org/apache/commons/configuration/HierarchicalINIConfiguration.java test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java

Author: oheger
Date: Mon May  9 20:35:24 2011
New Revision: 1101212

URL: http://svn.apache.org/viewvc?rev=1101212&view=rev
Log:
[CONFIGURATION-448] Improved handling of separators in HierarchicalINIConfiguration.

Modified:
    commons/proper/configuration/trunk/src/changes/changes.xml
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalINIConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java

Modified: commons/proper/configuration/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/changes/changes.xml?rev=1101212&r1=1101211&r2=1101212&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/changes/changes.xml (original)
+++ commons/proper/configuration/trunk/src/changes/changes.xml Mon May  9 20:35:24 2011
@@ -23,6 +23,10 @@
 
   <body>
     <release version="1.7" date="in SVN" description="">
+      <action dev="oheger" type="add" issue="CONFIGURATION-448">
+        The parsing of ini files has been improved for property definitions
+        containing multiple separator characters.
+      </action>
       <action dev="oheger" type="add" issue="CONFIGURATION-447">
         DefaultConfigurationBuilder now supports including environment properties
         using the "env" tag.

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalINIConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalINIConfiguration.java?rev=1101212&r1=1101211&r2=1101212&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalINIConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalINIConfiguration.java Mon May  9 20:35:24 2011
@@ -133,6 +133,10 @@ import org.apache.commons.lang.StringUti
  *  var3 = foo<br>
  *  var4 = bar<br>
  *  var5 = test2<br>
+ *  <br>
+ *  [sectionSeparators]<br>
+ *  passwd : abc=def<br>
+ *  a:b = "value"
  *  </code>
  * </p>
  * <p>
@@ -150,6 +154,15 @@ import org.apache.commons.lang.StringUti
  * <li>Section three uses both '=' and ':' to separate keys and values.</li>
  * <li>Section 3 has a duplicate key named "var5". The value for this key is
  * [test1, test2], and is represented as a List.</li>
+ * <li>The section called <em>sectionSeparators</em> demonstrates how the
+ * configuration deals with multiple occurrences of separator characters. Per
+ * default the first separator character in a line is detected and used to
+ * split the key from the value. Therefore the first property definition in this
+ * section has the key <code>passwd</code> and the value <code>abc=def</code>.
+ * This default behavior can be changed by using quotes. If there is a separator
+ * character before the first quote character (ignoring whitespace), this
+ * character is used as separator. Thus the second property definition in the
+ * section has the key <code>a:b</code> and the value <code>value</code>.</li>
  * </ul>
  * </p>
  * <p>
@@ -208,6 +221,11 @@ public class HierarchicalINIConfiguratio
     private static final String LINE_SEPARATOR = System.getProperty("line.separator");
 
     /**
+     * The characters used for quoting values.
+     */
+    private static final String QUOTE_CHARACTERS = "\"'";
+
+    /**
      * The line continuation character.
      */
     private static final String LINE_CONT = "\\";
@@ -347,7 +365,7 @@ public class HierarchicalINIConfiguratio
                     {
                         String key = "";
                         String value = "";
-                        int index = line.indexOf("=");
+                        int index = findSeparator(line);
                         if (index >= 0)
                         {
                             key = line.substring(0, index);
@@ -355,16 +373,7 @@ public class HierarchicalINIConfiguratio
                         }
                         else
                         {
-                            index = line.indexOf(":");
-                            if (index >= 0)
-                            {
-                                key = line.substring(0, index);
-                                value = parseValue(line.substring(index + 1), bufferedReader);
-                            }
-                            else
-                            {
-                                key = line;
-                            }
+                            key = line;
                         }
                         key = key.trim();
                         if (key.length() < 1)
@@ -557,6 +566,84 @@ public class HierarchicalINIConfiguratio
     }
 
     /**
+     * Tries to find the index of the separator character in the given string.
+     * This method checks for the presence of separator characters in the given
+     * string. If multiple characters are found, the first one is assumed to be
+     * the correct separator. If there are quoting characters, they are taken
+     * into account, too.
+     *
+     * @param line the line to be checked
+     * @return the index of the separator character or -1 if none is found
+     */
+    private static int findSeparator(String line)
+    {
+        int index =
+                findSeparatorBeforeQuote(line,
+                        findFirstOccurrence(line, QUOTE_CHARACTERS));
+        if (index < 0)
+        {
+            index = findFirstOccurrence(line, SEPARATOR_CHARS);
+        }
+        return index;
+    }
+
+    /**
+     * Checks for the occurrence of the specified separators in the given line.
+     * The index of the first separator is returned.
+     *
+     * @param line the line to be investigated
+     * @param separators a string with the separator characters to look for
+     * @return the lowest index of a separator character or -1 if no separator
+     *         is found
+     */
+    private static int findFirstOccurrence(String line, String separators)
+    {
+        int index = -1;
+
+        for (int i = 0; i < separators.length(); i++)
+        {
+            char sep = separators.charAt(i);
+            int pos = line.indexOf(sep);
+            if (pos >= 0)
+            {
+                if (index < 0 || pos < index)
+                {
+                    index = pos;
+                }
+            }
+        }
+
+        return index;
+    }
+
+    /**
+     * Searches for a separator character directly before a quoting character.
+     * If the first non-whitespace character before a quote character is a
+     * separator, it is considered the "real" separator in this line - even if
+     * there are other separators before.
+     *
+     * @param line the line to be investigated
+     * @param quoteIndex the index of the quote character
+     * @return the index of the separator before the quote or &lt; 0 if there is
+     *         none
+     */
+    private static int findSeparatorBeforeQuote(String line, int quoteIndex)
+    {
+        int index = quoteIndex - 1;
+        while (index >= 0 && Character.isWhitespace(line.charAt(index)))
+        {
+            index--;
+        }
+
+        if (index >= 0 && SEPARATOR_CHARS.indexOf(line.charAt(index)) < 0)
+        {
+            index = -1;
+        }
+
+        return index;
+    }
+
+    /**
      * Add quotes around the specified value if it contains a comment character.
      */
     private String formatValue(String value)

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java?rev=1101212&r1=1101211&r2=1101212&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestHierarchicalINIConfiguration.java Mon May  9 20:35:24 2011
@@ -76,6 +76,16 @@ public class TestHierarchicalINIConfigur
             + "  line 2" + LINE_SEPARATOR
             + "continueNoLine = one \\" + LINE_SEPARATOR;
 
+    private static final String INI_DATA_SEPARATORS = "[section]"
+            + LINE_SEPARATOR + "var1 = value1" + LINE_SEPARATOR
+            + "var2 : value2" + LINE_SEPARATOR
+            + "var3=value3" + LINE_SEPARATOR
+            + "var4:value4" + LINE_SEPARATOR
+            + "var5 : value=5" + LINE_SEPARATOR
+            + "var:6=value" + LINE_SEPARATOR
+            + "var:7=\"value7\"" + LINE_SEPARATOR
+            + "var:8 =  \"value8\"" + LINE_SEPARATOR;
+
     /** An ini file that contains only a property in the global section. */
     private static final String INI_DATA_GLOBAL_ONLY = "globalVar = testGlobal"
             + LINE_SEPARATOR + LINE_SEPARATOR;
@@ -704,6 +714,45 @@ public class TestHierarchicalINIConfigur
     }
 
     /**
+     * Tests whether the different separators with or without whitespace are
+     * recognized.
+     */
+    public void testSeparators() throws ConfigurationException
+    {
+        HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
+        for (int i = 1; i <= 4; i++)
+        {
+            assertEquals("Wrong value", "value" + i,
+                    config.getString("section.var" + i));
+        }
+    }
+
+    /**
+     * Tests property definitions containing multiple separators.
+     */
+    public void testMultipleSeparators() throws ConfigurationException
+    {
+        HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
+        assertEquals("Wrong value for var5", "value=5",
+                config.getString("section.var5"));
+        assertEquals("Wrong value for var6", "6=value",
+                config.getString("section.var"));
+    }
+
+    /**
+     * Tests property definitions containing multiple separators that are
+     * quoted.
+     */
+    public void testMultipleSeparatorsQuoted() throws ConfigurationException
+    {
+        HierarchicalINIConfiguration config = setUpConfig(INI_DATA_SEPARATORS);
+        assertEquals("Wrong value for var7", "value7",
+                config.getString("section.var:7"));
+        assertEquals("Wrong value for var8", "value8",
+                config.getString("section.var:8"));
+    }
+
+    /**
      * A thread class for testing concurrent access to the global section.
      */
     private static class GlobalSectionTestThread extends Thread