Thanks, Mark. The changes have already been made. On Wed, Jul 7, 2010 at 3:15 PM, Mark Hindess <mark.hind...@googlemail.com>wrote:
> > Kevin, > > During the merge to java6 I did a --record-only merge (which just > updates the metadata to say that it is complete but changes nothing) > for this commit on the assumption that the changes were already made in > r958904. If that is not correct - i.e. there is work missing - then please > make a commit with the missing changes. > > Thanks, > Mark. > > > In message <20100629101401.7f8272388...@eris.apache.org>, > zhouke...@apache.org > writes: > > > > Author: zhoukevin > > Date: Tue Jun 29 10:14:01 2010 > > New Revision: 958912 > > > > URL: http://svn.apache.org/viewvc?rev=958912&view=rev > > Log: > > As to java.util.Properties.store(os, comments) method, if the comments > argume > > nt 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. An > > y '\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 > cha > > racter ! then an ASCII # is written out after that line separator. > > This patch fixes the above issue. In addition, it includes several test > cases > > for coverage. > > > > Modified: > > > harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/java/util > > /Properties.java > > > harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org > > /apache/harmony/luni/tests/java/util/PropertiesTest.java > > > > Modified: > harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/jav > > a/util/Properties.java > > URL: > http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/module > > > s/luni/src/main/java/java/util/Properties.java?rev=958912&r1=958911&r2=958912 > > &view=diff > > > ============================================================================= > > = > > --- > harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/java/util > > /Properties.java (original) > > +++ > harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/java/util > > /Properties.java Tue Jun 29 10:14:01 2010 > > @@ -25,6 +25,7 @@ import java.io.OutputStreamWriter; > > import java.io.PrintStream; > > import java.io.PrintWriter; > > import java.io.StringReader; > > +import java.io.Writer; > > import java.nio.charset.Charset; > > import java.nio.charset.IllegalCharsetNameException; > > import java.nio.charset.UnsupportedCharsetException; > > @@ -97,15 +98,15 @@ 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 > isK > > ey) { > > + 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$ > > @@ -120,23 +121,33 @@ 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$ > > - } > > - buffer.append(hex); > > + buffer.append(toHexaDecimal(ch)); > > } > > } > > } > > } > > > > + 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 > > @@ -412,7 +423,7 @@ public class Properties extends Hashtabl > > } > > break; > > } > > - if (Character.isWhitespace(nextChar)) { > > + if (nextChar < 256 && Character.isWhitespace(nextChar)) > { > > if (mode == CONTINUE) { > > mode = IGNORE; > > } > > @@ -504,36 +515,36 @@ public class Properties extends Hashtabl > > private static String lineSeparator; > > > > /** > > - * Stores the mappings in this {...@code Properties} to the specified > {...@cod > > e > > - * OutputStream}, putting the specified comment at the beginning. > The ou > > tput > > - * from this method is suitable for being read by the > > + * Stores the mappings in this {...@code Properties} to the specified > > + * {...@code OutputStream}, putting the specified comment at the > beginning. > > The > > + * output from this method is suitable for being read by the > > * {...@link #load(InputStream)} method. > > * > > - * @param out the {...@code OutputStream} to write to. > > - * @param comment the comment to put at the beginning. > > - * @throws IOException if an error occurs during the write to the > {...@code > > - * OutputStream}. > > - * @throws ClassCastException if the key or value of a mapping is > not a > > - * {...@code String}. > > + * @param out > > + * the {...@code OutputStream} to write to. > > + * @param comments > > + * the comments to put at the beginning. > > + * @throws IOException > > + * if an error occurs during the write to the > > + * {...@code OutputStream}. > > + * @throws ClassCastException > > + * if the key or value of a mapping is not a {...@code > String}. > > */ > > - public synchronized void store(OutputStream out, String comment) > > + 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 (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); > > > > + StringBuilder buffer = new StringBuilder(200); > > for (Map.Entry<Object, Object> entry : entrySet()) { > > String key = (String) entry.getKey(); > > dumpString(buffer, key, true); > > @@ -546,6 +557,32 @@ 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] == '\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]); > > + } > > + } > > + 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/trunk/classlib/modules/luni/src/test/api/comm > > on/org/apache/harmony/luni/tests/java/util/PropertiesTest.java > > URL: > http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/module > > > s/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/Properties > > Test.java?rev=958912&r1=958911&r2=958912&view=diff > > > ============================================================================= > > = > > --- > harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org > > /apache/harmony/luni/tests/java/util/PropertiesTest.java (original) > > +++ > harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org > > /apache/harmony/luni/tests/java/util/PropertiesTest.java Tue Jun 29 > 10:14:01 > > 2010 > > @@ -17,10 +17,12 @@ > > > > package org.apache.harmony.luni.tests.java.util; > > > > +import java.io.BufferedReader; > > import java.io.ByteArrayInputStream; > > import java.io.ByteArrayOutputStream; > > import java.io.IOException; > > import java.io.InputStream; > > +import java.io.InputStreamReader; > > import java.io.PrintStream; > > import java.io.PrintWriter; > > import java.util.Enumeration; > > @@ -541,6 +543,131 @@ public class PropertiesTest extends juni > > assertEquals(1, props.size()); > > } > > > > + 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(); > > + } > > + > > /** > > * Sets up the fixture, for example, open a network connection. This > met > > hod > > * is called before a test is executed. > > > > > -- Best regards, Yours, Kevin Zhou