提交 4d81c7c3 编写于 作者: M malenkov

8007458: [findbugs] One more beans issue, with ReflectionUtils

Reviewed-by: art, alexsch
上级 37787fe7
......@@ -604,7 +604,7 @@ public class XMLEncoder extends Encoder implements AutoCloseable {
return;
}
Class<?> primitiveType = ReflectionUtils.primitiveTypeFor(value.getClass());
Class<?> primitiveType = primitiveTypeFor(value.getClass());
if (primitiveType != null && target == value.getClass() &&
methodName.equals("new")) {
String primitiveTypeName = primitiveType.getName();
......@@ -778,4 +778,18 @@ public class XMLEncoder extends Encoder implements AutoCloseable {
indentation--;
writeln("</" + tag + ">");
}
@SuppressWarnings("rawtypes")
static Class primitiveTypeFor(Class wrapper) {
if (wrapper == Boolean.class) return Boolean.TYPE;
if (wrapper == Byte.class) return Byte.TYPE;
if (wrapper == Character.class) return Character.TYPE;
if (wrapper == Short.class) return Short.TYPE;
if (wrapper == Integer.class) return Integer.TYPE;
if (wrapper == Long.class) return Long.TYPE;
if (wrapper == Float.class) return Float.TYPE;
if (wrapper == Double.class) return Double.TYPE;
if (wrapper == Void.class) return Void.TYPE;
return null;
}
}
......@@ -30,8 +30,10 @@ import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.lang.reflect.Field;
abstract class AbstractTest<T> implements ExceptionListener {
private final BeanValidator validator = new BeanValidator();
final BeanValidator validator = new BeanValidator();
public final void exceptionThrown(Exception exception) {
throw new Error("unexpected exception", exception);
......@@ -59,7 +61,7 @@ abstract class AbstractTest<T> implements ExceptionListener {
}
/**
* This method should be overriden
* This method should be overridden
* if specified encoder should be initialized.
*
* @param encoder the XML encoder to initialize
......@@ -68,7 +70,7 @@ abstract class AbstractTest<T> implements ExceptionListener {
}
/**
* This method should be overriden
* This method should be overridden
* if specified decoder should be initialized.
*
* @param decoder the XML decoder to initialize
......@@ -77,7 +79,7 @@ abstract class AbstractTest<T> implements ExceptionListener {
}
/**
* This method should be overriden
* This method should be overridden
* for test-specific comparison.
*
* @param before the object before encoding
......@@ -134,6 +136,7 @@ abstract class AbstractTest<T> implements ExceptionListener {
private byte[] writeObject(Object object) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
XMLEncoder encoder = new XMLEncoder(output);
encoder.setExceptionListener(this);
initialize(encoder);
encoder.writeObject(object);
encoder.close();
......@@ -143,9 +146,24 @@ abstract class AbstractTest<T> implements ExceptionListener {
private Object readObject(byte[] array) {
ByteArrayInputStream input = new ByteArrayInputStream(array);
XMLDecoder decoder = new XMLDecoder(input);
decoder.setExceptionListener(this);
initialize(decoder);
Object object = decoder.readObject();
decoder.close();
return object;
}
static Field getField(String name) {
try {
int index = name.lastIndexOf('.');
String className = name.substring(0, index);
String fieldName = name.substring(1 + index);
Field field = Class.forName(className).getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}
catch (Exception exception) {
throw new Error(exception);
}
}
}
......@@ -63,6 +63,15 @@ final class BeanValidator {
}
Class type = object1.getClass();
if (!type.equals(object2.getClass())) {
// resolve different implementations of the Map.Entry interface
if ((object1 instanceof Map.Entry) && (object2 instanceof Map.Entry)) {
log("!!! special case", "Map.Entry");
Map.Entry entry1 = (Map.Entry) object1;
Map.Entry entry2 = (Map.Entry) object2;
validate(entry1.getKey(), entry2.getKey());
validate(entry1.getValue(), entry2.getValue());
return;
}
throw new IllegalStateException("could not compare objects with different types");
}
// validate elements of arrays
......@@ -82,10 +91,14 @@ final class BeanValidator {
}
return;
}
// special case for collections: do not use equals
boolean ignore = Collection.class.isAssignableFrom(type)
|| Map.Entry.class.isAssignableFrom(type)
|| Map.class.isAssignableFrom(type);
// validate objects using equals()
// we assume that the method equals(Object) can be called,
// if the class declares such method
if (isDefined(type, "equals", Object.class)) {
if (!ignore && isDefined(type, "equals", Object.class)) {
if (object1.equals(object2)) {
return;
}
......@@ -205,27 +218,7 @@ final class BeanValidator {
}
private void validate(Map map1, Map map2, boolean sorted) {
if (map1.size() != map2.size()) {
throw new IllegalStateException("could not compare maps with different sizes");
}
if (sorted) {
Iterator first = map1.entrySet().iterator();
Iterator second = map2.entrySet().iterator();
int index = 0;
while (first.hasNext() && second.hasNext()) {
log("validate map entry", Integer.valueOf(index++));
validate(first.next(), second.next());
}
if (first.hasNext() || second.hasNext()) {
throw new IllegalStateException("one map contains more entries than another one");
}
} else {
// assume that equals() can be used for keys
for (Object key : map1.keySet()) {
log("validate map value for key", key);
validate(map1.get(key), map2.get(key));
}
}
validate(map1.entrySet(), map2.entrySet(), sorted);
}
private boolean isCyclic(Object object1, Object object2) {
......
......@@ -28,7 +28,6 @@
* @author Sergey Malenkov, Mark Davidson
*/
import java.beans.XMLEncoder;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
......@@ -78,10 +77,6 @@ public abstract class Test4631471 extends AbstractTest {
// do not any validation
}
protected final void initialize(XMLEncoder encoder) {
encoder.setExceptionListener(this);
}
public static TreeNode getRoot() {
DefaultMutableTreeNode node = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode first = new DefaultMutableTreeNode("first");
......
......@@ -103,7 +103,6 @@ public class Test4679556 extends AbstractTest {
}
protected void initialize(XMLEncoder encoder) {
encoder.setExceptionListener(this);
encoder.setPersistenceDelegate(C.class, new DefaultPersistenceDelegate() {
protected Expression instantiate(Object oldInstance, Encoder out) {
C c = (C) oldInstance;
......
......@@ -68,11 +68,9 @@ public final class java_awt_BorderLayout extends AbstractTest<BorderLayout> {
@Override
protected void validate(BorderLayout before, BorderLayout after) {
super.validate(before, after);
BeanValidator validator = new BeanValidator();
for (String constraint : CONSTRAINTS) {
validator.validate(before.getLayoutComponent(constraint),
after.getLayoutComponent(constraint));
super.validator.validate(before.getLayoutComponent(constraint),
after.getLayoutComponent(constraint));
}
}
......
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* 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
......@@ -22,57 +20,64 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.beans;
/*
* @test
* @bug 8007458
* @summary Tests CardLayout encoding
* @author Sergey Malenkov
*/
import java.awt.CardLayout;
import java.lang.reflect.Field;
import java.util.Vector;
import javax.swing.JLabel;
/**
* A utility class for reflectively finding methods, constuctors and fields
* using reflection.
*/
class ReflectionUtils {
public final class java_awt_CardLayout extends AbstractTest<CardLayout> {
private static final Field VECTOR = getField("java.awt.CardLayout.vector");
private static final Field NAME = getField("java.awt.CardLayout$Card.name");
private static final Field COMP = getField("java.awt.CardLayout$Card.comp");
@SuppressWarnings("rawtypes")
public static boolean isPrimitive(Class type) {
return primitiveTypeFor(type) != null;
public static void main(String[] args) throws Exception {
new java_awt_CardLayout().test(true);
}
@SuppressWarnings("rawtypes")
public static Class primitiveTypeFor(Class wrapper) {
if (wrapper == Boolean.class) return Boolean.TYPE;
if (wrapper == Byte.class) return Byte.TYPE;
if (wrapper == Character.class) return Character.TYPE;
if (wrapper == Short.class) return Short.TYPE;
if (wrapper == Integer.class) return Integer.TYPE;
if (wrapper == Long.class) return Long.TYPE;
if (wrapper == Float.class) return Float.TYPE;
if (wrapper == Double.class) return Double.TYPE;
if (wrapper == Void.class) return Void.TYPE;
return null;
@Override
protected CardLayout getObject() {
CardLayout layout = new CardLayout();
layout.addLayoutComponent(new JLabel("a"), "a");
layout.addLayoutComponent(new JLabel("b"), "b");
layout.addLayoutComponent(new JLabel("c"), "c");
return layout;
}
/**
* Returns the value of a private field.
*
* @param instance object instance
* @param cls class
* @param name name of the field
* @param el an exception listener to handle exceptions; or null
* @return value of the field; null if not found or an error is encountered
*/
@SuppressWarnings("rawtypes")
public static Object getPrivateField(Object instance, Class cls,
String name, ExceptionListener el) {
@Override
protected CardLayout getAnotherObject() {
CardLayout layout = new CardLayout();
layout.addLayoutComponent(new JLabel("a"), "a");
layout.addLayoutComponent(new JLabel("b"), "b");
layout.addLayoutComponent(new JLabel("c"), "c");
layout.addLayoutComponent(new JLabel("d"), "d");
return layout;
}
@Override
protected void validate(CardLayout before, CardLayout after) {
super.validate(before, after);
try {
Field f = cls.getDeclaredField(name);
f.setAccessible(true);
return f.get(instance);
}
catch (Exception e) {
if (el != null) {
el.exceptionThrown(e);
Vector a = (Vector) VECTOR.get(after);
Vector b = (Vector) VECTOR.get(before);
int size = a.size();
if (size != b.size()) {
throw new Error("different content");
}
for (int i = 0; i < size; i++) {
super.validator.validate(NAME.get(a.get(i)), NAME.get(b.get(i)));
super.validator.validate(COMP.get(a.get(i)), COMP.get(b.get(i)));
}
}
catch (Exception exception) {
throw new Error(exception);
}
return null;
}
}
/*
* Copyright (c) 2013, 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 8007458
* @summary Tests GridBagLayout encoding
* @author Sergey Malenkov
*/
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Map;
import javax.swing.JLabel;
public final class java_awt_GridBagLayout extends AbstractTest<GridBagLayout> {
private static final Field HASHTABLE = getField("java.awt.GridBagLayout.comptable");
public static void main(String[] args) {
new java_awt_GridBagLayout().test(true);
}
@Override
protected GridBagLayout getObject() {
GridBagLayout layout = new GridBagLayout();
update(layout, "1", 1, 1);
update(layout, "2", 2, 2);
update(layout, "3", 3, 3);
return layout;
}
@Override
protected GridBagLayout getAnotherObject() {
GridBagLayout layout = new GridBagLayout();
update(layout, "11", 1, 1);
update(layout, "12", 1, 2);
update(layout, "21", 2, 1);
update(layout, "22", 2, 2);
return layout;
}
@Override
protected void validate(GridBagLayout before, GridBagLayout after) {
super.validate(before, after);
try {
Hashtable a = (Hashtable) HASHTABLE.get(after);
Hashtable b = (Hashtable) HASHTABLE.get(before);
super.validator.validate(a, b);
// for (int i = 0; i < size; i++) {
// validator.validate(NAME.get(a.get(i)), NAME.get(b.get(i)));
// validator.validate(COMP.get(a.get(i)), COMP.get(b.get(i)));
// }
}
catch (Exception exception) {
throw new Error(exception);
}
// for (String name : names) {
// validator.validate(getConstraints(before, name), getConstraints(after, name));
// }
}
private static void update(GridBagLayout layout, String id, int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
layout.addLayoutComponent(new JLabel(id), gbc);
}
/*
private static GridBagConstraints getConstraints(GridBagLayout layout, String id) {
return (layout == null) ? null : ((MyGridBagLayout) layout).getConstraints(id);
}
*/
}
......@@ -28,6 +28,7 @@
* @author Sergey Malenkov
*/
import java.beans.XMLEncoder;
import javax.swing.DefaultCellEditor;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
......@@ -46,6 +47,11 @@ public final class javax_swing_DefaultCellEditor extends AbstractTest<DefaultCel
// return new DefaultCellEditor(new JTextField("Second"));
}
@Override
protected void initialize(XMLEncoder encoder) {
encoder.setExceptionListener(null); // TODO: ignore non-public listener because of 4808251
}
protected void validate(DefaultCellEditor before, DefaultCellEditor after) {
String text = ((JTextComponent) after.getComponent()).getText();
if (!text.equals(((JTextComponent) before.getComponent()).getText()))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册