提交 fc6f83bc 编写于 作者: P pchelko

8038999: In Java 8 java.awt.datatransfer.DataFlavor.equals is no longer symmetric

Reviewed-by: anthony, serb
上级 fbdbc9ed
......@@ -25,13 +25,28 @@
package java.awt.datatransfer;
import java.io.*;
import java.nio.*;
import java.util.*;
import sun.awt.datatransfer.DataTransferer;
import sun.reflect.misc.ReflectUtil;
import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.OptionalDataException;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
/**
......@@ -501,7 +516,7 @@ public class DataFlavor implements Externalizable, Cloneable {
* @throws ClassNotFoundException
* @throws NullPointerException if <code>mimeType</code> is null
*
* @see tryToLoadClass
* @see #tryToLoadClass
*/
private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
if (mimeType == null) {
......@@ -990,15 +1005,9 @@ public class DataFlavor implements Externalizable, Cloneable {
return true;
}
if (representationClass == null) {
if (that.getRepresentationClass() != null) {
return false;
}
} else {
if (!representationClass.equals(that.getRepresentationClass())) {
if (!Objects.equals(this.getRepresentationClass(), that.getRepresentationClass())) {
return false;
}
}
if (mimeType == null) {
if (that.mimeType != null) {
......@@ -1010,34 +1019,22 @@ public class DataFlavor implements Externalizable, Cloneable {
}
if ("text".equals(getPrimaryType())) {
if (DataTransferer.doesSubtypeSupportCharset(this) &&
representationClass != null &&
!(isRepresentationClassReader() ||
String.class.equals(representationClass) ||
isRepresentationClassCharBuffer() ||
char[].class.equals(representationClass)))
{
if (DataTransferer.doesSubtypeSupportCharset(this)
&& representationClass != null
&& !isStandardTextRepresentationClass()) {
String thisCharset =
DataTransferer.canonicalName(getParameter("charset"));
DataTransferer.canonicalName(this.getParameter("charset"));
String thatCharset =
DataTransferer.canonicalName(that.getParameter("charset"));
if (thisCharset == null) {
if (thatCharset != null) {
return false;
}
} else {
if (!thisCharset.equals(thatCharset)) {
if (!Objects.equals(thisCharset, thatCharset)) {
return false;
}
}
}
if ("html".equals(getSubType()) &&
this.getParameter("document") != null )
{
if (!this.getParameter("document").
equals(that.getParameter("document")))
{
if ("html".equals(getSubType())) {
String thisDocument = this.getParameter("document");
String thatDocument = that.getParameter("document");
if (!Objects.equals(thisDocument, thatDocument)) {
return false;
}
}
......@@ -1094,20 +1091,23 @@ public class DataFlavor implements Externalizable, Cloneable {
// MimeType.match which reports a match if one or both of the
// subTypes is '*', regardless of the other subType.
if ("text".equals(primaryType) &&
DataTransferer.doesSubtypeSupportCharset(this) &&
representationClass != null &&
!(isRepresentationClassReader() ||
String.class.equals(representationClass) ||
isRepresentationClassCharBuffer() ||
char[].class.equals(representationClass)))
{
String charset =
DataTransferer.canonicalName(getParameter("charset"));
if ("text".equals(primaryType)) {
if (DataTransferer.doesSubtypeSupportCharset(this)
&& representationClass != null
&& !isStandardTextRepresentationClass()) {
String charset = DataTransferer.canonicalName(getParameter("charset"));
if (charset != null) {
total += charset.hashCode();
}
}
if ("html".equals(getSubType())) {
String document = this.getParameter("document");
if (document != null) {
total += document.hashCode();
}
}
}
}
return total;
......@@ -1181,6 +1181,20 @@ public class DataFlavor implements Externalizable, Cloneable {
return mimeType.match(mtype);
}
/**
* Checks if the representation class is one of the standard text
* representation classes.
*
* @return true if the representation class is one of the standard text
* representation classes, otherwise false
*/
private boolean isStandardTextRepresentationClass() {
return isRepresentationClassReader()
|| String.class.equals(representationClass)
|| isRepresentationClassCharBuffer()
|| char[].class.equals(representationClass);
}
/**
* Does the <code>DataFlavor</code> represent a serialized object?
*/
......
/*
* 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.
*/
import java.awt.datatransfer.DataFlavor;
/**
* @test
* @bug 8038999
* @summary DataFlavor.equals is not symmetric
* @author Petr Pchelko <petr.pchelko@oracle.com>
*/
public class EqualsHashCodeSymmetryTest {
private static final DataFlavor[] dataFlavors = {
DataFlavor.stringFlavor,
DataFlavor.imageFlavor,
DataFlavor.javaFileListFlavor,
DataFlavor.allHtmlFlavor,
DataFlavor.selectionHtmlFlavor,
DataFlavor.fragmentHtmlFlavor,
createFlavor("text/html; class=java.lang.String"),
new DataFlavor(String.class, "My test flavor number 1"),
new DataFlavor(String.class, "My test flavor number 2"),
new DataFlavor(StringBuilder.class, "My test flavor number 1")
};
public static void main(String[] args) {
testEqualsSymmetry();
testEqualsHashCodeConsistency();
testSimpleCollision();
}
private static void testEqualsSymmetry() {
for (DataFlavor flavor1 : dataFlavors) {
for (DataFlavor flavor2 : dataFlavors) {
if (flavor1.equals(flavor2) != flavor2.equals(flavor1)) {
throw new RuntimeException(
String.format("Equals is not symmetric for %s and %s", flavor1, flavor2));
}
}
}
}
private static void testEqualsHashCodeConsistency() {
for (DataFlavor flavor1 : dataFlavors) {
for (DataFlavor flavor2 : dataFlavors) {
if ((flavor1.equals(flavor2) && flavor1.hashCode() != flavor2.hashCode())) {
throw new RuntimeException(
String.format("Equals and hash code not consistent for %s and %s", flavor1, flavor2));
}
}
}
}
private static void testSimpleCollision() {
if (createFlavor("text/html; class=java.lang.String").hashCode() == DataFlavor.allHtmlFlavor.hashCode()) {
throw new RuntimeException("HashCode collision because the document parameter is not used");
}
}
private static DataFlavor createFlavor(String mime) {
try {
return new DataFlavor(mime);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册