--- old/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java 2014-07-22 15:46:12.000000000 +0400 +++ new/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java 2014-07-22 15:46:11.000000000 +0400 @@ -74,13 +74,6 @@ private static final Object FLAVOR_MAP_KEY = new Object(); /** - * Copied from java.util.Properties. - */ - private static final String keyValueSeparators = "=: \t\r\n\f"; - private static final String strictKeyValueSeparators = "=:"; - private static final String whiteSpaceChars = " \t\r\n\f"; - - /** * The list of valid, decoded text flavor representation classes, in order * from best to worst. */ @@ -238,10 +231,11 @@ line = line.substring(0, line.length() - 1) + reader.readLine().trim(); } int delimiterPosition = line.indexOf('='); - String key = line.substring(0, delimiterPosition).replace("\\ ", " "); + String key = line.substring(0, delimiterPosition).replaceAll("\\ ", " "); String[] values = line.substring(delimiterPosition + 1, line.length()).split(","); for (String value : values) { try { + value = loadConvert(value); MimeType mime = new MimeType(value); if ("text".equals(mime.getPrimaryType())) { String charset = mime.getParameter("charset"); @@ -305,6 +299,62 @@ } } + private static String loadConvert(String theString) { + char aChar; + int len = theString.length(); + StringBuilder outBuffer = new StringBuilder(len); + + for (int x = 0; x < len; ) { + aChar = theString.charAt(x++); + if (aChar == '\\') { + aChar = theString.charAt(x++); + if (aChar == 'u') { + // Read the xxxx + int value = 0; + for (int i = 0; i < 4; i++) { + aChar = theString.charAt(x++); + switch (aChar) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + value = (value << 4) + aChar - '0'; + break; + } + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': { + value = (value << 4) + 10 + aChar - 'a'; + break; + } + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': { + value = (value << 4) + 10 + aChar - 'A'; + break; + } + default: { + throw new IllegalArgumentException( + "Malformed \\uxxxx encoding."); + } + } + } + outBuffer.append((char)value); + } else { + if (aChar == 't') { + aChar = '\t'; + } else if (aChar == 'r') { + aChar = '\r'; + } else if (aChar == 'n') { + aChar = '\n'; + } else if (aChar == 'f') { + aChar = '\f'; + } + outBuffer.append(aChar); + } + } else { + outBuffer.append(aChar); + } + } + return outBuffer.toString(); + } + /** * Stores the listed object under the specified hash key in map. Unlike a * standard map, the listed object will not replace any object already at --- /dev/null 2014-07-22 15:46:13.000000000 +0400 +++ new/test/java/awt/datatransfer/UnicodeTransferTest/UnicodeTransferTest.java 2014-07-22 15:46:13.000000000 +0400 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 4718897 + @summary tests that a Unicode string can be transferred between JVMs. + @author das@sparc.spb.su area=datatransfer + @library ../../regtesthelpers/process + @build ProcessResults ProcessCommunicator + @run main UnicodeTransferTest +*/ + +import java.awt.datatransfer.*; +import java.awt.*; +import java.text.Normalizer; + +import test.java.awt.regtesthelpers.process.ProcessResults; +import test.java.awt.regtesthelpers.process.ProcessCommunicator; + +public class UnicodeTransferTest { + private static final Toolkit tk = Toolkit.getDefaultToolkit(); + private static final Clipboard clipboard = tk.getSystemClipboard(); + private static final Transferable t = new StringSelection(Util.getTestString()); + + public static void main(String[] args) throws Exception { + Util.setClipboardContents(clipboard, t, null); + ProcessResults result = ProcessCommunicator.executeChildProcess( + UnicodeTransferTestChild.class, new String[0]); + verifyTestResults(result); + } + + private static void verifyTestResults(ProcessResults processResults) { + if (processResults.getExitValue() != 0) { + processResults.printProcessErrorOutput(System.err); + throw new RuntimeException("TEST IS FAILED. See child stderr"); + } + processResults.verifyStdErr(System.err); + processResults.verifyProcessExitValue(System.err); + processResults.printProcessStandartOutput(System.out); + } + +} + +class Util { + private static String testString = null; + + static { + StringBuilder buf = new StringBuilder(); + for (int i = 1; i < 0x10000; i++) { + // Skip surrogates. + if (i < 0xD800 || (i > 0xDFFF && i < 0xFFF0)) { + buf.append((char) i); + } else { + buf.append(0x20); + } + } + // On OS X the unicode string is normalized but the clipboard, + // so we need to use normalized strings as well to be able to + // check the result + testString = Normalizer.normalize(buf.toString(), Normalizer.Form.NFC); + } + + public static String getTestString() { + return testString; + } + + public static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + + boolean set = false; + while (!set) { + try { + cb.setContents(contents, owner); + set = true; + } catch (IllegalStateException ise) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public static Transferable getClipboardContents(Clipboard cb, + Object requestor) { + while (true) { + try { + return cb.getContents(requestor); + } catch (IllegalStateException ise) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } +} + +class UnicodeTransferTestChild { + private static final Toolkit tk = Toolkit.getDefaultToolkit(); + private static final Clipboard clipboard = tk.getSystemClipboard(); + + public static void main(String[] args) { + Transferable t = Util.getClipboardContents(clipboard, null); + + if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) { + Object o = null; + try { + o = t.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + e.printStackTrace(); + } + String testStr = Util.getTestString(); + + if (!testStr.equals(o)) { + if (o instanceof String) { + String s = (String)o; + if (s.length() != testStr.length()) { + System.err.println("Received length:" + s.length() + + " Expected length: " + + testStr.length()); + } else { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + char expected = testStr.charAt(i); + if (ch != expected) { + System.err.println("i=" + i + + " char=" + + Integer.toHexString((int)ch) + + " expected=" + + Integer.toHexString(expected)); + } + } + } + } else { + System.err.println("Received object:" + o); + } + throw new RuntimeException("String doesn't match."); + } + } else { + throw new RuntimeException("Clipboard content was not set"); + } + } +}