commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ebo...@apache.org
Subject svn commit: r225522 - in /jakarta/commons/proper/configuration/trunk: ./ conf/ src/java/org/apache/commons/configuration/ src/test/org/apache/commons/configuration/ xdocs/
Date Wed, 27 Jul 2005 14:13:06 GMT
Author: ebourg
Date: Wed Jul 27 07:12:59 2005
New Revision: 225522

URL: http://svn.apache.org/viewcvs?rev=225522&view=rev
Log:
PropertiesConfiguration now supports all key/value separators supported by java.util.Properties
(Bug 29171)
PropertiesConfiguration now supports escaped key/value separators in the keys (Bug 29192).
Updated the dependency on Commons Lang (2.1 instead of 2.0)

Modified:
    jakarta/commons/proper/configuration/trunk/conf/test.properties
    jakarta/commons/proper/configuration/trunk/project.xml
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
    jakarta/commons/proper/configuration/trunk/xdocs/changes.xml

Modified: jakarta/commons/proper/configuration/trunk/conf/test.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/conf/test.properties?rev=225522&r1=225521&r2=225522&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/conf/test.properties (original)
+++ jakarta/commons/proper/configuration/trunk/conf/test.properties Wed Jul 27 07:12:59 2005
@@ -75,6 +75,25 @@
 test.path = C:\\path3\\\
 complex\\test\\
 
+#
+# Test for the comment lines
+#
 
 #comment = this is not a property but a comment line starting with '#'
 !comment = this is not a property but a comment line starting with '!'
+
+#
+# Tests for the key/value separators ('=', ':' or white space, escaped or not)
+#
+
+test.separator\=in.key = foo
+test.separator\:in.key = bar
+test.separator\	in.key = foo
+test.separator\in.key = bar
+test.separator\ in.key = foo
+
+test.separator.equal = foo
+test.separator.colon : foo
+test.separator.tab	foo
+test.separator.formfeedfoo
+test.separator.whitespace foo

Modified: jakarta/commons/proper/configuration/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/project.xml?rev=225522&r1=225521&r2=225522&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/project.xml (original)
+++ jakarta/commons/proper/configuration/trunk/project.xml Wed Jul 27 07:12:59 2005
@@ -209,7 +209,7 @@
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-      <version>2.0</version>
+      <version>2.1</version>
       <properties>
         <war.bundle>true</war.bundle>
       </properties>

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java?rev=225522&r1=225521&r2=225522&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
(original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
Wed Jul 27 07:12:59 2005
@@ -29,6 +29,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 
@@ -42,14 +43,24 @@
  * added and later saved. include statements are (obviously) not supported
  * if you don't construct a PropertyConfiguration from a file.
  *
- * <p>The properties file syntax is explained here:
+ * <p>The properties file syntax is explained here, basically it follows
+ * the syntax of the stream parsed by {@link java.util.Properties#load} and
+ * adds several useful extensions:
  *
  * <ul>
  *  <li>
- *   Each property has the syntax <code>key = value</code>
+ *   Each property has the syntax <code>key &lt;separator> value</code>.
The
+ *   separators accepted are <code>'='</code>, <code>':'</code> and
any white
+ *   space character. Examples:
+ * <pre>
+ *  key1 = value1
+ *  key2 : value2
+ *  key3   value3</pre>
  *  </li>
  *  <li>
- *   The <i>key</i> may use any character but the equal sign '='.
+ *   The <i>key</i> may use any character, separators must be escaped:
+ * <pre>
+ *  key\:foo = bar</pre>
  *  </li>
  *  <li>
  *   <i>value</i> may be separated on different lines if a backslash
@@ -108,7 +119,7 @@
  *      tokens_on_multiple_lines = second token
  *
  *      # commas may be escaped in tokens
- *      commas.excaped = Hi\, what'up?
+ *      commas.escaped = Hi\, what'up?
  *
  *      # properties can reference other properties
  *      base.prop = /base
@@ -116,7 +127,8 @@
  *      second.prop = ${first.prop}/second
  * </pre>
  *
- * @author <a href="mailto:e.bourg@cross-systems.com">Emmanuel Bourg</a>
+ * @see java.util.Properties#load
+ *
  * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
  * @author <a href="mailto:daveb@miceda-data">Dave Bryson</a>
@@ -130,10 +142,17 @@
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
  * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
+ * @author <a href="mailto:ebourg@apache.org">Emmanuel Bourg</a>
  * @version $Id$
  */
 public class PropertiesConfiguration extends AbstractFileConfiguration
 {
+    /** The list of possible key/value separators */
+    private static final char[] SEPARATORS = new char[] { '=', ':' };
+
+    /** The white space characters used as key/value separators. */
+    private static final char[] WHITE_SPACE = new char[] { ' ', '\t', '\f' };
+
     /**
      * This is the name of the property that can point to other
      * properties file for including other properties files.
@@ -286,34 +305,32 @@
                     break; // EOF
                 }
 
-                int equalSign = line.indexOf('=');
-                if (equalSign > 0)
-                {
-                    String key = line.substring(0, equalSign).trim();
-                    String value = line.substring(equalSign + 1).trim();
-
-                    // Though some software (e.g. autoconf) may produce
-                    // empty values like foo=\n, emulate the behavior of
-                    // java.util.Properties by setting the value to the
-                    // empty string.
+                // parse the line
+                String[] property = parseProperty(line);
+                String key = property[0];
+                String value = property[1];
+
+                // Though some software (e.g. autoconf) may produce
+                // empty values like foo=\n, emulate the behavior of
+                // java.util.Properties by setting the value to the
+                // empty string.
 
-                    if (StringUtils.isNotEmpty(getInclude())
-                        && key.equalsIgnoreCase(getInclude()))
+                if (StringUtils.isNotEmpty(getInclude()) && key.equalsIgnoreCase(getInclude()))
+                {
+                    if (getIncludesAllowed())
                     {
-                        if (getIncludesAllowed())
+                        String [] files = StringUtils.split(value, getDelimiter());
+                        for (int i = 0; i < files.length; i++)
                         {
-                            String [] files = StringUtils.split(value, getDelimiter());
-                            for (int i = 0; i < files.length; i++)
-                            {
-                                load(ConfigurationUtils.locate(getBasePath(), files[i].trim()));
-                            }
+                            load(ConfigurationUtils.locate(getBasePath(), files[i].trim()));
                         }
                     }
-                    else
-                    {
-                        addProperty(key, unescapeJava(value, getDelimiter()));
-                    }
                 }
+                else
+                {
+                    addProperty(key, unescapeJava(value, getDelimiter()));
+                }
+
             }
         }
         catch (IOException ioe)
@@ -498,7 +515,7 @@
          */
         public void writeProperty(String key, Object value) throws IOException
         {
-            write(key);
+            write(escapeKey(key));
             write(" = ");
             if (value != null)
             {
@@ -534,6 +551,33 @@
         {
             write("# " + comment + "\n");
         }
+
+        /**
+         * Escape the separators in the key.
+         */
+        private String escapeKey(String key)
+        {
+            StringBuffer newkey = new StringBuffer();
+
+            for (int i = 0; i < key.length(); i++)
+            {
+                char c = key.charAt(i);
+
+                if (ArrayUtils.contains(SEPARATORS, c) || ArrayUtils.contains(WHITE_SPACE,
c))
+                {
+                    // escape the separator
+                    newkey.append('\\');
+                    newkey.append(c);
+                }
+                else
+                {
+                    newkey.append(c);
+                }
+            }
+
+            return newkey.toString();
+        }
+
     } // class PropertiesWriter
 
     /**
@@ -644,6 +688,104 @@
         }
 
         return out.toString();
+    }
+
+    /**
+     * Parse a property line and return the key and the value in an array.
+     */
+    private String[] parseProperty(String line)
+    {
+        // sorry for this spaghetti code, please replace it as soon as
+        // possible with a regexp when the Java 1.3 requirement is dropped
+
+        String[] result = new String[2];
+        StringBuffer key = new StringBuffer();
+        StringBuffer value = new StringBuffer();
+
+        // state of the automaton:
+        // 0: key parsing
+        // 1: antislash found while parsing the key
+        // 2: separator crossing
+        // 3: value parsing
+        int state = 0;
+
+        for (int pos = 0; pos < line.length(); pos++)
+        {
+            char c = line.charAt(pos);
+
+            switch (state)
+            {
+                case 0:
+                    if (c == '\\')
+                    {
+                        state = 1;
+                    }
+                    else if (ArrayUtils.contains(WHITE_SPACE, c))
+                    {
+                        // switch to the separator crossing state
+                        state = 2;
+                    }
+                    else if (ArrayUtils.contains(SEPARATORS, c))
+                    {
+                        // switch to the value parsing state
+                        state = 3;
+                    }
+                    else
+                    {
+                        key.append(c);
+                    }
+
+                    break;
+
+                case 1:
+                    if (ArrayUtils.contains(SEPARATORS, c) || ArrayUtils.contains(WHITE_SPACE,
c))
+                    {
+                        // this is an escaped separator or white space
+                        key.append(c);
+                    }
+                    else
+                    {
+                        // another escaped character, the '\' is preserved
+                        key.append('\\');
+                        key.append(c);
+                    }
+
+                    // return to the key parsing state
+                    state = 0;
+
+                    break;
+
+                case 2:
+                    if (ArrayUtils.contains(WHITE_SPACE, c))
+                    {
+                        // do nothing, eat all white spaces
+                    }
+                    else if (ArrayUtils.contains(SEPARATORS, c))
+                    {
+                        // switch to the value parsing state
+                        state = 3;
+                    }
+                    else
+                    {
+                        // any other character indicates we encoutered the beginning of the
value
+                        value.append(c);
+
+                        // switch to the value parsing state
+                        state = 3;
+                    }
+
+                    break;
+
+                case 3:
+                    value.append(c);
+                    break;
+            }
+        }
+
+        result[0] = key.toString().trim();
+        result[1] = value.toString().trim();
+
+        return result;
     }
 
 }

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java?rev=225522&r1=225521&r2=225522&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
(original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
Wed Jul 27 07:12:59 2005
@@ -371,4 +371,27 @@
         assertFalse("comment line starting with '#' parsed as a property", conf.containsKey("#comment"));
         assertFalse("comment line starting with '!' parsed as a property", conf.containsKey("!comment"));
     }
+
+    /**
+     * Check that key/value separators can be part of a key.
+     */
+    public void testEscapedKeyValueSeparator()
+    {
+        assertEquals("Escaped separator '=' not supported in keys", "foo", conf.getProperty("test.separator=in.key"));
+        assertEquals("Escaped separator ':' not supported in keys", "bar", conf.getProperty("test.separator:in.key"));
+        assertEquals("Escaped separator '\\t' not supported in keys", "foo", conf.getProperty("test.separator\tin.key"));
+        assertEquals("Escaped separator '\\f' not supported in keys", "bar", conf.getProperty("test.separator\fin.key"));
+        assertEquals("Escaped separator ' ' not supported in keys"  , "foo", conf.getProperty("test.separator
in.key"));
+    }
+
+    /**
+     * Test all acceptable key/value separators ('=', ':' or white spaces).
+     */
+    public void testKeyValueSeparators() {
+        assertEquals("equal separator not properly parsed",      "foo", conf.getProperty("test.separator.equal"));
+        assertEquals("colon separator not properly parsed",      "foo", conf.getProperty("test.separator.colon"));
+        assertEquals("tab separator not properly parsed",        "foo", conf.getProperty("test.separator.tab"));
+        assertEquals("formfeed separator not properly parsed",   "foo", conf.getProperty("test.separator.formfeed"));
+        assertEquals("whitespace separator not properly parsed", "foo", conf.getProperty("test.separator.whitespace"));
+    }
 }

Modified: jakarta/commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/xdocs/changes.xml?rev=225522&r1=225521&r2=225522&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Wed Jul 27 07:12:59 2005
@@ -23,6 +23,17 @@
   <body>
 
     <release version="1.2-dev" date="in SVN">
+      <action dev="ebourg" type="add" issue="29192">
+        PropertiesConfiguration now supports escaped key/value separators in the keys
+        (i.e foo\:key = bar).
+      </action>
+      <action dev="ebourg" type="add" issue="29171">
+        PropertiesConfiguration now supports all key/value separators supported by java.util.Properties
+        ('=', ':' and white space characters).
+      </action>
+      <action dev="ebourg" type="update">
+        Commons Configuration now depends on Commons Lang 2.1 instead of 2.0
+      </action>
       <action dev="ebourg" type="update" issue="35888">
         Comment lines for PropertiesConfiguration can start with the '!' char (compatibility
with java.util.Properties)
       </action>



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


Mime
View raw message