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 2007/05/08 22:55:43 UTC

svn commit: r536326 - in /jakarta/commons/proper/configuration/trunk: conf/test.xml src/java/org/apache/commons/configuration/XMLConfiguration.java src/test/org/apache/commons/configuration/TestXMLConfiguration.java xdocs/changes.xml

Author: oheger
Date: Tue May  8 13:55:42 2007
New Revision: 536326

URL: http://svn.apache.org/viewvc?view=rev&rev=536326
Log:
CONFIGURATION-268: Perform correct splitting and escaping when delimiter parsing is disabled for XMLConfiguration

Modified:
    jakarta/commons/proper/configuration/trunk/conf/test.xml
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java
    jakarta/commons/proper/configuration/trunk/xdocs/changes.xml

Modified: jakarta/commons/proper/configuration/trunk/conf/test.xml
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/conf/test.xml?view=diff&rev=536326&r1=536325&r2=536326
==============================================================================
--- jakarta/commons/proper/configuration/trunk/conf/test.xml (original)
+++ jakarta/commons/proper/configuration/trunk/conf/test.xml Tue May  8 13:55:42 2007
@@ -85,4 +85,9 @@
       <a name="y">1,2,3</a>
       <a name="u,v,w" test="yes">value1,value2</a>
     </attrList>
+
+    <!-- An attribute with multiple values and escape characters for testing
+         splitting when delimiter parsing is disabled.
+    -->
+    <expressions value="a \|\| (b &amp;&amp; c)|!d"/>
 </testconfig>

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java?view=diff&rev=536326&r1=536325&r2=536326
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java Tue May  8 13:55:42 2007
@@ -40,7 +40,6 @@
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
-import org.apache.commons.collections.iterators.SingletonIterator;
 import org.w3c.dom.Attr;
 import org.w3c.dom.CDATASection;
 import org.w3c.dom.DOMException;
@@ -93,6 +92,35 @@
  * <code>cite</code> element the comma is escaped, so that no splitting is
  * performed.</p>
  *
+ * <p>The configuration API allows setting multiple values for a single attribute,
+ * e.g. something like the following is legal (assuming that the default
+ * expression engine is used):
+ * <pre>
+ * XMLConfiguration config = new XMLConfiguration();
+ * config.addProperty("test.dir[@name]", "C:\\Temp\\");
+ * config.addProperty("test.dir[@name]", "D:\\Data\\");
+ * </pre></p>
+ *
+ * <p>Because in XML such a constellation is not directly supported (an attribute
+ * can appear only once for a single element), the values are concatenated to a
+ * single value. If delimiter parsing is enabled (refer to the
+ * <code>{@link #setDelimiterParsingDisabled(boolean)}</code> method), the
+ * current list delimiter character will be used as separator. Otherwise the
+ * pipe symbol ("|") will be used for this purpose. No matter which character is
+ * used as delimiter, it can always be escaped with a backslash. A backslash
+ * itself can also be escaped with another backslash. Consider the following
+ * example fragment from a configuration file:
+ * <pre>
+ * &lt;directories names="C:\Temp\\|D:\Data\"/&gt;
+ * </pre>
+ * Here the backslash after Temp is escaped. This is necessary because it
+ * would escape the list delimiter (the pipe symbol assuming that list delimiter
+ * parsing is disabled) otherwise. So this attribute would have two values.</p>
+ *
+ * <p>Note: You should ensure that the <em>delimiter parsing disabled</em>
+ * property is always consistent when you load and save a configuration file.
+ * Otherwise the values of properties can become corrupted.</p>
+ *
  * <p><code>XMLConfiguration</code> implements the <code>{@link FileConfiguration}</code>
  * interface and thus provides full support for loading XML documents from
  * different sources like files, URLs, or streams. A full description of these
@@ -102,7 +130,7 @@
  * @since commons-configuration 1.0
  *
  * @author J&ouml;rg Schaible
- * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger </a>
+ * @author Oliver Heger
  * @version $Revision$, $Date$
  */
 public class XMLConfiguration extends AbstractHierarchicalFileConfiguration
@@ -115,6 +143,9 @@
     /** Constant for the default root element name. */
     private static final String DEFAULT_ROOT_NAME = "configuration";
 
+    /** Constant for the delimiter for multiple attribute values.*/
+    private static final char ATTR_VALUE_DELIMITER = '|';
+
     /** The document from this configuration's data source. */
     private Document document;
 
@@ -432,15 +463,10 @@
             if (w3cNode instanceof Attr)
             {
                 Attr attr = (Attr) w3cNode;
-                Iterator it;
-                if (isDelimiterParsingDisabled())
-                {
-                    it = new SingletonIterator(attr.getValue());
-                }
-                else
-                {
-                    it = PropertyConverter.split(attr.getValue(), getListDelimiter()).iterator();
-                }
+                Iterator it = PropertyConverter.split(
+                        attr.getValue(),
+                        isDelimiterParsingDisabled() ? ATTR_VALUE_DELIMITER
+                                : getListDelimiter()).iterator();
                 while (it.hasNext())
                 {
                     Node child = new XMLNode(attr.getName(),
@@ -570,7 +596,8 @@
                 document = newDocument;
             }
 
-            XMLBuilderVisitor builder = new XMLBuilderVisitor(document, getListDelimiter());
+            XMLBuilderVisitor builder = new XMLBuilderVisitor(document,
+                    isDelimiterParsingDisabled() ? (char) 0 : getListDelimiter());
             builder.processDocument(getRoot());
             return document;
         } /* try */
@@ -966,8 +993,12 @@
                 Element elem = document.createElement(newNode.getName());
                 if (newNode.getValue() != null)
                 {
-                    elem.appendChild(document.createTextNode(
-                            PropertyConverter.escapeDelimiters(newNode.getValue().toString(), listDelimiter)));
+                    String txt = newNode.getValue().toString();
+                    if (listDelimiter != 0)
+                    {
+                        txt = PropertyConverter.escapeDelimiters(txt, listDelimiter);
+                    }
+                    elem.appendChild(document.createTextNode(txt));
                 }
                 if (sibling2 == null)
                 {
@@ -992,7 +1023,7 @@
          * @param node the affected node
          * @param elem the element that is associated with this node
          * @param name the name of the affected attribute
-         * @param listDelimiter the delimiter vor attributes with multiple values
+         * @param listDelimiter the delimiter for attributes with multiple values
          */
         private static void updateAttribute(Node node, Element elem, String name, char listDelimiter)
         {
@@ -1000,6 +1031,7 @@
             {
                 List attrs = node.getAttributes(name);
                 StringBuffer buf = new StringBuffer();
+                char delimiter = (listDelimiter != 0) ? listDelimiter : ATTR_VALUE_DELIMITER;
                 for (Iterator it = attrs.iterator(); it.hasNext();)
                 {
                     Node attr = (Node) it.next();
@@ -1007,10 +1039,10 @@
                     {
                         if (buf.length() > 0)
                         {
-                            buf.append(listDelimiter);
+                            buf.append(delimiter);
                         }
                         buf.append(PropertyConverter.escapeDelimiters(attr
-                                .getValue().toString(), getDefaultListDelimiter()));
+                                .getValue().toString(), delimiter));
                     }
                     attr.setReference(elem);
                 }

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java?view=diff&rev=536326&r1=536325&r2=536326
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java Tue May  8 13:55:42 2007
@@ -1062,6 +1062,76 @@
     }
 
     /**
+     * Tests saving and loading a configuration when delimiter parsing is
+     * disabled.
+     */
+    public void testSaveDelimiterParsingDisabled()
+            throws ConfigurationException
+    {
+        checkSaveDelimiterParsingDisabled("list.delimiter.test");
+    }
+
+    /**
+     * Tests saving and loading a configuration when delimiter parsing is
+     * disabled and attributes are involved.
+     */
+    public void testSaveDelimiterParsingDisabledAttrs()
+            throws ConfigurationException
+    {
+        checkSaveDelimiterParsingDisabled("list.delimiter.test[@attr]");
+    }
+
+    /**
+     * Helper method for testing saving and loading a configuration when
+     * delimiter parsing is disabled.
+     *
+     * @param key the key to be checked
+     * @throws ConfigurationException if an error occurs
+     */
+    private void checkSaveDelimiterParsingDisabled(String key)
+            throws ConfigurationException
+    {
+        conf.clear();
+        conf.setDelimiterParsingDisabled(true);
+        conf.load();
+        conf.setProperty(key, "C:\\Temp\\,C:\\Data\\");
+        conf.addProperty(key, "a,b,c");
+        conf.save(testSaveConf);
+        XMLConfiguration checkConf = new XMLConfiguration();
+        checkConf.setDelimiterParsingDisabled(true);
+        checkConf.setFile(testSaveConf);
+        checkSavedConfig(checkConf);
+    }
+
+    /**
+     * Tests multiple attribute values in delimiter parsing disabled mode.
+     */
+    public void testDelimiterParsingDisabledMultiAttrValues() throws ConfigurationException
+    {
+        conf.clear();
+        conf.setDelimiterParsingDisabled(true);
+        conf.load();
+        List expr = conf.getList("expressions[@value]");
+        assertEquals("Wrong list size", 2, expr.size());
+        assertEquals("Wrong element 1", "a || (b && c)", expr.get(0));
+        assertEquals("Wrong element 2", "!d", expr.get(1));
+    }
+
+    /**
+     * Tests using multiple attribute values, which are partly escaped when
+     * delimiter parsing is not disabled.
+     */
+    public void testMultipleAttrValuesEscaped() throws ConfigurationException
+    {
+        conf.addProperty("test.dir[@name]", "C:\\Temp\\");
+        conf.addProperty("test.dir[@name]", "C:\\Data\\");
+        conf.save(testSaveConf);
+        XMLConfiguration checkConf = new XMLConfiguration();
+        checkConf.setFile(testSaveConf);
+        checkSavedConfig(checkConf);
+    }
+
+    /**
      * Prepares a configuration object for testing a reload operation.
      *
      * @return the initialized configuration

Modified: jakarta/commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/xdocs/changes.xml?view=diff&rev=536326&r1=536325&r2=536326
==============================================================================
--- jakarta/commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Tue May  8 13:55:42 2007
@@ -23,6 +23,12 @@
 
   <body>
     <release version="1.5-SNAPSHOT" date="in SVN" description="">
+      <action dev="oheger" type="update" issue="CONFIGURATION-268">
+        When delimiter parsing was disabled for XMLConfiguration, saving and
+        loading the configuration accidently added escape characters to properties
+        containing the list delimiter character. This has been fixed. It is now
+        also possible to escape the escape character itself.
+      </action>
       <action dev="oheger" type="update" issue="CONFIGURATION-253">
         The return value of FileConfiguration.getFile() is now always
         consistent with the result of getURL().



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