[FELIX-5156] Felix Properties doesn't handle multi value properties correctly

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1723557 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/utils/src/main/java/org/apache/felix/utils/properties/Properties.java b/utils/src/main/java/org/apache/felix/utils/properties/Properties.java
index 41455f9..aef4212 100644
--- a/utils/src/main/java/org/apache/felix/utils/properties/Properties.java
+++ b/utils/src/main/java/org/apache/felix/utils/properties/Properties.java
@@ -27,6 +27,7 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Reader;
+import java.io.StringReader;
 import java.io.Writer;
 import java.net.URL;
 import java.security.AccessController;
@@ -284,21 +285,32 @@
         commentLines = new ArrayList<String>(commentLines);
         valueLines = new ArrayList<String>(valueLines);
         String escapedKey = escapeKey(key);
+        StringBuilder sb = new StringBuilder();
         int lastLine = valueLines.size() - 1;
         if (valueLines.isEmpty()) {
             valueLines.add(escapedKey + "=");
-        } else if (!valueLines.get(0).trim().startsWith(escapedKey)) {
-            valueLines.set(0, escapedKey + " = " + escapeJava(valueLines.get(0)) + (0 < lastLine? "\\": ""));
+            sb.append(escapedKey).append("=");
+        } else {
+            String val0 = valueLines.get(0);
+            if (!val0.trim().startsWith(escapedKey)) {
+                valueLines.set(0, escapedKey + " = " + escapeJava(val0) /*+ (0 < lastLine? "\\": "")*/);
+                sb.append(escapedKey).append(" = ").append(escapeJava(val0));
+            } else {
+                valueLines.set(0, escapeJava(val0) /*+ (0 < lastLine? "\\": "")*/);
+                sb.append(escapeJava(val0));
+            }
         }
         for (int i = 1; i < valueLines.size(); i++) {
-            valueLines.set(i, escapeJava(valueLines.get(i)) + (i < lastLine? "\\": ""));
+            String val = valueLines.get(i);
+            valueLines.set(i, escapeJava(val) /*+ (i < lastLine? "\\": "")*/);
+            while (!val.isEmpty() && Character.isWhitespace(val.charAt(0))) {
+                val = val.substring(1);
+            }
+            sb.append(val);
         }
-        StringBuilder value = new StringBuilder();
-        for (String line: valueLines) {
-            value.append(line);
-        }
+        String[] property = PropertiesReader.parseProperty(sb.toString());
         this.layout.put(key, new Layout(commentLines, valueLines));
-        return storage.put(key, unescapeJava(value.toString()));
+        return storage.put(key, property[1]);
     }
 
     public String put(String key, List<String> commentLines, String value) {
@@ -470,9 +482,17 @@
             }
             if (l != null && l.getValueLines() != null)
             {
-                for (String s : l.getValueLines())
+                for (int i = 0; i < l.getValueLines().size(); i++)
                 {
-                    writer.writeln(s);
+                    String s = l.getValueLines().get(i);
+                    if (i < l.getValueLines().size() - 1)
+                    {
+                        writer.writeln(s + "\\");
+                    }
+                    else
+                    {
+                        writer.writeln(s);
+                    }
                 }
             }
             else
@@ -838,20 +858,19 @@
                     continue;
                 }
 
+                boolean combine = checkCombineLines(line);
+                if (combine)
+                {
+                    line = line.substring(0, line.length() - 1);
+                }
                 valueLines.add(line);
                 while (line.length() > 0 && contains(WHITE_SPACE, line.charAt(0)))
                 {
                     line = line.substring(1, line.length());
                 }
-
-                if (checkCombineLines(line))
+                buffer.append(line);
+                if (!combine)
                 {
-                    line = line.substring(0, line.length() - 1);
-                    buffer.append(line);
-                }
-                else
-                {
-                    buffer.append(line);
                     break;
                 }
             }
diff --git a/utils/src/test/java/org/apache/felix/utils/properties/PropertiesTest.java b/utils/src/test/java/org/apache/felix/utils/properties/PropertiesTest.java
index a52e667..782993e 100644
--- a/utils/src/test/java/org/apache/felix/utils/properties/PropertiesTest.java
+++ b/utils/src/test/java/org/apache/felix/utils/properties/PropertiesTest.java
@@ -22,6 +22,7 @@
 import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -237,7 +238,7 @@
         assertTrue(sw.toString(), sw.toString().endsWith(RESULT3));
         List<String> rawValue = properties.getRaw(KEY1);
         assertEquals(2, rawValue.size());
-        assertEquals(KEY1A + " = " + VALUE1 + "\\", rawValue.get(0));
+        assertEquals(KEY1A + " = " + VALUE1, rawValue.get(0));
         assertEquals(VALUE1, rawValue.get(1));
     }
 
@@ -263,4 +264,56 @@
         assertEquals(VALUE1 + "x", properties.get(KEY1));
     }
 
+    public void testMultiValueEscaping() throws IOException {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        pw.println("fruits                           apple, banana, pear, \\");
+        pw.println("                                 cantaloupe, watermelon, \\");
+        pw.println("                                 kiwi, mango");
+
+        java.util.Properties p = new java.util.Properties();
+        p.load(new StringReader(sw.toString()));
+        assertEquals("apple, banana, pear, cantaloupe, watermelon, kiwi, mango", p.getProperty("fruits"));
+
+        Properties props = new Properties();
+        props.load(new StringReader(sw.toString()));
+        assertEquals("apple, banana, pear, cantaloupe, watermelon, kiwi, mango", props.getProperty("fruits"));
+        List<String> raw = props.getRaw("fruits");
+        assertNotNull(raw);
+        assertEquals(3, raw.size());
+        assertEquals("fruits                           apple, banana, pear, ", raw.get(0));
+
+        props = new Properties();
+        props.put("fruits", props.getComments("fruits"), Arrays.asList(
+                "fruits                           apple, banana, pear, ",
+                "                                 cantaloupe, watermelon, ",
+                "                                 kiwi, mango"));
+        assertEquals("apple, banana, pear, cantaloupe, watermelon, kiwi, mango", props.getProperty("fruits"));
+        raw = props.getRaw("fruits");
+        assertNotNull(raw);
+        assertEquals(3, raw.size());
+        assertEquals("fruits                           apple, banana, pear, ", raw.get(0));
+
+        sw = new StringWriter();
+        props.save(sw);
+        props = new Properties();
+        props.load(new StringReader(sw.toString()));
+        assertEquals("apple, banana, pear, cantaloupe, watermelon, kiwi, mango", props.getProperty("fruits"));
+        raw = props.getRaw("fruits");
+        assertNotNull(raw);
+        assertEquals(3, raw.size());
+        assertEquals("fruits                           apple, banana, pear, ", raw.get(0));
+
+        props = new Properties();
+        props.put("fruits", props.getComments("fruits"), Arrays.asList(
+                "                           apple, banana, pear, ",
+                "                                 cantaloupe, watermelon, ",
+                "                                 kiwi, mango"));
+        assertEquals("apple, banana, pear, cantaloupe, watermelon, kiwi, mango", props.getProperty("fruits"));
+        raw = props.getRaw("fruits");
+        assertNotNull(raw);
+        assertEquals(3, raw.size());
+        assertEquals("fruits =                            apple, banana, pear, ", raw.get(0));
+    }
+
 }