harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zhouke...@apache.org
Subject svn commit: r958904 - in /harmony/enhanced/java/branches/java6/classlib/modules/luni/src: main/java/java/util/Properties.java test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java
Date Tue, 29 Jun 2010 09:42:20 GMT
Author: zhoukevin
Date: Tue Jun 29 09:42:20 2010
New Revision: 958904

URL: http://svn.apache.org/viewvc?rev=958904&view=rev
Log:
As to java.util.Properties.store(os, comments) method, if the comments argument is not null,
then '#' character and a line separator are first written to the output stream. Thus, the
comments can serve as an identifying comment. Any '\n', '\r' or "\r\n" in comments is replaced
by a line separator generated by the Writer and if the next character in comments is not character
# or character ! then an ASCII # is written out after that line separator.
As to java.util.Properties.load(Reader) method, if there is a non-ASCII space character like
Japanese character, we should not remove it.

This patch fixes the above 2 issues. In addition, it includes several test cases for coverage.

Modified:
    harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/java/java/util/Properties.java
    harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java

Modified: harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/java/java/util/Properties.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/java/java/util/Properties.java?rev=958904&r1=958903&r2=958904&view=diff
==============================================================================
--- harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/java/java/util/Properties.java
(original)
+++ harmony/enhanced/java/branches/java6/classlib/modules/luni/src/main/java/java/util/Properties.java
Tue Jun 29 09:42:20 2010
@@ -17,8 +17,8 @@
 
 package java.util;
 
-import java.io.BufferedReader;
 import java.io.BufferedInputStream;
+import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -101,15 +101,16 @@ public class Properties extends Hashtabl
         defaults = properties;
     }
 
-    private void dumpString(StringBuilder buffer, String string, boolean key) {
-        int i = 0;
-        if (!key && i < string.length() && string.charAt(i) == ' ') {
+    private void dumpString(StringBuilder buffer, String string, boolean isKey,
+            boolean toHexaDecimal) {
+        int index = 0, length = string.length();
+        if (!isKey && index < length && string.charAt(index) == ' ') {
             buffer.append("\\ "); //$NON-NLS-1$
-            i++;
+            index++;
         }
 
-        for (; i < string.length(); i++) {
-            char ch = string.charAt(i);
+        for (; index < length; index++) {
+            char ch = string.charAt(index);
             switch (ch) {
             case '\t':
                 buffer.append("\\t"); //$NON-NLS-1$
@@ -124,23 +125,37 @@ public class Properties extends Hashtabl
                 buffer.append("\\r"); //$NON-NLS-1$
                 break;
             default:
-                if ("\\#!=:".indexOf(ch) >= 0 || (key && ch == ' ')) {
+                if ("\\#!=:".indexOf(ch) >= 0 || (isKey && ch == ' ')) {
                     buffer.append('\\');
                 }
                 if (ch >= ' ' && ch <= '~') {
                     buffer.append(ch);
                 } else {
-                    String hex = Integer.toHexString(ch);
-                    buffer.append("\\u"); //$NON-NLS-1$
-                    for (int j = 0; j < 4 - hex.length(); j++) {
-                        buffer.append("0"); //$NON-NLS-1$
+                    if (toHexaDecimal) {
+                        buffer.append(toHexaDecimal(ch));
+                    } else {
+                        buffer.append(ch);
                     }
-                    buffer.append(hex);
                 }
             }
         }
     }
 
+    private char[] toHexaDecimal(final int ch) {
+        char[] hexChars = { '\\', 'u', '0', '0', '0', '0' };
+        int hexChar, index = hexChars.length, copyOfCh = ch;
+        do {
+            hexChar = copyOfCh & 15;
+            if (hexChar > 9) {
+                hexChar = hexChar - 10 + 'A';
+            } else {
+                hexChar += '0';
+            }
+            hexChars[--index] = (char) hexChar;
+        } while ((copyOfCh >>>= 4) != 0);
+        return hexChars;
+    }
+
     /**
      * Searches for the property with the specified name. If the property is not
      * found, the default {@code Properties} are checked. If the property is not
@@ -446,7 +461,7 @@ public class Properties extends Hashtabl
                     }
                     break;
                 }
-                if (Character.isWhitespace(nextChar)) {
+                if (nextChar < 256 && Character.isWhitespace(nextChar)) {
                     if (mode == CONTINUE) {
                         mode = IGNORE;
                     }
@@ -581,50 +596,48 @@ public class Properties extends Hashtabl
 
     private static String lineSeparator;
 
-	/**
-	 * Stores the mappings in this Properties to the specified OutputStream,
-	 * putting the specified comment at the beginning. The output from this
-	 * method is suitable for being read by the load() method.
-	 * 
-	 * @param out
-	 *            the OutputStream
-	 * @param comment
-	 *            the comment
-	 * @throws IOException 
-	 * 
-	 * @exception ClassCastException
-	 *                when the key or value of a mapping is not a String
-	 */
-	public synchronized void store(OutputStream out, String comment)
-			throws IOException {
-		if (lineSeparator == null) {
-			lineSeparator = AccessController
-					.doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$
-        }
-
-		StringBuilder buffer = new StringBuilder(200);
-		OutputStreamWriter writer = new OutputStreamWriter(out, "ISO8859_1"); //$NON-NLS-1$
-		if (comment != null) {
-            writer.write("#"); //$NON-NLS-1$
-            writer.write(comment);
-			writer.write(lineSeparator); 
+    /**
+     * Stores the mappings in this Properties to the specified OutputStream,
+     * putting the specified comment at the beginning. The output from this
+     * method is suitable for being read by the load() method.
+     * 
+     * @param out
+     *            the OutputStream
+     * @param comments
+     *            the comments
+     * @throws IOException
+     * 
+     * @exception ClassCastException
+     *                when the key or value of a mapping is not a String
+     */
+    public synchronized void store(OutputStream out, String comments)
+            throws IOException {
+        if (lineSeparator == null) {
+            lineSeparator = AccessController
+                    .doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$
+        }
+
+        StringBuilder buffer = new StringBuilder(200);
+        OutputStreamWriter writer = new OutputStreamWriter(out, "ISO8859_1"); //$NON-NLS-1$
+        if (comments != null) {
+            writeComments(writer, comments);
         }
-        writer.write("#"); //$NON-NLS-1$
+        writer.write('#');
         writer.write(new Date().toString());
-        writer.write(lineSeparator); 
+        writer.write(lineSeparator);
+
+        for (Map.Entry<Object, Object> entry : entrySet()) {
+            String key = (String) entry.getKey();
+            dumpString(buffer, key, true, true);
+            buffer.append('=');
+            dumpString(buffer, (String) entry.getValue(), false, true);
+            buffer.append(lineSeparator);
+            writer.write(buffer.toString());
+            buffer.setLength(0);
+        }
+        writer.flush();
+    }
 
-		for (Map.Entry<Object, Object> entry : entrySet()) {
-			String key = (String) entry.getKey();
-			dumpString(buffer, key, true);
-			buffer.append('=');
-			dumpString(buffer, (String) entry.getValue(), false);
-			buffer.append(lineSeparator);
-			writer.write(buffer.toString());
-			buffer.setLength(0);
-		}
-		writer.flush();
-	}
-    
     /**
      * Stores the mappings in this Properties to the specified OutputStream,
      * putting the specified comment at the beginning. The output from this
@@ -632,32 +645,31 @@ public class Properties extends Hashtabl
      * 
      * @param writer
      *            the writer
-     * @param comment
-     *            the comment
-     * @throws IOException 
-     *            if any I/O exception occurs
-     * @since 1.6 
+     * @param comments
+     *            the comments
+     * @throws IOException
+     *             if any I/O exception occurs
+     * @since 1.6
      */
-    public synchronized void store(Writer writer, String comment) throws IOException {
+    public synchronized void store(Writer writer, String comments)
+            throws IOException {
         if (lineSeparator == null) {
             lineSeparator = AccessController
                     .doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$
         }
-        StringBuilder buffer = new StringBuilder(200);
-        if (comment != null) {
-            writer.write("#"); //$NON-NLS-1$
-            writer.write(comment);
-            writer.write(lineSeparator); 
+        if (comments != null) {
+            writeComments(writer, comments);
         }
-        writer.write("#"); //$NON-NLS-1$
+        writer.write('#');
         writer.write(new Date().toString());
-        writer.write(lineSeparator); 
+        writer.write(lineSeparator);
 
+        StringBuilder buffer = new StringBuilder(200);
         for (Map.Entry<Object, Object> entry : entrySet()) {
             String key = (String) entry.getKey();
-            dumpString(buffer, key, true);
+            dumpString(buffer, key, true, false);
             buffer.append('=');
-            dumpString(buffer, (String) entry.getValue(), false);
+            dumpString(buffer, (String) entry.getValue(), false, false);
             buffer.append(lineSeparator);
             writer.write(buffer.toString());
             buffer.setLength(0);
@@ -665,6 +677,36 @@ public class Properties extends Hashtabl
         writer.flush();
     }
 
+    private void writeComments(Writer writer, String comments)
+            throws IOException {
+        writer.write('#');
+        char[] chars = comments.toCharArray();
+        for (int index = 0; index < chars.length; index++) {
+            if (chars[index] < 256) {
+                if (chars[index] == '\r' || chars[index] == '\n') {
+                    int indexPlusOne = index + 1;
+                    if (chars[index] == '\r' && indexPlusOne < chars.length
+                            && chars[indexPlusOne] == '\n') {
+                        // "\r\n"
+                        continue;
+                    }
+                    writer.write(lineSeparator);
+                    if (indexPlusOne < chars.length
+                            && (chars[indexPlusOne] == '#' || chars[indexPlusOne]
== '!')) {
+                        // return char with either '#' or '!' afterward
+                        continue;
+                    }
+                    writer.write('#');
+                } else {
+                    writer.write(chars[index]);
+                }
+            } else {
+                writer.write(toHexaDecimal(chars[index]));
+            }
+        }
+        writer.write(lineSeparator);
+    }
+
     /**
      * Loads the properties from an {@code InputStream} containing the
      * properties in XML form. The XML document must begin with (and conform to)

Modified: harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java?rev=958904&r1=958903&r2=958904&view=diff
==============================================================================
--- harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java
(original)
+++ harmony/enhanced/java/branches/java6/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/PropertiesTest.java
Tue Jun 29 09:42:20 2010
@@ -17,6 +17,7 @@
 
 package org.apache.harmony.luni.tests.java.util;
 
+import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -1050,6 +1051,151 @@ public class PropertiesTest extends juni
         assertEquals("value", mockProperties.get("key"));
     }
 
+    private String comment1 = "comment1";
+
+    private String comment2 = "comment2";
+
+    private void validateOutput(String[] expectStrings, byte[] output)
+            throws IOException {
+        ByteArrayInputStream bais = new ByteArrayInputStream(output);
+        BufferedReader br = new BufferedReader(new InputStreamReader(bais,
+                "ISO8859_1"));
+        for (String expectString : expectStrings) {
+            assertEquals(expectString, br.readLine());
+        }
+        br.readLine();
+        assertNull(br.readLine());
+        br.close();
+    }
+
+    public void testStore_scenario0() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario1() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario2() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + '\n' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario3() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + '\r' + comment2);
+        validateOutput(new String[] { "#comment1", "#", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario4() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + '#' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario5() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + '!' + comment2);
+        validateOutput(new String[] { "#comment1", "!comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario6() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + '#' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario7() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + '!' + comment2);
+        validateOutput(new String[] { "#comment1", "!comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario8() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + '\n' + '#' + comment2);
+        validateOutput(new String[] { "#comment1", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario9() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + '\r' + '#' + comment2);
+        validateOutput(new String[] { "#comment1", "#", "#comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario10() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\r' + '\n' + '!' + comment2);
+        validateOutput(new String[] { "#comment1", "!comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testStore_scenario11() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Properties props = new Properties();
+        props.store(baos, comment1 + '\n' + '\r' + '!' + comment2);
+        validateOutput(new String[] { "#comment1", "#", "!comment2" },
+                baos.toByteArray());
+        baos.close();
+    }
+
+    public void testLoadReader() throws IOException {
+        InputStream inputStream = new ByteArrayInputStream(
+                "\u3000key=value".getBytes("UTF-8"));
+        Properties props = new Properties();
+        props.load(inputStream);
+        Enumeration<Object> keyEnum = props.keys();
+        assertFalse("\u3000key".equals(keyEnum.nextElement()));
+        assertFalse(keyEnum.hasMoreElements());
+        inputStream.close();
+
+        inputStream = new ByteArrayInputStream(
+                "\u3000key=value".getBytes("UTF-8"));
+        props = new Properties();
+        props.load(new InputStreamReader(inputStream, "UTF-8"));
+        keyEnum = props.keys();
+        assertEquals("\u3000key", keyEnum.nextElement());
+        assertFalse(keyEnum.hasMoreElements());
+        inputStream.close();
+    }
+
     /**
      * Sets up the fixture, for example, open a network connection. This method
      * is called before a test is executed.



Mime
View raw message