JDK-6311448 : XML transformer failed to output surrorates pair.
  • Type: Bug
  • Component: xml
  • Sub-Component: javax.xml.parsers
  • Affected Version: 5.0u4
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_2.5.1
  • CPU: x86
  • Submitted: 2005-08-16
  • Updated: 2016-04-26
  • Resolved: 2006-12-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6 JDK 7
1.4.0 1.4Fixed 6u2Fixed 7Fixed
Description
OPERATING SYSTEM(S):
SLES9 SP1 with zh_CN.GB18030 locale
RHEL4 with zh_CN.GB18030 locale

FULL JDK VERSION(S):
$java -version
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode)

DESCRIPTION:
- Exact steps to reproduce
 1. Compile and run testcase "java PrefTest"
 2. Query saved name by issue "java PrefTest -q"
 3. Terminal print out the following message:
    WARNING: Invalid preferences format in $HOME/.java/.userPrefs/mynode/myKey/prefs.xml
    You name is NOT DEFINED.
    2005-8-5 2:42:58 java.util.prefs.FileSystemPreferences$7 run
    WARNING: Prefs file removed in background $HOME/.java/.userPrefs/mynode/myKey/prefs.xml

- Minimal source code that demonstrates the problem
/*
 * PrefTest.java
 * - A sample program for Preferences class
 */
import java.util.prefs.*;
import java.awt.event.*;
public class PrefTest {
    static private String ourNodeName = "/mynode/myKey";
    static private String key = "myName";
    
    static void setName(String name) {
        Preferences prefs = Preferences.userRoot().node(ourNodeName);
        
        prefs.put(key, name);
    }
    
    static void getName() {
        Preferences prefs = Preferences.userRoot().node(ourNodeName);
        
        String myName = prefs.get(key, "");
        if (myName.equals("")) {
            System.out.println("You name is NOT DEFINED.");
        } else {
            System.out.println("Your name is " + myName + ".");
        }
    }
    
    static void removeName() {
        Preferences prefs = Preferences.userRoot().node(ourNodeName);
        
        prefs.remove(key);
    }
    
    public static void main(String[] args) {
        if (args.length > 0) {
	        if (args[0].equals("-q")) {
	            PrefTest.getName();
	        } else if (args[0].equals("-r")) {
	            PrefTest.removeName();
	        }
	    } else {
	        PrefTest.setName("\ud840\udc00");
	    }
    }
    
}

- Exact text of any error messages
WARNING: Invalid preferences format in $HOME/.java/.userPrefs/mynode/myKey/prefs.xml
    You name is NOT DEFINED.
    2005-8-5 2:42:58 java.util.prefs.FileSystemPreferences$7 run
    WARNING: Prefs file removed in background $HOME/.java/.userPrefs/mynode/myKey/prefs.xml

Comments
EVALUATION Proposed fix is correct. The fix has now been integrated into JAXP 1.4 RI (will be part of weekly build available from Java.net).
12-12-2006

EVALUATION src/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.writeAttrString() deos not write out surrogates correctly. accumDefaultEscape()returns i+2 if a pair of surrogates have been written out successfully, but iteration loop in writeAttrString always step 1, the result is the low-half of the surrogates is always being incorrectly attached for each pair of surrogates output. attached is the test case. String attrKey = "key"; String attrValue = "\ud800\udc00"; Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder() .getDOMImplementation() .createDocument(null, null, null); Element xmlRoot = doc.createElement("root"); xmlRoot.setAttribute(attrKey, attrValue); doc.appendChild(xmlRoot); Transformer t = TransformerFactory.newInstance() .newTransformer(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( new FileOutputStream("foo.xml"), "UTF-8")); t.transform(new DOMSource(doc), new StreamResult(bw)); bw.close();
07-12-2006

SUGGESTED FIX *** /tmp/geta27253 Wed Dec 6 15:46:51 2006 --- ToStream.java Wed Dec 6 15:45:53 2006 *************** *** 1642,1648 **** { int pos = accumDefaultEntity(writer, ch, i, chars, len, fromTextNode, escLF); - if (i == pos) { if (Encodings.isHighUTF16Surrogate(ch)) --- 1642,1647 ---- *************** *** 1967,1978 **** string.getChars(0,len, m_attrBuff, 0); final char[] stringChars = m_attrBuff; ! for (int i = 0; i < len; i++) { char ch = stringChars[i]; if (escapingNotNeeded(ch) && (!m_charInfo.isSpecialAttrChar(ch))) { writer.write(ch); } else { // I guess the parser doesn't normalize cr/lf in attributes. -sb --- 1966,1980 ---- string.getChars(0,len, m_attrBuff, 0); final char[] stringChars = m_attrBuff; ! int i = 0; ! while (i < len) ! // for (int i = 0; i < len; i++) { char ch = stringChars[i]; if (escapingNotNeeded(ch) && (!m_charInfo.isSpecialAttrChar(ch))) { writer.write(ch); + i++; } else { // I guess the parser doesn't normalize cr/lf in attributes. -sb *************** *** 1984,1990 **** // ch = CharInfo.S_LINEFEED; // } ! accumDefaultEscape(writer, ch, i, stringChars, len, false, true); } } --- 1986,1992 ---- // ch = CharInfo.S_LINEFEED; // } ! i = accumDefaultEscape(writer, ch, i, stringChars, len, false, true); } }
07-12-2006