You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/08/24 12:50:58 UTC

cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections ExtendedProperties.java

scolebourne    2003/08/24 03:50:58

  Modified:    collections/src/test/org/apache/commons/collections
                        TestExtendedProperties.java
               collections/src/java/org/apache/commons/collections
                        ExtendedProperties.java
  Log:
  Fix escaping behaviour of save method
  bug 19061, from Mohan Kishore, reported by Dariusz Wojtas
  
  Revision  Changes    Path
  1.5       +75 -8     jakarta-commons/collections/src/test/org/apache/commons/collections/TestExtendedProperties.java
  
  Index: TestExtendedProperties.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/TestExtendedProperties.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TestExtendedProperties.java	21 Sep 2001 03:15:15 -0000	1.4
  +++ TestExtendedProperties.java	24 Aug 2003 10:50:58 -0000	1.5
  @@ -7,7 +7,7 @@
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  + * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -65,12 +65,15 @@
   import junit.framework.TestCase;
   import junit.framework.TestSuite;
   
  +import java.io.*;
  +
   /**
  - *   Tests some basic functions of the ExtendedProperties
  - *   class
  + * Tests some basic functions of the ExtendedProperties
  + * class
    * 
  - *   @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  - *   @version $Id$
  + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  + * @author Mohan Kishore
  + * @version $Id$
    */
   public class TestExtendedProperties extends TestCase
   {
  @@ -151,5 +154,69 @@
           eprop.setProperty("db", "${applicationRoot}/db/hypersonic");
           String dbProp = "/home/applicationRoot/db/hypersonic";
           assertTrue("Checking interpolated variable", eprop.getString("db").equals(dbProp));
  +    }
  +    
  +    public void testSaveAndLoad() {
  +        ExtendedProperties ep1 = new ExtendedProperties();
  +        ExtendedProperties ep2 = new ExtendedProperties();
  +
  +        try {
  +            /* initialize value:
  +            one=Hello\World
  +            two=Hello\,World
  +            three=Hello,World
  +            */
  +            String s1 = "one=Hello\\World\ntwo=Hello\\,World\nthree=Hello,World";
  +            byte[] bytes = s1.getBytes();
  +            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  +            ep1.load(bais);
  +            assertEquals("Back-slashes not interpreted properly", 
  +                    "Hello\\World", ep1.getString("one"));
  +            assertEquals("Escaped commas not interpreted properly", 
  +                    "Hello,World", ep1.getString("two"));
  +            assertEquals("Commas not interpreted properly", 
  +                    2, ep1.getVector("three").size());
  +            assertEquals("Commas not interpreted properly", 
  +                    "Hello", ep1.getVector("three").get(0));
  +            assertEquals("Commas not interpreted properly", 
  +                    "World", ep1.getVector("three").get(1));
  +                    
  +            ByteArrayOutputStream baos = new ByteArrayOutputStream();
  +            ep1.save(baos, null);
  +            bytes = baos.toByteArray();
  +            bais = new ByteArrayInputStream(bytes);
  +            ep2.load(bais);
  +            assertEquals("Back-slash not same after being saved and loaded",
  +                    ep1.getString("one"), ep2.getString("one"));
  +            assertEquals("Escaped comma not same after being saved and loaded",
  +                    ep1.getString("two"), ep2.getString("two"));
  +            assertEquals("Comma not same after being saved and loaded",
  +                    ep1.getString("three"), ep2.getString("three"));
  +        } catch (IOException ioe) {
  +            fail("There was an exception saving and loading the EP");
  +        }
  +    }
  +    
  +    public void testTrailingBackSlash() {
  +        ExtendedProperties ep1 = new ExtendedProperties();
  +
  +        try {
  +            /*
  +            initialize using:
  +            one=ONE
  +            two=TWO \\
  +            three=THREE
  +            */
  +            String s1 = "one=ONE\ntwo=TWO \\\\\nthree=THREE";
  +            byte[] bytes = s1.getBytes();
  +            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  +            ep1.load(bais);
  +            assertEquals("Trailing back-slashes not interpreted properly", 
  +                    3, ep1.size());
  +            assertEquals("Back-slash not escaped properly", 
  +                    "TWO \\", ep1.getString("two"));
  +        } catch (IOException ioe) {
  +            fail("There was an exception loading the EP");
  +        }
       }
   }
  
  
  
  1.13      +65 -8     jakarta-commons/collections/src/java/org/apache/commons/collections/ExtendedProperties.java
  
  Index: ExtendedProperties.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/ExtendedProperties.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ExtendedProperties.java	20 Jun 2003 07:59:59 -0000	1.12
  +++ ExtendedProperties.java	24 Aug 2003 10:50:58 -0000	1.13
  @@ -103,6 +103,9 @@
    *   the comma.
    *  </li>
    *  <li>
  + *   Backslashes are escaped by using two consecutive backslashes i.e. \\
  + *  </li>
  + *  <li>
    *   If a <i>key</i> is used more than once, the values are appended
    *   like if they were on the same line separated with commas.
    *  </li>
  @@ -170,6 +173,7 @@
    * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
    * @author <a href="mailto:ipriha@surfeu.fi">Ilkka Priha</a>
    * @author Janek Bogucki
  + * @author Mohan Kishore
    */
   public class ExtendedProperties extends Hashtable {
       
  @@ -248,6 +252,57 @@
           
           return result.toString();
       }
  +    
  +    /**
  +     * Inserts a backslash before every comma and backslash. 
  +     */
  +    private static String escape(String s) {
  +        StringBuffer buf = new StringBuffer(s);
  +        for (int i=0; i < buf.length();i++) {
  +            char c = buf.charAt(i);
  +            if (c == ',' || c == '\\') {
  +                buf.insert(i, '\\');
  +                i++;
  +            }
  +        }
  +        return buf.toString();
  +    }
  +    
  +    /**
  +     * Removes a backslash from every pair of backslashes. 
  +     */
  +    private static String unescape(String s) {
  +        StringBuffer buf = new StringBuffer(s);
  +        for (int i=0; i < buf.length()-1;i++) {
  +            char c1 = buf.charAt(i);
  +            char c2 = buf.charAt(i+1);
  +            if (c1 == '\\' && c2 == '\\') {
  +                buf.deleteCharAt(i);
  +            }
  +        }
  +        return buf.toString();
  +    }
  +    
  +    /**
  +     * Counts the number of successive times 'ch' appears in the
  +     * 'line' before the position indicated by the 'index'.
  +     */
  +    private static int countPreceding(String line, int index, char ch) {
  +        int i;
  +        for (i = index-1; i >= 0; i--) {
  +            if (line.charAt(i) != ch) break;
  +        }
  +        return index-1-i;
  +    }
  +    
  +    /**
  +     * Checks if the line ends with odd number of backslashes 
  +     */
  +    private static boolean endsWithSlash(String line) {
  +        if (!line.endsWith("\\")) return false;
  +
  +        return (countPreceding(line, line.length()-1, '\\') % 2 == 0);
  +    }
   
       /**
        * This class is used to read properties lines.  These lines do
  @@ -284,7 +339,7 @@
                       String line = readLine().trim();
                       if ((line.length() != 0) && (line.charAt(0) != '#'))
                       {
  -                        if (line.endsWith("\\"))
  +                        if (endsWithSlash(line))
                           {
                               line = line.substring(0, line.length() - 1);
                               buffer.append(line);
  @@ -350,7 +405,7 @@
               while (hasMoreTokens())
               {
                   String token = super.nextToken();
  -                if (token.endsWith("\\"))
  +                if (endsWithSlash(token))
                   {
                       buffer.append(token.substring(0, token.length() - 1));
                       buffer.append(DELIMITER);
  @@ -678,7 +733,7 @@
                        * just goes in rather than risking vectorization
                        * if it contains an escaped comma
                        */
  -                    addStringProperty(key,value);
  +                    addStringProperty(key,unescape(value));
                   }
               }
               else
  @@ -692,7 +747,9 @@
                    * to perform operations with configuration
                    * in a definite order it will be possible.
                    */
  -
  +                if (token instanceof String) {
  +                    token = unescape((String)token);
  +                }
                   addPropertyDirect( key, token );
               }                
           }
  @@ -821,7 +878,7 @@
                           StringBuffer currentOutput = new StringBuffer();
                           currentOutput.append(key);
                           currentOutput.append("=");
  -                        currentOutput.append((String) value);
  +                        currentOutput.append(escape((String) value));
                           theWrtr.println(currentOutput.toString());
                       }
                       else if(value instanceof Vector)
  @@ -835,7 +892,7 @@
                               StringBuffer currentOutput = new StringBuffer();
                               currentOutput.append(key);
                               currentOutput.append("=");
  -                            currentOutput.append(currentElement);
  +                            currentOutput.append(escape(currentElement));
                               theWrtr.println(currentOutput.toString());
                           }
                       }